├── .github └── FUNDING.yml ├── .gitignore ├── ChangeLog ├── Makefile ├── README ├── README.linux-one ├── TODO ├── TODO.linux-one ├── debian ├── changelog ├── compat ├── control ├── copyright ├── docs ├── linux-fusion-dkms.dkms └── rules ├── doc ├── .cvsignore ├── Makefile ├── fusion.pdf ├── fusion.tmpl ├── libfusion.ps └── libfusion.texi ├── include └── linux │ └── one.h ├── linux ├── drivers │ └── char │ │ └── fusion │ │ ├── .cvsignore │ │ ├── .gitignore │ │ ├── Kconfig │ │ ├── Makefile-2.4 │ │ ├── Makefile-2.6 │ │ ├── call.c │ │ ├── call.h │ │ ├── debug.c │ │ ├── debug.h │ │ ├── entries.c │ │ ├── entries.h │ │ ├── fifo.c │ │ ├── fifo.h │ │ ├── fusioncore.h │ │ ├── fusiondev.c │ │ ├── fusiondev.h │ │ ├── fusionee.c │ │ ├── fusionee.h │ │ ├── hash.c │ │ ├── hash.h │ │ ├── list.c │ │ ├── list.h │ │ ├── property.c │ │ ├── property.h │ │ ├── reactor.c │ │ ├── reactor.h │ │ ├── ref.c │ │ ├── ref.h │ │ ├── shmpool.c │ │ ├── shmpool.h │ │ ├── single │ │ ├── fusioncore_impl.c │ │ └── fusioncore_impl.h │ │ ├── skirmish.c │ │ ├── skirmish.h │ │ └── types.h └── include │ └── linux │ └── fusion.h ├── one ├── .gitignore ├── Kconfig ├── Makefile-2.4 ├── Makefile-2.6 ├── OneTypes.h ├── app.c ├── app.h ├── debug.c ├── debug.h ├── entries.c ├── entries.h ├── fifo.c ├── fifo.h ├── list.c ├── list.h ├── one_udp.c ├── one_udp.h ├── onecore.h ├── onedev.c ├── onedev.h ├── packet.c ├── packet.h ├── queue.c ├── queue.h ├── single │ ├── onecore_impl.c │ └── onecore_impl.h ├── target.c ├── target.h └── types.h └── tests ├── .cvsignore ├── Makefile ├── calls.c ├── latency.c ├── throughput.c └── throughput_pipe.c /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: deniskropp -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.ko 2 | .*.ko.cmd 3 | *.mod.c 4 | *.o 5 | *.o.cmd 6 | .tmp_versions 7 | Module.symvers 8 | modules.order 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # for native builds: 2 | # make modules modules_install 3 | # make KERNELDIR= modules modules_install 4 | # make KERNEL_VERSION= modules modules_install 5 | # 6 | # for cross builds, using standard kernel make environment, i.e. 7 | # make KERNELDIR= INSTALL_MOD_PATH= modules modules_install 8 | 9 | KERNEL_VERSION ?= $(shell uname -r) 10 | INSTALL_MOD_PATH ?= / 11 | KERNELDIR ?= $(INSTALL_MOD_PATH)/lib/modules/$(KERNEL_VERSION)/build 12 | FUSIONCORE ?= single 13 | ONECORE ?= single 14 | 15 | export FUSIONCORE 16 | export ONECORE 17 | 18 | FUSION_CPPFLAGS += -DFUSION_CALL_INTERRUPTIBLE \ 19 | -I`pwd`/linux/drivers/char/fusion \ 20 | -I`pwd`/linux/drivers/char/fusion/multi \ 21 | -I`pwd`/linux/drivers/char/fusion/$(FUSIONCORE) 22 | 23 | ONE_CPPFLAGS += \ 24 | -I`pwd`/one \ 25 | -I`pwd`/one/$(ONECORE) \ 26 | -I`pwd`/include \ 27 | 28 | KERNEL_BUILD = $(KERNELDIR) 29 | # works for 2.6.23 30 | KERNEL_SOURCE = $(shell grep ^KERNELSRC $(KERNEL_BUILD)/Makefile | cut -d ' ' -f 6) 31 | ifeq ($(KERNEL_SOURCE), ) 32 | # works for 2.6.32 33 | KERNEL_SOURCE = $(shell grep '^MAKEARGS := -C ' $(KERNEL_BUILD)/Makefile | cut -d ' ' -f 4) 34 | endif 35 | ifneq ($(KERNEL_SOURCE), ) 36 | K_VERSION = $(shell grep '^VERSION =' $(KERNEL_SOURCE)/Makefile | cut -d ' ' -f 3) 37 | K_PATCHLEVEL = $(shell grep '^PATCHLEVEL =' $(KERNEL_SOURCE)/Makefile | cut -d ' ' -f 3) 38 | K_SUBLEVEL = $(shell grep '^SUBLEVEL =' $(KERNEL_SOURCE)/Makefile | cut -d ' ' -f 3) 39 | else 40 | K_VERSION = $(shell grep '^VERSION =' $(KERNEL_BUILD)/Makefile | cut -d ' ' -f 3) 41 | K_PATCHLEVEL = $(shell grep '^PATCHLEVEL =' $(KERNEL_BUILD)/Makefile | cut -d ' ' -f 3) 42 | K_SUBLEVEL = $(shell grep '^SUBLEVEL =' $(KERNEL_BUILD)/Makefile | cut -d ' ' -f 3) 43 | endif 44 | 45 | FUSION_SUB = linux/drivers/char/fusion 46 | ONE_SUB = one 47 | SUBMOD = drivers/char/fusion 48 | 49 | export CONFIG_FUSION_DEVICE=m 50 | export CONFIG_LINUX_ONE=m 51 | 52 | ifeq ($(DEBUG),yes) 53 | FUSION_CPPFLAGS += -DFUSION_DEBUG_SKIRMISH_DEADLOCK -DFUSION_ENABLE_DEBUG 54 | ONE_CPPFLAGS += -DONE_ENABLE_DEBUG 55 | endif 56 | 57 | ifeq ($(shell test -e $(KERNEL_BUILD)/include/linux/autoconf.h && echo yes),yes) 58 | AUTOCONF_H = -include $(KERNEL_BUILD)/include/linux/autoconf.h 59 | endif 60 | 61 | ifeq ($(shell test -e $(KERNEL_BUILD)/include/linux/config.h && echo yes),yes) 62 | CPPFLAGS += -DHAVE_LINUX_CONFIG_H 63 | endif 64 | 65 | ifeq ($(K_VERSION),3) 66 | KMAKEFILE = Makefile-2.6 67 | else 68 | KMAKEFILE = Makefile-2.$(K_PATCHLEVEL) 69 | endif 70 | 71 | check-version = $(shell expr \( $(K_VERSION) \* 65536 + $(K_PATCHLEVEL) \* 256 + $(K_SUBLEVEL) \) \>= \( $(1) \* 65536 + $(2) \* 256 + $(3) \)) 72 | 73 | ifeq ($(call check-version,2,6,24),1) 74 | FUSION_EXTRAFLAGS = KCPPFLAGS="$(CPPFLAGS) $(FUSION_CPPFLAGS) -I`pwd`/linux/include" INSTALL_MOD_DIR="$(SUBMOD)" 75 | ONE_EXTRAFLAGS = KCPPFLAGS="$(CPPFLAGS) $(ONE_CPPFLAGS) -I`pwd`/linux/include" INSTALL_MOD_DIR="$(SUBMOD)" 76 | else 77 | FUSION_EXTRAFLAGS = CPPFLAGS="$(CPPFLAGS) $(FUSION_CPPFLAGS) -D__KERNEL__ -I`pwd`/linux/include -I$(KERNEL_BUILD)/include -I$(KERNEL_BUILD)/include2 -I$(KERNEL_SOURCE)/include $(AUTOCONF_H)" 78 | ONE_EXTRAFLAGS = CPPFLAGS="$(CPPFLAGS) $(ONE_CPPFLAGS) -D__KERNEL__ -I`pwd`/linux/include -I$(KERNEL_BUILD)/include -I$(KERNEL_BUILD)/include2 -I$(KERNEL_SOURCE)/include $(AUTOCONF_H)" 79 | endif 80 | 81 | .PHONY: all modules modules_install install clean 82 | 83 | all: modules 84 | install: modules_install headers_install 85 | 86 | modules: 87 | rm -f $(FUSION_SUB)/Makefile 88 | rm -f $(ONE_SUB)/Makefile 89 | cp $(FUSION_SUB)/$(KMAKEFILE) $(FUSION_SUB)/Makefile 90 | cp $(ONE_SUB)/$(KMAKEFILE) $(ONE_SUB)/Makefile 91 | echo kernel is in $(KERNEL_SOURCE) and version is $(K_SUBLEVEL), building module in $(FUSION_SUB) 92 | $(MAKE) -C $(KERNEL_BUILD) \ 93 | $(FUSION_EXTRAFLAGS) \ 94 | SUBDIRS=`pwd`/$(FUSION_SUB) modules 95 | echo kernel is in $(KERNEL_SOURCE) and version is $(K_SUBLEVEL), building module in $(ONE_SUB) 96 | $(MAKE) -C $(KERNEL_BUILD) \ 97 | $(ONE_EXTRAFLAGS) \ 98 | SUBDIRS=`pwd`/$(ONE_SUB) modules 99 | 100 | modules_install: modules 101 | ifeq ($(K_VERSION)$(K_PATCHLEVEL),24) 102 | install -d $(INSTALL_MOD_PATH)/lib/modules/$(KERNEL_VERSION)/drivers/char/fusion 103 | install -m 644 linux/drivers/char/fusion/fusion.o $(INSTALL_MOD_PATH)/lib/modules/$(KERNEL_VERSION)/drivers/char/fusion 104 | install -m 644 one/linux-one.o $(INSTALL_MOD_PATH)/lib/modules/$(KERNEL_VERSION)/drivers/char/fusion 105 | rm -f $(INSTALL_MOD_PATH)/lib/modules/$(KERNEL_VERSION)/fusion.o 106 | rm -f $(INSTALL_MOD_PATH)/lib/modules/$(KERNEL_VERSION)/linux-one.o 107 | /sbin/depmod -ae -b $(INSTALL_MOD_PATH) $(KERNEL_VERSION) 108 | else 109 | $(MAKE) -C $(KERNEL_BUILD) \ 110 | $(FUSION_EXTRAFLAGS) \ 111 | SUBDIRS=`pwd`/$(FUSION_SUB) modules_install 112 | $(MAKE) -C $(KERNEL_BUILD) \ 113 | $(ONE_EXTRAFLAGS) \ 114 | SUBDIRS=`pwd`/$(ONE_SUB) modules_install 115 | endif 116 | 117 | headers_install: 118 | install -d $(INSTALL_MOD_PATH)/usr/include/linux 119 | install -m 644 linux/include/linux/fusion.h $(INSTALL_MOD_PATH)/usr/include/linux 120 | install -m 644 include/linux/one.h $(INSTALL_MOD_PATH)/usr/include/linux 121 | 122 | 123 | 124 | clean: 125 | find $(FUSION_SUB) \( -name .git -prune \ 126 | -o -name *.o -o -name *.ko -o -name .*.o.cmd \ 127 | -o -name fusion.mod.* -o -name .fusion.* \ 128 | -o -name Module.symvers -o -name modules.order \) \ 129 | -type f -print | xargs rm -f 130 | find $(FUSION_SUB) -name .tmp_versions -type d -print | xargs rm -rf 131 | rm -f $(FUSION_SUB)/Makefile 132 | find $(ONE_SUB) \( -name .git -prune \ 133 | -o -name *.o -o -name *.ko -o -name .*.o.cmd \ 134 | -o -name fusion.mod.* -o -name .fusion.* \ 135 | -o -name Module.symvers -o -name modules.order \) \ 136 | -type f -print | xargs rm -f 137 | find $(ONE_SUB) -name .tmp_versions -type d -print | xargs rm -rf 138 | rm -f $(ONE_SUB)/Makefile 139 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Easy installation without kernel patch 2 | -------------------------------------- 3 | 4 | 1) Run 'make' and 'make install'. It builds and installs the module 5 | for the running kernel version as reported by 'uname -r'. 6 | If you want to build for another kernel, edit the Makefile. 7 | 8 | 2) Either run 'modprobe fusion' manually or add "fusion" to "/etc/modules". 9 | 10 | 3) Create the fusion device(s) if not using devfs or udev: 11 | 12 | mkdir /dev/fusion 13 | mknod /dev/fusion/0 c 250 0 14 | 15 | ...if you need more than one session 16 | 17 | mknod /dev/fusion/1 c 250 1 18 | mknod /dev/fusion/2 c 250 2 19 | 20 | ...and so on (currently limited to eight sessions) 21 | 22 | 4) Add udev rules to /etc/udev/rules.d/40-fusion.rules if using udev: 23 | 24 | KERNEL=="fusion[0-9]*", NAME="fusion/%n", GROUP="video", MODE="0660" 25 | 26 | ...customize to suit your needs 27 | 28 | 29 | Special arguments for cross builds 30 | ---------------------------------- 31 | 32 | 1) Simple example: 33 | 34 | make KERNEL_VERSION=2.6.25.4 SYSROOT=/opt/sh7723 install 35 | 36 | 2) Explicit source tree: 37 | 38 | make KERNEL_VERSION=2.6.25.4 SYSROOT=/opt/sh7723 KERNEL_BUILD=/home/sh7723/kernel install 39 | -------------------------------------------------------------------------------- /README.linux-one: -------------------------------------------------------------------------------- 1 | Easy installation without kernel patch 2 | -------------------------------------- 3 | 4 | 1) Run 'make' and 'make install'. It builds and installs the module 5 | for the running kernel version as reported by 'uname -r'. 6 | If you want to build for another kernel, edit the Makefile. 7 | 8 | 2) Either run 'modprobe one' manually or add "one" to "/etc/modules". 9 | 10 | 3) Create the one device(s) if not using devfs or udev: 11 | 12 | mkdir /dev/one 13 | mknod /dev/one/0 c 250 0 14 | 15 | ...if you need more than one session 16 | 17 | mknod /dev/one/1 c 250 1 18 | mknod /dev/one/2 c 250 2 19 | 20 | ...and so on (currently limited to eight sessions) 21 | 22 | 4) Add udev rules to /etc/udev/rules.d/40-one.rules if using udev: 23 | 24 | KERNEL=="one[0-9]*", NAME="one/%n", GROUP="video", MODE="0660" 25 | 26 | ...customize to suit your needs 27 | 28 | 29 | Special arguments for cross builds 30 | ---------------------------------- 31 | 32 | 1) Simple example: 33 | 34 | make -f Makefile.static KERNEL_VERSION=2.6.25.4 SYSROOT=/opt/sh7723 install 35 | 36 | 2) Explicit source tree: 37 | 38 | make -f Makefile.static KERNEL_VERSION=2.6.25.4 SYSROOT=/opt/sh7723 KERNEL_BUILD=/home/sh7723/kernel install 39 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Improve performance by using a hash table or a faster approach 2 | for looking up ids. Currently an automatic "move-to-front-when-accessed" 3 | mechanism is implemented. 4 | 5 | Output more information in /proc/fusion. 6 | 7 | Improve performance (especially message throughput) by avoiding kmalloc. 8 | 9 | Implement defering/blocking of SIGSTOP while a Skirmish is locked 10 | by the process. This will avoid rare deadlocks when pressing Ctrl-Z 11 | in the terminal where a DirectFB slave application has been started. 12 | 13 | Revert semaphores to spinlocks where possible. 14 | 15 | Implement user space based skirmish_prevail()/dismiss() for the 16 | uncontended case, similar to futexes. 17 | 18 | Fix types. 19 | 20 | Add timeout to throw/catch of refs. 21 | -------------------------------------------------------------------------------- /TODO.linux-one: -------------------------------------------------------------------------------- 1 | 2 | 3 | Remove packet size limit, splitting up if needed. 4 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | linux-fusion (9.0.2-1) unstable; urgency=low 2 | 3 | * new upstream version 4 | 5 | -- Andreas Shimokawa Fri, 15 Jul 2013 11:31:12 +0200 6 | 7 | linux-fusion (9.0.1-1) unstable; urgency=high 8 | 9 | * new upstream version 10 | 11 | -- Andreas Shimokawa Fri, 05 Jul 2013 17:23:13 +0200 12 | 13 | linux-fusion (9.0.0-2) unstable; urgency=high 14 | 15 | * inclcude one.h 16 | 17 | -- Andreas Shimokawa Fri, 18 Jan 2013 21:21:23 +0200 18 | 19 | linux-fusion (9.0.0-1) unstable; urgency=high 20 | 21 | * new upstream version 22 | 23 | -- Andreas Shimokawa Tue, 15 Jan 2013 11:33:51 +0200 24 | 25 | linux-fusion (8.10.4-2) unstable; urgency=high 26 | 27 | * include linux-one 28 | 29 | -- Andreas Shimokawa Tue, 23 Okt 2012 11:46:59 +0200 30 | 31 | linux-fusion (8.10.4-1) unstable; urgency=high 32 | 33 | * new upstream version (8.10.4) 34 | 35 | -- Andreas Shimokawa Thu, 13 Sep 2012 14:46:51 +0200 36 | 37 | linux-fusion (8.10.3-1) unstable; urgency=high 38 | 39 | * new upstream version (8.10.3) 40 | 41 | -- Andreas Shimokawa Thu, 25 Jul 2012 19:28:50 +0200 42 | 43 | linux-fusion (8.10.2-1) unstable; urgency=high 44 | 45 | * new upstream version (8.10.2) 46 | 47 | -- Andreas Shimokawa Thu, 29 Jun 2012 15:39:51 +0200 48 | 49 | linux-fusion (8.10.1-1) unstable; urgency=high 50 | 51 | * new upstream version (8.10.1) 52 | 53 | -- Andreas Shimokawa Thu, 14 Jun 2012 17:49:59 +0200 54 | 55 | linux-fusion (8.9.0-1) unstable; urgency=high 56 | 57 | * new upstream version (8.9.0) 58 | 59 | -- Andreas Shimokawa Tue, 22 May 2012 18:24:35 +0200 60 | 61 | linux-fusion (8.8.1-1) unstable; urgency=high 62 | 63 | * new upstream version (8.8.1) 64 | 65 | -- Andreas Shimokawa Tue, 20 Mar 2012 16:12:55 +0200 66 | 67 | linux-fusion (8.7.0-1) unstable; urgency=high 68 | 69 | * new upstream version (8.7.0) 70 | 71 | -- Andreas Shimokawa Mon, 26 Sep 2011 11:23:17 +0200 72 | 73 | linux-fusion (8.5.2-1) unstable; urgency=high 74 | 75 | * new upstream version (8.5.2) 76 | 77 | -- Andreas Shimokawa Tue, 20 Sep 2011 13:29:17 +0200 78 | 79 | linux-fusion (8.5.1-1) unstable; urgency=high 80 | 81 | * new upstream version (8.5.1) 82 | 83 | -- Andreas Shimokawa Fri, 29 Jul 2011 18:29:17 +0200 84 | 85 | linux-fusion (8.5.0-1) unstable; urgency=high 86 | 87 | * new upstream version (8.5.0) 88 | 89 | -- Andreas Shimokawa Fri, 29 Jul 2011 12:24:58 +0200 90 | 91 | linux-fusion (8.4.0-1) unstable; urgency=high 92 | 93 | * new upstream version (8.4.0) 94 | 95 | -- Andreas Shimokawa Tue, 12 Jul 2011 11:20:48 +0200 96 | 97 | linux-fusion (8.3.1-1) unstable; urgency=high 98 | 99 | * new upstream version (8.3.1) 100 | 101 | -- Andreas Shimokawa Sat, 09 Apr 2011 18:02:48 +0200 102 | 103 | linux-fusion (8.3.0-2) unstable; urgency=high 104 | 105 | * new upstream version (8.3.0 final) 106 | 107 | -- Andreas Shimokawa Tue, 30 Mar 2011 13:02:48 +0200 108 | 109 | linux-fusion (8.3.0-1) unstable; urgency=low 110 | 111 | * Initial package version 112 | 113 | -- Andreas Shimokawa Tue, 22 Mar 2011 13:02:48 +0200 114 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: linux-fusion 2 | Section: kernel 3 | Priority: extra 4 | Maintainer: Andreas Shimokawa 5 | Uploaders: Andreas Shimokawa 6 | Dm-Upload-Allowed: yes 7 | Homepage: http://www.directfb.org/ 8 | Standards-Version: 3.8.4 9 | Build-Depends: debhelper (>= 7), dkms (>= 2.1.1.1-2) 10 | Build-Depends-Indep: bzip2 11 | 12 | Package: linux-fusion-dkms 13 | Architecture: all 14 | Depends: ${misc:Depends} 15 | Description: DKMS Source for the linux-fusion kernel module 16 | This package contains the source for the linux-fusion kernel modules, 17 | packaged with approriate configuration for DKMS to build new modules 18 | dynamically. 19 | linux-fusion is required for DirectFB multi-application core 20 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | This program is free software; you can redistribute it and/or modify 2 | it under the terms of the GNU General Public License as published by 3 | the Free Software Foundation; version 2 dated June, 1991. 4 | 5 | This program is distributed in the hope that it will be useful, 6 | but WITHOUT ANY WARRANTY; without even the implied warranty of 7 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8 | GNU General Public License for more details. 9 | 10 | You should have received a copy of the GNU General Public License 11 | along with this program; if not, write to the Free Software 12 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 13 | 02110-1301 USA 14 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README 2 | TODO 3 | doc/fusion.pdf 4 | -------------------------------------------------------------------------------- /debian/linux-fusion-dkms.dkms: -------------------------------------------------------------------------------- 1 | # DKMS configuration for the linux-fusion kernel module. -*- sh -*- 2 | 3 | # The version is replaced at build time by debian/rules. 4 | PACKAGE_NAME='linux-fusion' 5 | PACKAGE_VERSION="#MODULE_VERSION#" 6 | 7 | BUILT_MODULE_NAME[0]=fusion 8 | DEST_MODULE_LOCATION[0]="/kernel/drivers/char/" 9 | BUILT_MODULE_LOCATION[0]="linux/drivers/char/fusion" 10 | BUILT_MODULE_NAME[1]=linux-one 11 | DEST_MODULE_LOCATION[1]="/kernel/drivers/char/" 12 | BUILT_MODULE_LOCATION[1]="one" 13 | AUTOINSTALL=yes 14 | 15 | MAKE[0]="make KERNELDIR=${kernel_source_dir} BUILD_DIR=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" 16 | CLEAN="make KERNELDIR=${kernel_source_dir} BUILD_DIR=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean" 17 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | # 9 | # This version is for a hypothetical package that can build a kernel modules 10 | # architecture-dependant package via make-kpkg, as well as an 11 | # architecture-independent module source package, and other packages 12 | # either dep/indep for things like common files or userspace components 13 | # needed for the kernel modules. 14 | 15 | # Uncomment this to turn on verbose mode. 16 | #export DH_VERBOSE=1 17 | 18 | # some default definitions, important! 19 | # 20 | # Name of the source package 21 | dkmssource:=linux-fusion-dkms 22 | 23 | # The short upstream name, used for the module source directory 24 | sname:=linux-fusion 25 | 26 | version:= $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2 \ 27 | | cut -d- -f1) 28 | 29 | 30 | k = $(shell echo $(KVERS) | grep -q ^2.6 && echo k) 31 | 32 | 33 | build: 34 | 35 | clean: 36 | dh_testdir 37 | dh_testroot 38 | 39 | # Add here commands to clean up after the build process. 40 | # 41 | # clean can be run from module assistant or the original package rules file. 42 | 43 | dh_clean 44 | 45 | install: DH_OPTIONS= 46 | install: build 47 | dh_testdir 48 | dh_testroot 49 | dh_prep 50 | dh_installdirs 51 | dh_installdocs 52 | 53 | ############################# 54 | # setup linux-fusion-source # 55 | ############################# 56 | # Create the directories to install the source into 57 | dh_installdirs -p$(dkmssource) usr/src/$(sname)-$(version) 58 | 59 | # Copy only the driver source to the proper location 60 | cp -r include one linux Makefile \ 61 | debian/$(dkmssource)/usr/src/$(sname)-$(version) 62 | # Copy the needed debian/ pieces to the proper location 63 | 64 | mkdir -p debian/$(dkmssource)/usr/share/doc/$(dkmssource) 65 | cp debian/copyright debian/$(dkmssource)/usr/share/doc/$(dkmssource) 66 | 67 | mkdir -p debian/$(dkmssource)/usr/include/linux 68 | cp linux/include/linux/fusion.h debian/$(dkmssource)/usr/include/linux/ 69 | cp include/linux/one.h debian/$(dkmssource)/usr/include/linux/ 70 | cp debian/copyright debian/$(dkmssource)/usr/share/doc/$(dkmssource) 71 | 72 | dh_dkms -V 73 | dh_install 74 | 75 | # Build architecture-independent files here. 76 | # Pass -i to all debhelper commands in this target to reduce clutter. 77 | binary-indep: build install 78 | dh_testdir -i 79 | dh_testroot -i 80 | dh_installchangelogs -i ChangeLog 81 | dh_installman -i 82 | dh_link -i 83 | dh_compress -i 84 | dh_fixperms -i 85 | dh_installdeb -i 86 | dh_installdeb -i 87 | dh_gencontrol -i 88 | dh_md5sums -i 89 | dh_builddeb -i 90 | 91 | # Build architecture-dependent files here. 92 | binary-arch: 93 | 94 | binary: clean binary-indep 95 | 96 | .PHONY: build clean binary-indep binary-arch binary install kdist kdist_configure kdist_image kdist_clean 97 | -------------------------------------------------------------------------------- /doc/.cvsignore: -------------------------------------------------------------------------------- 1 | fusion.aux 2 | fusion.cp 3 | fusion.fn 4 | fusion.ky 5 | fusion.log 6 | fusion.pg 7 | fusion.toc 8 | fusion.tp 9 | fusion.vr 10 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | all: libfusion.ps fusion.pdf 2 | 3 | # common 4 | 5 | clean: 6 | rm -rf libfusion.t2d 7 | 8 | extra-clean: clean 9 | rm -f libfusion.dvi libfusion.ps fusion.pdf 10 | 11 | .PHONY: clean extra-clean 12 | 13 | # for libfusion 14 | 15 | libfusion.ps: libfusion.dvi 16 | dvips libfusion.dvi 17 | 18 | libfusion.dvi: libfusion.texi 19 | texi2dvi --tidy libfusion.texi 20 | 21 | # for fusion.tmpl 22 | 23 | %.xml: %.tmpl 24 | #./docproc doc $< >$@ 25 | cp $< $@ 26 | 27 | %.pdf : %.xml 28 | db2pdf -o $(dir $@) $< 29 | 30 | -------------------------------------------------------------------------------- /doc/fusion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniskropp/linux-fusion/9c0013d066de179ec6ba6135d8f5e5b37af8b736/doc/fusion.pdf -------------------------------------------------------------------------------- /doc/libfusion.texi: -------------------------------------------------------------------------------- 1 | \input texinfo 2 | @c %**start of header 3 | @c Copyright 2003 Denis Oliver Kropp 4 | @c Licensed under the Gnu Public License, Version 2 5 | @c 6 | @c Fusion IPC 7 | @c 8 | @setfilename fusion.info 9 | @settitle Fusion 10 | @paragraphindent 0 11 | @c %**end of header 12 | 13 | @titlepage 14 | @title Fusion 15 | @subtitle High level IPC 16 | @subtitle July 2003 17 | @author by Denis Oliver Kropp 18 | @end titlepage 19 | 20 | @contents 21 | 22 | @chapter Introduction 23 | 24 | @section What is Fusion? 25 | 26 | Fusion is a high level IPC API providing mechanisms 27 | for master/slave environments. 28 | 29 | @section Master/Slave vs. Client/Server 30 | 31 | In client/server environments clients delegate every operation 32 | to the server which has sole access to shared resources. 33 | Such environments suffer from the overhead caused by 34 | 35 | @itemize @bullet 36 | @item Command encoding and decoding 37 | @item Transport of command packets 38 | @item Transport of data referenced by commands 39 | @item Context switches between client and server processes 40 | @item Strict seperation of client and server implementation 41 | @end itemize 42 | 43 | The master/slave approach eliminates this overhead by virtually 44 | merging the processes at the lower level of their implementation. 45 | This way of making multiple processes look like multiple threads 46 | gave Fusion its name and includes 47 | 48 | @itemize @bullet 49 | @item Shared memory for data normally held solely by the server 50 | @item High level messaging for virtually local event handlers and callbacks 51 | @item Advanced locking techniques for synchronization and access control 52 | @item Framework for distributed allocation and cleanup of resources 53 | @end itemize 54 | 55 | 56 | 57 | @chapter Design 58 | 59 | This chapter explains some fundamental concepts of Fusion. 60 | 61 | 62 | @section Shared memory 63 | 64 | Shared memory provides direct access for all processes to many kinds of 65 | shared information, including structures, lists and data. It's also used by 66 | the user space part of Fusion itself. 67 | 68 | Fusion's shared memory has the following special features 69 | 70 | @itemize @bullet 71 | @item Shared memory is mapped to the same virtual address in all processes 72 | to enable pointers within shared memory pointing to other locations 73 | in shared memory 74 | @item Allocation and deallocation of shared memory blocks is provided by an API 75 | that is equivalent to the libc malloc(), realloc(), free() etc. 76 | @end itemize 77 | 78 | 79 | @section Arena 80 | 81 | The first process in a master/slave environment initializes the session while 82 | additional processes simply join. The Fusion Arena represents such an 83 | environment and defines the role of each entering process. Each Arena is 84 | identified by a name which is specified when the Arena is entered. If the Arena 85 | doesn't exist yet, the process becomes the master and initializes the rest of 86 | the environment. Otherwise the process becomes a slave and joins the environment 87 | running the local setup only. 88 | 89 | The Fusion Arena also provides "fields" which are basically pairs of a string 90 | and a shared memory pointer. These fields are used to register entry points 91 | to the shared memory for each part of the environment during its initialization. 92 | They are looked up by their name when the environment is being joined by another 93 | process. 94 | 95 | The exit mechanism is similar to the enter mechanism. If the exiting process 96 | is the last one, it does a complete shutdown, otherwise it simply leaves. The 97 | master may reject to leave the environment before all slaves did. In this case 98 | the exit fails and the master can notify the user, wait for all slaves or kill 99 | them. 100 | 101 | 102 | @section Skirmish 103 | @section Reference counter 104 | @section Reactor 105 | @section Object 106 | @section Property 107 | @section Messages 108 | @section Call 109 | 110 | 111 | 112 | @chapter Implementation 113 | 114 | @section Kernel space 115 | 116 | @subsection Skirmish 117 | @subsection Reference counter 118 | @subsection Property 119 | 120 | 121 | @section Kernel/user space 122 | 123 | @subsection Messages 124 | @subsection Call 125 | @subsection Reactor 126 | 127 | 128 | @section User space 129 | 130 | @subsection POSIX shared memory 131 | @subsection Arena 132 | @subsection Object 133 | 134 | 135 | @bye 136 | -------------------------------------------------------------------------------- /include/linux/one.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __LINUX__ONE_H__ 13 | #define __LINUX__ONE_H__ 14 | 15 | #include 16 | 17 | #ifndef __KERNEL__ 18 | #include 19 | #endif 20 | 21 | #include 22 | 23 | /* One supports all API versions up to this version */ 24 | #define ONE_API_MAJOR_PROVIDED 1 25 | #define ONE_API_MINOR_PROVIDED 0 26 | #define ONE_API_MICRO_PROVIDED 0 27 | 28 | /* 29 | * One Kernel Device API Version 30 | * Default behaviour: 1.0.0 31 | */ 32 | #ifndef ONE_API_MAJOR 33 | #undef ONE_API_MAJOR 34 | #undef ONE_API_MINOR 35 | #undef ONE_API_MICRO 36 | #define ONE_API_MAJOR 1 37 | #define ONE_API_MINOR 0 38 | #define ONE_API_MICRO 0 39 | #endif 40 | 41 | 42 | #define ONE_MAX_PACKET_SIZE 32768 // FIXME: move to kernel module and report to user space via ENTER ioctl 43 | 44 | 45 | /* 46 | * The One ID is a unique identifier for one process. 47 | */ 48 | typedef uint32_t OneID; 49 | 50 | 51 | /* 52 | * Entering a world 53 | * API version (major/minor): master determines API of this world. slave has to follow. 54 | * supported are API 3.x for DirectFB 1.0.x, API 4.x for DirectFB 1.1.x, and API 8.x for DirectFB 1.2.x and beyond. 55 | */ 56 | typedef struct { 57 | struct { 58 | int major; 59 | int minor; 60 | } api; 61 | 62 | OneID one_id; 63 | } OneEnter; 64 | 65 | 66 | 67 | /* 68 | * Create a queue 69 | */ 70 | typedef struct { 71 | OneQueueFlags flags; /* Queue Flags */ 72 | 73 | OneQID queue_id; /* New Queue ID, if zero the new ID will be allocated, otherwise it fails if the ID is already used */ 74 | } OneQueueNew; 75 | 76 | 77 | /* 78 | * Destroy a queue 79 | */ 80 | typedef struct { 81 | OneQID queue_id; /* Queue ID */ 82 | } OneQueueDestroy; 83 | 84 | 85 | /* 86 | * Attach to a virtual queue 87 | */ 88 | typedef struct { 89 | OneQID queue_id; /* (Virtual) Queue ID, the one to attach to */ 90 | 91 | OneQID target_id; /* Target Queue ID, the one being attached */ 92 | } OneQueueAttach; 93 | 94 | /* 95 | * Detach from a virtual queue 96 | */ 97 | typedef struct { 98 | OneQID queue_id; /* (Virtual) Queue ID, the one to detach from */ 99 | 100 | OneQID target_id; /* Target Queue ID, the one being detached */ 101 | } OneQueueDetach; 102 | 103 | 104 | /* 105 | * Dispatch a packet 106 | */ 107 | typedef struct { 108 | OnePacketHeader header; /* Packet Header */ 109 | 110 | const struct iovec *iov; /* iovec as for writev() */ 111 | size_t iov_count; /* iovec count as for writev() */ 112 | } OneQueueDispatch; 113 | 114 | 115 | /* 116 | * Receive packets 117 | */ 118 | typedef struct { 119 | const OneQID *ids; /* Queue IDs for which to receive */ 120 | size_t ids_count; /* Number of IDs */ 121 | 122 | const struct iovec *iov; /* iovec as for readv() */ 123 | size_t iov_count; /* iovec count as for readv() */ 124 | 125 | int timeout_ms; /* Optional timeout, 0 = no timeout, -1 = return immediately if nothing to receive */ 126 | 127 | size_t ret_received; /* Number of bytes received in total (headers and data) */ 128 | } OneQueueReceive; 129 | 130 | 131 | /* 132 | * Dispatch and receive packets 133 | */ 134 | typedef struct { 135 | OneQueueDispatch *dispatch; /* Dispatch commands (like multiple OneQueueDispatch) */ 136 | size_t dispatch_count; /* Number of Dispatch (in case of error changed to number of successful dispatch) */ 137 | 138 | OneQueueReceive receive; /* Receive command (like OneQueueReceive after dispatch is done) */ 139 | } OneQueueDispatchReceive; 140 | 141 | 142 | /* 143 | * Wake up receivers of queues (threads of calling process) 144 | */ 145 | typedef struct { 146 | const OneQID *ids; /* Queue IDs for which to wake up any receivers */ 147 | size_t ids_count; /* Number of IDs */ 148 | } OneQueueWakeUp; 149 | 150 | 151 | 152 | /* 153 | * One types 154 | */ 155 | typedef enum { 156 | ONE_LOUNGE, 157 | ONE_QUEUE, 158 | } OneType; 159 | 160 | /* 161 | * Set attributes like 'name' for an entry of the specified type. 162 | */ 163 | #define ONE_ENTRY_INFO_NAME_LENGTH 24 164 | 165 | typedef struct { 166 | OneType type; 167 | uint32_t id; 168 | 169 | char name[ONE_ENTRY_INFO_NAME_LENGTH]; 170 | } OneEntryInfo; 171 | 172 | 173 | #define ONE_ENTER _IOR (ONE_LOUNGE, 0x00, OneEnter) 174 | #define ONE_SYNC _IO (ONE_LOUNGE, 0x01) 175 | 176 | #define ONE_ENTRY_SET_INFO _IOW (ONE_LOUNGE, 0x02, OneEntryInfo) 177 | #define ONE_ENTRY_GET_INFO _IOW (ONE_LOUNGE, 0x03, OneEntryInfo) 178 | 179 | 180 | #define ONE_QUEUE_NEW _IOWR(ONE_QUEUE, 0x00, OneQueueNew) 181 | #define ONE_QUEUE_DESTROY _IOW (ONE_QUEUE, 0x01, OneQueueDestroy) 182 | #define ONE_QUEUE_ATTACH _IOW (ONE_QUEUE, 0x02, OneQueueAttach) 183 | #define ONE_QUEUE_DETACH _IOW (ONE_QUEUE, 0x03, OneQueueDetach) 184 | #define ONE_QUEUE_DISPATCH _IOW (ONE_QUEUE, 0x04, OneQueueDispatch) 185 | #define ONE_QUEUE_RECEIVE _IOWR(ONE_QUEUE, 0x05, OneQueueReceive) 186 | #define ONE_QUEUE_DISPATCH_RECEIVE _IOWR(ONE_QUEUE, 0x06, OneQueueDispatchReceive) 187 | #define ONE_QUEUE_WAKEUP _IOW (ONE_QUEUE, 0x07, OneQueueWakeUp) 188 | 189 | #endif 190 | 191 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/.cvsignore: -------------------------------------------------------------------------------- 1 | *.o.flags 2 | *.cmd 3 | Makefile 4 | fusion.ko 5 | fusion.mod.c 6 | .tmp_versions 7 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/Kconfig: -------------------------------------------------------------------------------- 1 | config FUSION_DEVICE 2 | tristate "Fusion Kernel Device" 3 | ---help--- 4 | Fusion is the IPC API used by DirectFB and FusionSound. 5 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/Makefile-2.4: -------------------------------------------------------------------------------- 1 | O_TARGET := fusion.o 2 | 3 | obj-y := $(FUSIONCORE)/fusioncore_impl.o call.o debug.o entries.o fifo.o fusiondev.o fusionee.o hash.o list.o property.o reactor.o ref.o skirmish.o shmpool.o 4 | obj-$(CONFIG_FUSION_DEVICE) := $(O_TARGET) 5 | 6 | include $(TOPDIR)/Rules.make 7 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/Makefile-2.6: -------------------------------------------------------------------------------- 1 | obj-$(CONFIG_FUSION_DEVICE) += fusion.o 2 | 3 | fusion-y := $(FUSIONCORE)/fusioncore_impl.o call.o debug.o entries.o fifo.o fusiondev.o fusionee.o hash.o list.o property.o reactor.o ref.o skirmish.o shmpool.o 4 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/call.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__CALL_H__ 16 | #define __FUSION__CALL_H__ 17 | 18 | #include 19 | 20 | #include "fusiondev.h" 21 | 22 | /* module init/cleanup */ 23 | 24 | int fusion_call_init(FusionDev * dev); 25 | void fusion_call_deinit(FusionDev * dev); 26 | 27 | /* public API */ 28 | 29 | int fusion_call_new(FusionDev * dev, Fusionee *fusionee, FusionCallNew * call); 30 | 31 | int fusion_call_execute(FusionDev * dev, Fusionee * fusionee, /* NULL if call is from kernel */ 32 | FusionCallExecute * execute); 33 | 34 | int fusion_call_execute2(FusionDev * dev, Fusionee * fusionee, /* NULL if call is from kernel */ 35 | FusionCallExecute2 * execute); 36 | 37 | int fusion_call_return(FusionDev * dev, 38 | int fusion_id, FusionCallReturn * call_ret); 39 | 40 | int fusion_call_execute3(FusionDev * dev, Fusionee * fusionee, /* NULL if call is from kernel */ 41 | FusionCallExecute3 * execute); 42 | 43 | int fusion_call_return3(FusionDev * dev, 44 | int fusion_id, FusionCallReturn3 * call_ret); 45 | 46 | int fusion_call_get_owner(FusionDev * dev, int call_id, FusionID *ret_fusion_id); 47 | 48 | int fusion_call_set_quota(FusionDev * dev, FusionCallSetQuota *set_quota); 49 | 50 | int fusion_call_destroy(FusionDev * dev, Fusionee *fusionee, int call_id); 51 | 52 | /* internal functions */ 53 | 54 | void fusion_call_destroy_all(FusionDev * dev, Fusionee *fusionee); 55 | 56 | 57 | void fusion_call_quota_message_callback(FusionDev * dev, int id, void *ctx, int arg); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "debug.h" 33 | 34 | 35 | 36 | static unsigned long 37 | direct_clock_get_micros( void ) 38 | { 39 | unsigned long micros; 40 | struct timespec spec; 41 | 42 | ktime_get_real_ts( &spec ); 43 | 44 | micros = spec.tv_sec * 1000000 + spec.tv_nsec / 1000; 45 | 46 | return micros; 47 | } 48 | 49 | __attribute__((no_instrument_function)) 50 | pid_t 51 | direct_gettid( void ) 52 | { 53 | #if LINUX_VERSION_CODE > KERNEL_VERSION( 2, 6, 18 ) // FIXME: which version? 54 | return task_pid_vnr(current); 55 | #else 56 | return current->tgid; 57 | #endif 58 | } 59 | 60 | 61 | void 62 | fusion_debug_printk( const char *format, ... ) 63 | { 64 | char buf[512]; 65 | unsigned long micros = direct_clock_get_micros(); 66 | const char *name = "NO NAME"; 67 | 68 | va_list ap; 69 | 70 | va_start( ap, format ); 71 | 72 | vsnprintf( buf, sizeof(buf), format, ap ); 73 | 74 | va_end( ap ); 75 | 76 | printk( KERN_DEBUG "(-) [%-16.16s %03lu] (%5d) %s: %*s%s", 77 | name, micros, 78 | direct_gettid(), "Fusion", /*indent*/ 0, "", buf ); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__DEBUG_H__ 16 | #define __FUSION__DEBUG_H__ 17 | 18 | #include 19 | 20 | #define D_ARRAY_SIZE(array) ((int)(sizeof(array) / sizeof((array)[0]))) 21 | 22 | #define FUSION_ASSERT(exp) do { if (!(exp)) { printk( KERN_ERR "linux-fusion: Assertion [ " #exp " ] failed! (%s:%d)\n", __FILE__, __LINE__ ); *(char*) 0 = 0; } } while (0) 23 | #define FUSION_ASSUME(exp) do { if (!(exp)) printk( KERN_ERR "linux-fusion: Assumption [ " #exp " ] failed! (%s:%d)\n", __FILE__, __LINE__ ); } while (0) 24 | 25 | #ifdef FUSION_ENABLE_DEBUG 26 | #define FUSION_DEBUG(x...) fusion_debug_printk (x) 27 | #else 28 | #define FUSION_DEBUG(x...) do {} while (0) 29 | #endif 30 | 31 | void fusion_debug_printk( const char *format, ... ); 32 | 33 | 34 | #define D_ASSERT FUSION_ASSERT 35 | #define D_ASSUME FUSION_ASSUME 36 | 37 | 38 | /* 39 | * Magic Assertions & Utilities 40 | */ 41 | 42 | #define D_MAGIC(spell) ( (((spell)[sizeof(spell)*8/9] << 24) | \ 43 | ((spell)[sizeof(spell)*7/9] << 16) | \ 44 | ((spell)[sizeof(spell)*6/9] << 8) | \ 45 | ((spell)[sizeof(spell)*5/9] )) ^ \ 46 | (((spell)[sizeof(spell)*4/9] << 24) | \ 47 | ((spell)[sizeof(spell)*3/9] << 16) | \ 48 | ((spell)[sizeof(spell)*2/9] << 8) | \ 49 | ((spell)[sizeof(spell)*1/9] )) ) 50 | 51 | 52 | #define D_MAGIC_CHECK(o,m) ((o) != NULL && (o)->magic == D_MAGIC(#m)) 53 | 54 | #define D_MAGIC_SET(o,m) do { \ 55 | D_ASSERT( (o) != NULL ); \ 56 | D_ASSUME( (o)->magic != D_MAGIC(#m) ); \ 57 | \ 58 | (o)->magic = D_MAGIC(#m); \ 59 | } while (0) 60 | 61 | #define D_MAGIC_SET_ONLY(o,m) do { \ 62 | D_ASSERT( (o) != NULL ); \ 63 | \ 64 | (o)->magic = D_MAGIC(#m); \ 65 | } while (0) 66 | 67 | #define D_MAGIC_ASSERT(o,m) do { \ 68 | D_ASSERT( (o) != NULL ); \ 69 | D_ASSERT( (o)->magic == D_MAGIC(#m) ); \ 70 | } while (0) 71 | 72 | #define D_MAGIC_ASSUME(o,m) do { \ 73 | D_ASSUME( (o) != NULL ); \ 74 | if (o) \ 75 | D_ASSUME( (o)->magic == D_MAGIC(#m) ); \ 76 | } while (0) 77 | 78 | #define D_MAGIC_ASSERT_IF(o,m) do { \ 79 | if (o) \ 80 | D_ASSERT( (o)->magic == D_MAGIC(#m) ); \ 81 | } while (0) 82 | 83 | #define D_MAGIC_CLEAR(o) do { \ 84 | D_ASSERT( (o) != NULL ); \ 85 | D_ASSUME( (o)->magic != 0 ); \ 86 | \ 87 | (o)->magic = 0; \ 88 | } while (0) 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/entries.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__ENTRIES_H__ 16 | #define __FUSION__ENTRIES_H__ 17 | 18 | #include 19 | #include 20 | 21 | #include "types.h" 22 | #include "list.h" 23 | 24 | #include "fusioncore.h" 25 | 26 | 27 | typedef struct __FD_FusionEntry FusionEntry; 28 | 29 | typedef const struct { 30 | int object_size; 31 | 32 | int (*Init) (FusionEntry * entry, void *ctx, void *create_ctx); 33 | void (*Destroy) (FusionEntry * entry, void *ctx); 34 | void (*Print) (FusionEntry * entry, void *ctx, struct seq_file * p); 35 | } FusionEntryClass; 36 | 37 | typedef struct { 38 | unsigned int class_index; 39 | void *ctx; 40 | 41 | FusionLink *list; 42 | int ids; 43 | 44 | FusionDev *dev; 45 | 46 | struct timeval now; /* temporary for /proc code (seq start/show) */ 47 | 48 | FusionHash *hash; 49 | } FusionEntries; 50 | 51 | typedef struct { 52 | DirectLink link; 53 | 54 | FusionID fusion_id; 55 | unsigned int permissions; 56 | } FusionEntryPermissionsItem; 57 | 58 | struct __FD_FusionEntry { 59 | FusionLink link; 60 | 61 | FusionEntries *entries; 62 | 63 | int id; 64 | pid_t pid; 65 | 66 | FusionWaitQueue wait; 67 | int waiters; 68 | int *waiters_list; 69 | int waiters_list_max; 70 | 71 | struct timeval last_lock; 72 | 73 | char name[FUSION_ENTRY_INFO_NAME_LENGTH]; 74 | 75 | DirectLink *permissions; 76 | 77 | FusionID creator; 78 | }; 79 | 80 | /* Entries Init & DeInit */ 81 | 82 | void fusion_entries_init( FusionEntries *entries, 83 | FusionEntryClass *class, 84 | void *ctx, 85 | FusionDev *dev ); 86 | 87 | void fusion_entries_deinit(FusionEntries * entries); 88 | 89 | /* '/proc' support */ 90 | 91 | void fusion_entries_create_proc_entry(FusionDev * dev, const char *name, 92 | FusionEntries * data); 93 | 94 | void fusion_entries_destroy_proc_entry(FusionDev * dev, const char *name); 95 | 96 | /* Create & Destroy */ 97 | 98 | int fusion_entry_create(FusionEntries * entries, int *ret_id, void *create_ctx, FusionID fusion_id); 99 | 100 | int fusion_entry_destroy(FusionEntries * entries, int id); 101 | 102 | void fusion_entry_destroy_locked(FusionEntries * entries, FusionEntry * entry); 103 | 104 | /* Information */ 105 | 106 | int fusion_entry_set_info(FusionEntries * entries, 107 | const FusionEntryInfo * info); 108 | 109 | int fusion_entry_get_info(FusionEntries * entries, FusionEntryInfo * info); 110 | 111 | /* Permissions */ 112 | 113 | int fusion_entry_add_permissions ( FusionEntries *entries, 114 | const FusionEntryPermissions *permissions, 115 | Fusionee *fusionee ); 116 | 117 | int fusion_entry_check_permissions( FusionEntries *entries, 118 | int entry_id, 119 | FusionID fusion_id, 120 | unsigned int nr ); 121 | 122 | /* Lookup */ 123 | 124 | int fusion_entry_lookup(FusionEntries * entries, int id, FusionEntry ** ret_entry); 125 | 126 | /** Wait & Notify **/ 127 | 128 | /* 129 | * Wait for the entry to be notified with an optional timeout. 130 | * 131 | * The entry 132 | * (1) has to be locked prior to calling this function. 133 | * (2) is temporarily unlocked while being waited for. 134 | * 135 | * If this function returns an error, the entry is not locked again! 136 | * 137 | * Possible errors are: 138 | * -EIDRM Entry has been removed while being waited for. 139 | * -ETIMEDOUT Timeout occured. 140 | * -EINTR A signal has been received. 141 | */ 142 | int fusion_entry_wait(FusionEntry * entry, int *timeout); 143 | 144 | /* 145 | * Wake up one or all processes waiting for the entry to be notified. 146 | * 147 | * The entry has to be locked prior to calling this function. 148 | */ 149 | void fusion_entry_notify(FusionEntry * entry); 150 | 151 | #define FUSION_ENTRY_CLASS( Type, name, init_func, destroy_func, print_func ) \ 152 | \ 153 | static FusionEntryClass name##_class = { \ 154 | .object_size = sizeof(Type), \ 155 | .Init = init_func, \ 156 | .Destroy = destroy_func, \ 157 | .Print = print_func \ 158 | }; \ 159 | \ 160 | static inline int fusion_##name##_lookup( FusionEntries *entries, \ 161 | int id, \ 162 | Type **ret_##name ) \ 163 | { \ 164 | int ret; \ 165 | FusionEntry *entry; \ 166 | \ 167 | ret = fusion_entry_lookup( entries, id, &entry ); \ 168 | \ 169 | if (!ret) \ 170 | *ret_##name = (Type *) entry; \ 171 | \ 172 | return ret; \ 173 | } \ 174 | \ 175 | static inline int fusion_##name##_wait( Type *name, int *timeout ) \ 176 | { \ 177 | return fusion_entry_wait( (FusionEntry*) name, timeout ); \ 178 | } \ 179 | \ 180 | static inline void fusion_##name##_notify( Type *name ) \ 181 | { \ 182 | fusion_entry_notify( (FusionEntry*) name ); \ 183 | } 184 | 185 | #endif 186 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/fifo.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | 17 | #include "fifo.h" 18 | 19 | void fusion_fifo_put(FusionFifo * fifo, FusionLink * link) 20 | { 21 | direct_list_append( &fifo->items, link ); 22 | 23 | fifo->count++; 24 | } 25 | 26 | FusionLink *fusion_fifo_get(FusionFifo * fifo) 27 | { 28 | FusionLink *first = fifo->items; 29 | 30 | if (!first) { 31 | D_ASSERT( fifo->count == 0 ); 32 | return NULL; 33 | } 34 | 35 | direct_list_remove( &fifo->items, first ); 36 | 37 | fifo->count--; 38 | 39 | return first; 40 | } 41 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/fifo.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__FIFO_H__ 16 | #define __FUSION__FIFO_H__ 17 | 18 | #include "types.h" 19 | #include "list.h" 20 | 21 | typedef struct { 22 | FusionLink *items; 23 | int count; 24 | } FusionFifo; 25 | 26 | void fusion_fifo_put(FusionFifo * fifo, FusionLink * link); 27 | 28 | FusionLink *fusion_fifo_get(FusionFifo * fifo); 29 | 30 | static inline void fusion_fifo_reset(FusionFifo * fifo) 31 | { 32 | fifo->items = NULL; 33 | fifo->count = 0; 34 | } 35 | 36 | #endif /* __FUSION__FIFO_H__ */ 37 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/fusioncore.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__FUSIONCORE_H__ 16 | #define __FUSION__FUSIONCORE_H__ 17 | 18 | #include 19 | 20 | #include "fusioncore_impl.h" 21 | 22 | typedef enum { 23 | FC_OK, 24 | FC_FAILURE 25 | } FusionCoreResult; 26 | 27 | 28 | typedef struct __Fusion_FusionCore FusionCore; 29 | 30 | 31 | FusionCoreResult fusion_core_enter ( int cpu_index, 32 | FusionCore **ret_core ); 33 | 34 | void fusion_core_exit ( FusionCore *core ); 35 | 36 | pid_t fusion_core_pid ( FusionCore *core ); 37 | 38 | 39 | void *fusion_core_malloc ( FusionCore *core, 40 | size_t size ); 41 | 42 | void fusion_core_free ( FusionCore *core, 43 | void *ptr ); 44 | 45 | void fusion_core_set_pointer( FusionCore *core, 46 | unsigned int index, 47 | void *ptr ); 48 | 49 | void *fusion_core_get_pointer( FusionCore *core, 50 | unsigned int index ); 51 | 52 | 53 | void fusion_core_lock ( FusionCore *core ); 54 | void fusion_core_unlock ( FusionCore *core ); 55 | 56 | 57 | FusionCoreResult fusion_core_wq_init ( FusionCore *core, 58 | FusionWaitQueue *queue ); 59 | 60 | void fusion_core_wq_deinit( FusionCore *core, 61 | FusionWaitQueue *queue ); 62 | 63 | void fusion_core_wq_wait ( FusionCore *core, 64 | FusionWaitQueue *queue, 65 | int *timeout_ms, 66 | bool interruptible ); 67 | 68 | void fusion_core_wq_wake ( FusionCore *core, 69 | FusionWaitQueue *queue ); 70 | 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/fusiondev.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__FUSIONDEV_H__ 16 | #define __FUSION__FUSIONDEV_H__ 17 | 18 | #include 19 | #include 20 | 21 | #include "debug.h" 22 | #include "entries.h" 23 | #include "list.h" 24 | #include "shmpool.h" 25 | 26 | #define D_ARRAY_SIZE(array) ((int)(sizeof(array) / sizeof((array)[0]))) 27 | 28 | #define NUM_MINORS 32 29 | #define NUM_CLASSES 8 30 | 31 | #define CACHE_EXECUTIONS_NUM 10 32 | #define CACHE_EXECUTIONS_DATA_LEN 20 33 | 34 | typedef struct __Fusion_FusionShared FusionShared; 35 | 36 | struct __Fusion_FusionDev { 37 | FusionShared *shared; 38 | 39 | int refs; 40 | int index; 41 | struct { 42 | int major; 43 | int minor; 44 | } api; 45 | 46 | int enter_ok; 47 | FusionWaitQueue enter_wait; 48 | 49 | int secure; 50 | 51 | #ifdef FUSION_CORE_SHMPOOLS 52 | void *shared_area; 53 | #else 54 | unsigned long shared_area; 55 | #endif 56 | 57 | struct { 58 | int property_lease_purchase; 59 | int property_cede; 60 | 61 | int reactor_attach; 62 | int reactor_detach; 63 | int reactor_dispatch; 64 | 65 | int ref_up; 66 | int ref_down; 67 | 68 | int ref_catch; 69 | int ref_throw; 70 | 71 | int skirmish_prevail_swoop; 72 | int skirmish_dismiss; 73 | int skirmish_wait; 74 | int skirmish_notify; 75 | 76 | int shmpool_attach; 77 | int shmpool_detach; 78 | } stat; 79 | 80 | struct { 81 | int last_id; 82 | FusionLink *list; 83 | FusionWaitQueue wait; 84 | } fusionee; 85 | 86 | FusionEntries call; 87 | FusionEntries properties; 88 | FusionEntries reactor; 89 | FusionEntries ref; 90 | FusionEntries shmpool; 91 | FusionEntries skirmish; 92 | 93 | FusionLink *execution_free_list; 94 | unsigned int execution_free_list_num; 95 | 96 | unsigned int next_class_index; 97 | 98 | #if FUSION_SHM_PER_WORLD_SPACE 99 | FusionLink *addr_entries; 100 | void *addr_base; 101 | #endif 102 | 103 | unsigned long shm_base; 104 | 105 | int shutdown; 106 | }; 107 | 108 | struct __Fusion_FusionShared { 109 | FusionDev devs[NUM_MINORS]; 110 | 111 | #if !FUSION_SHM_PER_WORLD_SPACE 112 | FusionLink *addr_entries; 113 | void *addr_base; 114 | #endif 115 | }; 116 | 117 | extern FusionCore *fusion_core; 118 | extern struct proc_dir_entry *fusion_proc_dir[NUM_MINORS]; 119 | 120 | 121 | extern unsigned long fusion_shm_base; 122 | extern unsigned long fusion_shm_size; 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/fusionee.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__FUSIONEE_H__ 16 | #define __FUSION__FUSIONEE_H__ 17 | 18 | #include 19 | #include 20 | 21 | #include "fusiondev.h" 22 | #include "fifo.h" 23 | #include "types.h" 24 | 25 | 26 | struct __Fusion_Fusionee { 27 | FusionLink link; 28 | 29 | int magic; 30 | 31 | int refs; 32 | 33 | FusionID id; 34 | int pid; 35 | 36 | FusionFifo packets; 37 | FusionFifo prev_packets; 38 | 39 | FusionFifo free_packets; 40 | 41 | atomic_long_t rcv_total; /* Total number of messages received. */ 42 | atomic_long_t snd_total; /* Total number of messages sent. */ 43 | 44 | FusionWaitQueue wait_receive; 45 | FusionWaitQueue wait_process; 46 | bool waiting; 47 | 48 | bool force_slave; 49 | 50 | struct mm_struct *mm; 51 | 52 | pid_t dispatcher_pid; 53 | 54 | FusionDev *fusion_dev; 55 | 56 | char exe_file[PATH_MAX]; 57 | 58 | int wait_on_call_quota; 59 | }; 60 | 61 | 62 | 63 | 64 | typedef enum { 65 | FMC_NONE, 66 | FMC_DISPATCH, 67 | FMC_CALL_QUOTA 68 | } FusionMessageCallback; 69 | 70 | 71 | /* module init/cleanup */ 72 | 73 | int fusionee_init(FusionDev * dev); 74 | void fusionee_deinit(FusionDev * dev); 75 | 76 | /* internal functions */ 77 | 78 | int fusionee_new(FusionDev * dev, bool force_slave, Fusionee ** ret_fusionee); 79 | 80 | int fusionee_enter(FusionDev * dev, FusionEnter * enter, Fusionee * fusionee); 81 | 82 | void fusionee_ref(Fusionee * fusionee); 83 | void fusionee_unref(Fusionee * fusionee); 84 | 85 | int fusionee_fork(FusionDev * dev, FusionFork * fork, Fusionee * fusionee); 86 | 87 | int fusionee_get_info(FusionDev * dev, FusionGetFusioneeInfo * get_info); 88 | 89 | int fusionee_send_message(FusionDev * dev, 90 | Fusionee * fusionee, 91 | FusionID recipient, 92 | FusionMessageType msg_type, 93 | int msg_id, 94 | int msg_channel, 95 | int msg_size, 96 | const void *msg_data, 97 | FusionMessageCallback callback, 98 | void *callback_ctx, int callback_param, 99 | const void *extra_data, unsigned int extra_size); 100 | 101 | int fusionee_send_message2(FusionDev * dev, 102 | Fusionee * sender, 103 | Fusionee * recipient, 104 | FusionMessageType msg_type, 105 | int msg_id, 106 | int msg_channel, 107 | int msg_size, 108 | const void *msg_data, 109 | FusionMessageCallback callback, 110 | void *callback_ctx, int callback_param, 111 | const void *extra_data, unsigned int extra_size, 112 | bool flush); 113 | 114 | int fusionee_get_messages(FusionDev * dev, 115 | Fusionee * fusionee, 116 | void *buf, int buf_size, bool block); 117 | 118 | int fusionee_wait_processing(FusionDev * dev, 119 | int fusion_id, 120 | FusionMessageType msg_type, int msg_id); 121 | 122 | int fusionee_remove_message_callbacks(Fusionee *recipient, 123 | void *ctx); 124 | 125 | unsigned 126 | int fusionee_poll(FusionDev * dev, 127 | Fusionee * fusionee, struct file *file, poll_table * wait); 128 | 129 | int fusionee_sync(FusionDev *dev, 130 | Fusionee *fusionee); 131 | 132 | int fusionee_kill(FusionDev * dev, 133 | Fusionee * fusionee, 134 | FusionID target, int signal, int timeout_ms); 135 | 136 | void fusionee_destroy(FusionDev * dev, Fusionee * fusionee); 137 | 138 | FusionID fusionee_id(const Fusionee * fusionee); 139 | 140 | pid_t fusionee_dispatcher_pid(FusionDev * dev, FusionID fusion_id); 141 | 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | GLIB - Library of useful routines for C programming 3 | Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 4 | (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) 5 | (c) Copyright 2000-2004 Convergence (integrated media) GmbH 6 | 7 | All rights reserved. 8 | 9 | Written by Denis Oliver Kropp , 10 | Andreas Hundt , 11 | Sven Neumann , 12 | Ville Syrjälä , 13 | Claudio Ciccani and 14 | Michael Emmel . 15 | 16 | This library is free software; you can redistribute it and/or 17 | modify it under the terms of the GNU Lesser General Public 18 | License as published by the Free Software Foundation; either 19 | version 2 of the License, or (at your option) any later version. 20 | 21 | This library is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | Lesser General Public License for more details. 25 | 26 | You should have received a copy of the GNU Lesser General Public 27 | License along with this library; if not, write to the 28 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, 29 | Boston, MA 02111-1307, USA. 30 | */ 31 | 32 | /* 33 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS 34 | * file for a list of people on the GLib Team. See the ChangeLog 35 | * files for a list of changes. These files are distributed with 36 | * GLib at ftp://ftp.gtk.org/pub/gtk/. 37 | */ 38 | 39 | #ifndef __FUSION_HASH_H__ 40 | #define __FUSION_HASH_H__ 41 | 42 | #include 43 | 44 | #include "types.h" 45 | 46 | 47 | #define FUSION_HASH_MIN_SIZE 11 48 | #define FUSION_HASH_MAX_SIZE 13845163 49 | 50 | typedef enum { 51 | FHT_PTR, 52 | FHT_STRING, 53 | FHT_INT 54 | } FusionHashType; 55 | 56 | typedef struct _FusionHashNode FusionHashNode; 57 | 58 | struct _FusionHashNode 59 | { 60 | void *key; 61 | void *value; 62 | FusionHashNode *next; 63 | }; 64 | 65 | struct __Fusion_FusionHash 66 | { 67 | int magic; 68 | FusionHashType key_type; 69 | FusionHashType value_type; 70 | int size; 71 | int nnodes; 72 | FusionHashNode **nodes; 73 | 74 | bool free_keys; 75 | bool free_values; 76 | }; 77 | 78 | typedef bool (*FusionHashIteratorFunc)( FusionHash *hash, 79 | void *key, 80 | void *value, 81 | void *ctx ); 82 | 83 | 84 | int 85 | fusion_hash_resize (FusionHash *hash); 86 | 87 | int 88 | fusion_hash_create (FusionHashType key_type, 89 | FusionHashType value_type, 90 | int size, FusionHash **ret_hash ); 91 | 92 | int 93 | fusion_hash_remove (FusionHash *hash, 94 | const void * key, 95 | void **old_key, 96 | void **old_value); 97 | 98 | int 99 | fusion_hash_insert( FusionHash *hash, void *key, void *value ); 100 | 101 | int 102 | fusion_hash_replace (FusionHash *hash, 103 | void * key, 104 | void * value, 105 | void **old_key, 106 | void **old_value); 107 | void 108 | fusion_hash_destroy( FusionHash *hash ); 109 | 110 | void 111 | fusion_hash_set_autofree( FusionHash *hash, bool free_keys, bool free_values ); 112 | 113 | void * 114 | fusion_hash_lookup (FusionHash *hash, const void * key); 115 | 116 | void 117 | fusion_hash_iterate( FusionHash *hash, 118 | FusionHashIteratorFunc func, 119 | void *ctx ); 120 | 121 | unsigned int 122 | fusion_hash_size (FusionHash *hash); 123 | 124 | bool fusion_hash_should_resize ( FusionHash *hash); 125 | 126 | 127 | 128 | 129 | typedef struct { 130 | FusionHash *hash; 131 | int index; 132 | FusionHashNode *next; 133 | } FusionHashIterator; 134 | 135 | static inline void * 136 | fusion_hash_iterator_next( FusionHashIterator *iterator ) 137 | { 138 | FusionHashNode *node = NULL; 139 | 140 | if (iterator->next) { 141 | node = iterator->next; 142 | iterator->next = node->next; 143 | } 144 | else { 145 | FusionHash *hash = iterator->hash; 146 | 147 | D_MAGIC_ASSERT( hash, FusionHash ); 148 | 149 | for (iterator->index++; iterator->index < hash->size; iterator->index++) { 150 | node = hash->nodes[iterator->index]; 151 | if (node) { 152 | iterator->next = node->next; 153 | 154 | break; 155 | } 156 | } 157 | } 158 | 159 | return node ? node->value : NULL; 160 | } 161 | 162 | static inline void * 163 | fusion_hash_iterator_init( FusionHashIterator *iterator, 164 | FusionHash *hash ) 165 | { 166 | D_MAGIC_ASSERT( hash, FusionHash ); 167 | 168 | iterator->hash = hash; 169 | iterator->index = -1; 170 | iterator->next = NULL; 171 | 172 | return fusion_hash_iterator_next( iterator ); 173 | } 174 | 175 | 176 | #define fusion_hash_foreach( elem, iterator, hash ) \ 177 | for ((elem) = (__typeof__(elem)) fusion_hash_iterator_init( &iterator, hash ); \ 178 | (elem) != NULL; \ 179 | (elem) = (__typeof__(elem)) fusion_hash_iterator_next( &iterator )) 180 | 181 | 182 | #endif /*__FUSION_HASH_H__*/ 183 | 184 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/list.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | //#include 16 | 17 | //#include 18 | 19 | 20 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __DIRECT__LIST_H__ 16 | #define __DIRECT__LIST_H__ 17 | 18 | #include "debug.h" 19 | 20 | typedef struct __D_DirectLink DirectLink; 21 | 22 | 23 | typedef struct __D_DirectLink FusionLink; 24 | 25 | #define fusion_list_foreach direct_list_foreach 26 | #define fusion_list_foreach_safe direct_list_foreach_safe 27 | #define fusion_list_prepend direct_list_prepend 28 | #define fusion_list_remove direct_list_remove 29 | #define fusion_list_move_to_front direct_list_move_to_front 30 | 31 | 32 | struct __D_DirectLink { 33 | int magic; 34 | 35 | DirectLink *next; 36 | DirectLink *prev; /* The 'prev' pointer of the first element always points 37 | to the last element of the list, for fast appending ;-) */ 38 | }; 39 | 40 | static __inline__ void 41 | direct_list_prepend( DirectLink **list, DirectLink *link ) 42 | { 43 | DirectLink *first; 44 | 45 | D_ASSERT( list != NULL ); 46 | D_ASSERT( link != NULL ); 47 | 48 | first = *list; 49 | 50 | link->next = first; 51 | 52 | if (first) { 53 | D_MAGIC_ASSERT( first, DirectLink ); 54 | 55 | link->prev = first->prev; 56 | 57 | first->prev = link; 58 | } 59 | else 60 | link->prev = link; 61 | 62 | *list = link; 63 | 64 | D_MAGIC_SET( link, DirectLink ); 65 | } 66 | 67 | static __inline__ void 68 | direct_list_append( DirectLink **list, DirectLink *link ) 69 | { 70 | DirectLink *first; 71 | 72 | D_ASSERT( list != NULL ); 73 | D_ASSERT( link != NULL ); 74 | 75 | first = *list; 76 | 77 | link->next = NULL; 78 | 79 | if (first) { 80 | DirectLink *last = first->prev; 81 | 82 | D_MAGIC_ASSERT( first, DirectLink ); 83 | D_MAGIC_ASSERT( last, DirectLink ); 84 | 85 | link->prev = last; 86 | 87 | last->next = first->prev = link; 88 | } 89 | else 90 | *list = link->prev = link; 91 | 92 | D_MAGIC_SET( link, DirectLink ); 93 | } 94 | 95 | static __inline__ void 96 | direct_list_insert( DirectLink **list, DirectLink *link, DirectLink *before ) 97 | { 98 | DirectLink *first; 99 | 100 | D_ASSERT( list != NULL ); 101 | D_ASSERT( link != NULL ); 102 | 103 | first = *list; 104 | 105 | D_MAGIC_ASSERT_IF( first, DirectLink ); 106 | D_MAGIC_ASSERT_IF( before, DirectLink ); 107 | 108 | if (first == before) { 109 | direct_list_prepend( list, link ); 110 | } 111 | else if (first == NULL || before == NULL) { 112 | direct_list_append( list, link ); 113 | } 114 | else { 115 | DirectLink *prev = before->prev; 116 | 117 | D_MAGIC_ASSERT( prev, DirectLink ); 118 | 119 | prev->next = link; 120 | 121 | link->prev = prev; 122 | link->next = before; 123 | 124 | before->prev = link; 125 | 126 | D_MAGIC_SET( link, DirectLink ); 127 | } 128 | } 129 | 130 | static __inline__ bool 131 | direct_list_contains_element_EXPENSIVE( DirectLink *list, DirectLink *link ) 132 | { 133 | D_MAGIC_ASSERT_IF( list, DirectLink ); 134 | 135 | while (list) { 136 | if (list == link) 137 | return true; 138 | 139 | list = list->next; 140 | } 141 | 142 | return false; 143 | } 144 | 145 | static __inline__ int 146 | direct_list_count_elements_EXPENSIVE( DirectLink *list ) 147 | { 148 | int count = 0; 149 | 150 | while (list) { 151 | D_MAGIC_ASSERT( list, DirectLink ); 152 | 153 | count++; 154 | 155 | list = list->next; 156 | } 157 | 158 | return count; 159 | } 160 | 161 | static __inline__ bool 162 | direct_list_remove( DirectLink **list, DirectLink *link ) 163 | { 164 | DirectLink *next; 165 | DirectLink *prev; 166 | 167 | D_ASSERT( list != NULL ); 168 | 169 | D_ASSERT( direct_list_contains_element_EXPENSIVE( *list, link ) ); 170 | 171 | D_MAGIC_ASSERT( *list, DirectLink ); 172 | D_MAGIC_ASSERT( link, DirectLink ); 173 | 174 | next = link->next; 175 | prev = link->prev; 176 | 177 | if (next) { 178 | D_MAGIC_ASSERT( next, DirectLink ); 179 | 180 | next->prev = prev; 181 | } 182 | else 183 | (*list)->prev = prev; 184 | 185 | if (link == *list) 186 | *list = next; 187 | else { 188 | D_MAGIC_ASSERT( prev, DirectLink ); 189 | 190 | prev->next = next; 191 | } 192 | 193 | link->next = link->prev = NULL; 194 | 195 | D_MAGIC_CLEAR( link ); 196 | 197 | return true; 198 | } 199 | 200 | static __inline__ DirectLink * 201 | direct_list_last( DirectLink *list ) 202 | { 203 | if (!list) 204 | return NULL; 205 | 206 | D_MAGIC_ASSERT( list, DirectLink ); 207 | 208 | return list->prev; 209 | } 210 | 211 | static __inline__ void 212 | direct_list_move_to_front( DirectLink **list, DirectLink *link ) 213 | { 214 | DirectLink *next; 215 | DirectLink *prev; 216 | DirectLink *first; 217 | 218 | D_ASSERT( list != NULL ); 219 | 220 | first = *list; 221 | 222 | D_ASSERT( direct_list_contains_element_EXPENSIVE( first, link ) ); 223 | 224 | D_MAGIC_ASSERT( first, DirectLink ); 225 | D_MAGIC_ASSERT( link, DirectLink ); 226 | 227 | if (first == link) 228 | return; 229 | 230 | next = link->next; 231 | prev = link->prev; 232 | 233 | D_MAGIC_ASSERT_IF( next, DirectLink ); 234 | D_MAGIC_ASSERT( prev, DirectLink ); 235 | 236 | if (next) { 237 | next->prev = prev; 238 | 239 | link->prev = first->prev; 240 | } 241 | else 242 | link->prev = prev; 243 | 244 | prev->next = next; 245 | 246 | link->next = first; 247 | 248 | first->prev = link; 249 | 250 | *list = link; 251 | } 252 | 253 | #ifdef __GNUC__ 254 | #define direct_list_check_link( link ) \ 255 | ({ \ 256 | D_MAGIC_ASSERT_IF( link, DirectLink ); \ 257 | link != NULL; \ 258 | }) 259 | #else 260 | #define direct_list_check_link( link ) \ 261 | (link != NULL) 262 | #endif 263 | 264 | #define direct_list_foreach(elem, list) \ 265 | for (elem = (__typeof__(elem))(list); \ 266 | direct_list_check_link( (DirectLink*)(elem) ); \ 267 | elem = (__typeof__(elem))(((DirectLink*)(elem))->next)) 268 | 269 | #define direct_list_foreach_via(elem, list, _link) \ 270 | for (elem = (list) ? (__typeof__(elem)) ((void*)(list) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL; \ 271 | direct_list_check_link( (elem) ? &(elem)->_link : NULL ); \ 272 | elem = ((elem)->_link.next) ? (__typeof__(elem)) ((void*)((elem)->_link.next) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL ) 273 | 274 | #define direct_list_foreach_via_safe(elem, temp, list, _link) \ 275 | for (elem = (list) ? (__typeof__(elem)) ((void*)(list) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL, temp = ((elem) ? (((elem)->_link.next) ? (__typeof__(elem)) ((void*)((elem)->_link.next) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL) : NULL); \ 276 | direct_list_check_link( (elem) ? &(elem)->_link : NULL ); \ 277 | elem = (__typeof__(elem))(temp), temp = ((elem) ? (((elem)->_link.next) ? (__typeof__(elem)) ((void*)((elem)->_link.next) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL) : NULL) ) 278 | 279 | #define direct_list_foreach_reverse(elem, list) \ 280 | for (elem = (__typeof__(elem))((list) ? (list)->prev : NULL); \ 281 | direct_list_check_link( (DirectLink*)(elem) ); \ 282 | elem = (__typeof__(elem))((((DirectLink*)(elem))->prev->next) ? ((DirectLink*)(elem))->prev : NULL)) 283 | 284 | #define direct_list_foreach_safe(elem, temp, list) \ 285 | for (elem = (__typeof__(elem))(list), temp = ((__typeof__(temp))(elem) ? (__typeof__(temp))(((DirectLink*)(elem))->next) : NULL); \ 286 | direct_list_check_link( (DirectLink*)(elem) ); \ 287 | elem = (__typeof__(elem))(temp), temp = ((__typeof__(temp))(elem) ? (__typeof__(temp))(((DirectLink*)(elem))->next) : NULL)) 288 | 289 | #define direct_list_foreach_remove(elem, list) \ 290 | while ((elem = (__typeof__(elem))(list)) && direct_list_remove( &(list), (DirectLink*)(elem) )) 291 | 292 | 293 | #endif 294 | 295 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/property.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifdef HAVE_LINUX_CONFIG_H 16 | #include 17 | #endif 18 | #include 19 | #include 20 | #include 21 | #include 22 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) 23 | #include 24 | #endif 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "fusiondev.h" 31 | #include "entries.h" 32 | #include "fusionee.h" 33 | #include "list.h" 34 | #include "property.h" 35 | 36 | typedef enum { 37 | FUSION_PROPERTY_AVAILABLE = 0, 38 | FUSION_PROPERTY_LEASED, 39 | FUSION_PROPERTY_PURCHASED 40 | } FusionPropertyState; 41 | 42 | typedef struct { 43 | FusionEntry entry; 44 | 45 | FusionPropertyState state; 46 | int fusion_id; /* non-zero if leased/purchased */ 47 | unsigned long purchase_stamp; 48 | int lock_pid; 49 | int count; /* lock counter */ 50 | } FusionProperty; 51 | 52 | static void 53 | fusion_property_print(FusionEntry * entry, void *ctx, struct seq_file *p) 54 | { 55 | FusionProperty *property = (FusionProperty *) entry; 56 | 57 | if (property->state != FUSION_PROPERTY_AVAILABLE) { 58 | seq_printf(p, "%s by 0x%08x (%d) %dx\n", 59 | property->state == 60 | FUSION_PROPERTY_LEASED ? "leased" : "purchased", 61 | property->fusion_id, property->lock_pid, 62 | property->count); 63 | return; 64 | } 65 | 66 | seq_printf(p, "\n"); 67 | } 68 | 69 | FUSION_ENTRY_CLASS(FusionProperty, property, NULL, NULL, fusion_property_print) 70 | 71 | /******************************************************************************/ 72 | int fusion_property_init(FusionDev * dev) 73 | { 74 | fusion_entries_init(&dev->properties, &property_class, dev, dev); 75 | 76 | fusion_entries_create_proc_entry(dev, "properties", &dev->properties); 77 | 78 | return 0; 79 | } 80 | 81 | void fusion_property_deinit(FusionDev * dev) 82 | { 83 | fusion_entries_destroy_proc_entry( dev, "properties" ); 84 | 85 | fusion_entries_deinit(&dev->properties); 86 | } 87 | 88 | /******************************************************************************/ 89 | 90 | int fusion_property_new(FusionDev * dev, Fusionee *fusionee, int *ret_id) 91 | { 92 | return fusion_entry_create(&dev->properties, ret_id, NULL, fusionee_id(fusionee)); 93 | } 94 | 95 | int fusion_property_lease(FusionDev * dev, int id, int fusion_id) 96 | { 97 | int ret; 98 | FusionProperty *property; 99 | int timeout = -1; 100 | 101 | dev->stat.property_lease_purchase++; 102 | 103 | ret = fusion_property_lookup(&dev->properties, id, &property); 104 | if (ret) 105 | return ret; 106 | 107 | while (true) { 108 | switch (property->state) { 109 | case FUSION_PROPERTY_AVAILABLE: 110 | property->state = FUSION_PROPERTY_LEASED; 111 | property->fusion_id = fusion_id; 112 | property->lock_pid = fusion_core_pid( fusion_core ); 113 | property->count = 1; 114 | 115 | return 0; 116 | 117 | case FUSION_PROPERTY_LEASED: 118 | if (property->lock_pid == fusion_core_pid( fusion_core )) { 119 | property->count++; 120 | 121 | return 0; 122 | } 123 | 124 | ret = fusion_property_wait(property, NULL); 125 | if (ret) 126 | return ret; 127 | 128 | break; 129 | 130 | case FUSION_PROPERTY_PURCHASED: 131 | if (property->lock_pid == fusion_core_pid( fusion_core )) 132 | return -EIO; 133 | 134 | if (timeout == -1) { 135 | // FIXME: add fusion_core_jiffies() 136 | if (jiffies - property->purchase_stamp > HZ / 10) 137 | return -EAGAIN; 138 | 139 | timeout = HZ / 10; 140 | } 141 | 142 | ret = fusion_property_wait(property, &timeout); 143 | if (ret) 144 | return ret; 145 | 146 | break; 147 | 148 | default: 149 | BUG(); 150 | } 151 | } 152 | 153 | BUG(); 154 | 155 | /* won't reach this */ 156 | return -1; 157 | } 158 | 159 | int fusion_property_purchase(FusionDev * dev, int id, int fusion_id) 160 | { 161 | int ret; 162 | FusionProperty *property; 163 | int timeout = -1; 164 | 165 | dev->stat.property_lease_purchase++; 166 | 167 | ret = fusion_property_lookup(&dev->properties, id, &property); 168 | if (ret) 169 | return ret; 170 | 171 | while (true) { 172 | switch (property->state) { 173 | case FUSION_PROPERTY_AVAILABLE: 174 | property->state = FUSION_PROPERTY_PURCHASED; 175 | property->fusion_id = fusion_id; 176 | property->purchase_stamp = jiffies; 177 | property->lock_pid = fusion_core_pid( fusion_core ); 178 | property->count = 1; 179 | 180 | fusion_property_notify(property); 181 | return 0; 182 | 183 | case FUSION_PROPERTY_LEASED: 184 | if (property->lock_pid == fusion_core_pid( fusion_core )) 185 | return -EIO; 186 | 187 | ret = fusion_property_wait(property, NULL); 188 | if (ret) 189 | return ret; 190 | 191 | break; 192 | 193 | case FUSION_PROPERTY_PURCHASED: 194 | if (property->lock_pid == fusion_core_pid( fusion_core )) { 195 | property->count++; 196 | 197 | return 0; 198 | } 199 | 200 | if (timeout == -1) { 201 | if (jiffies - property->purchase_stamp > HZ) 202 | return -EAGAIN; 203 | 204 | timeout = HZ; 205 | } 206 | 207 | ret = fusion_property_wait(property, &timeout); 208 | if (ret) 209 | return ret; 210 | 211 | break; 212 | 213 | default: 214 | BUG(); 215 | } 216 | } 217 | 218 | BUG(); 219 | 220 | /* won't reach this */ 221 | return -1; 222 | } 223 | 224 | int fusion_property_cede(FusionDev * dev, int id, int fusion_id) 225 | { 226 | int ret; 227 | FusionProperty *property; 228 | bool purchased; 229 | 230 | dev->stat.property_cede++; 231 | 232 | ret = fusion_property_lookup(&dev->properties, id, &property); 233 | if (ret) 234 | return ret; 235 | 236 | if (property->lock_pid != fusion_core_pid( fusion_core )) 237 | return -EIO; 238 | 239 | if (--property->count) 240 | return 0; 241 | 242 | purchased = (property->state == FUSION_PROPERTY_PURCHASED); 243 | 244 | property->state = FUSION_PROPERTY_AVAILABLE; 245 | property->fusion_id = 0; 246 | property->lock_pid = 0; 247 | 248 | fusion_property_notify(property); 249 | 250 | return 0; 251 | } 252 | 253 | int fusion_property_holdup(FusionDev * dev, int id, Fusionee * fusionee) 254 | { 255 | int ret; 256 | FusionProperty *property; 257 | FusionID fusion_id = fusionee_id(fusionee); 258 | 259 | if (fusion_id > 1) 260 | return -EPERM; 261 | 262 | ret = fusion_property_lookup(&dev->properties, id, &property); 263 | if (ret) 264 | return ret; 265 | 266 | if (property->state == FUSION_PROPERTY_PURCHASED) { 267 | if (property->fusion_id == fusion_id) 268 | return -EIO; 269 | 270 | fusionee_kill(dev, fusionee, property->fusion_id, SIGKILL, -1); 271 | } 272 | 273 | return 0; 274 | } 275 | 276 | int fusion_property_destroy(FusionDev * dev, int id) 277 | { 278 | return fusion_entry_destroy(&dev->properties, id); 279 | } 280 | 281 | void fusion_property_cede_all(FusionDev * dev, int fusion_id) 282 | { 283 | FusionLink *l; 284 | 285 | fusion_list_foreach(l, dev->properties.list) { 286 | FusionProperty *property = (FusionProperty *) l; 287 | 288 | if (property->fusion_id == fusion_id) { 289 | property->state = FUSION_PROPERTY_AVAILABLE; 290 | property->fusion_id = 0; 291 | property->lock_pid = 0; 292 | 293 | fusion_core_wq_wake( fusion_core, &property->entry.wait); 294 | } 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/property.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__PROPERTY_H__ 16 | #define __FUSION__PROPERTY_H__ 17 | 18 | #include "fusiondev.h" 19 | #include "types.h" 20 | 21 | /* module init/cleanup */ 22 | 23 | int fusion_property_init(FusionDev * dev); 24 | void fusion_property_deinit(FusionDev * dev); 25 | 26 | /* public API */ 27 | 28 | int fusion_property_new(FusionDev * dev, Fusionee *fusionee, int *ret_id); 29 | 30 | int fusion_property_lease(FusionDev * dev, int id, int fusion_id); 31 | 32 | int fusion_property_purchase(FusionDev * dev, int id, int fusion_id); 33 | 34 | int fusion_property_cede(FusionDev * dev, int id, int fusion_id); 35 | 36 | int fusion_property_holdup(FusionDev * dev, int id, Fusionee * fusionee); 37 | 38 | int fusion_property_destroy(FusionDev * dev, int id); 39 | 40 | /* internal functions */ 41 | 42 | void fusion_property_cede_all(FusionDev * dev, int fusion_id); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/reactor.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__REACTOR_H__ 16 | #define __FUSION__REACTOR_H__ 17 | 18 | #include "fusiondev.h" 19 | #include "types.h" 20 | 21 | /* module init/cleanup */ 22 | 23 | int fusion_reactor_init(FusionDev * dev); 24 | void fusion_reactor_deinit(FusionDev * dev); 25 | 26 | /* public API */ 27 | 28 | int fusion_reactor_new(FusionDev * dev, Fusionee *fusionee, int *id); 29 | 30 | int fusion_reactor_attach(FusionDev * dev, 31 | int id, int channel, FusionID fusion_id); 32 | 33 | int fusion_reactor_detach(FusionDev * dev, 34 | int id, int channel, FusionID fusion_id); 35 | 36 | int fusion_reactor_dispatch(FusionDev * dev, 37 | int id, 38 | int channel, 39 | Fusionee * fusionee, 40 | int msg_size, const void *msg_data); 41 | 42 | int fusion_reactor_destroy(FusionDev * dev, int id); 43 | 44 | int fusion_reactor_set_dispatch_callback(FusionDev * dev, 45 | int id, int call_id, void *call_ptr); 46 | 47 | /* internal functions */ 48 | 49 | void fusion_reactor_detach_all(FusionDev * dev, FusionID fusion_id); 50 | 51 | int fusion_reactor_fork_all(FusionDev * dev, 52 | FusionID fusion_id, FusionID from_id); 53 | 54 | 55 | 56 | void fusion_reactor_dispatch_message_callback(FusionDev * dev, int id, void *ctx, int arg); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/ref.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__REF_H__ 16 | #define __FUSION__REF_H__ 17 | 18 | #include "fusiondev.h" 19 | #include "types.h" 20 | 21 | /* module init/cleanup */ 22 | 23 | int fusion_ref_init(FusionDev * dev); 24 | void fusion_ref_deinit(FusionDev * dev); 25 | 26 | /* public API */ 27 | 28 | int fusion_ref_new(FusionDev * dev, Fusionee *fusionee, int *id); 29 | 30 | int fusion_ref_up(FusionDev * dev, int id, FusionID fusion_id); 31 | 32 | int fusion_ref_down(FusionDev * dev, int id, FusionID fusion_id); 33 | 34 | int fusion_ref_catch(FusionDev * dev, int id, FusionID fusion_id); 35 | 36 | int fusion_ref_throw(FusionDev * dev, int id, FusionID fusion_id, FusionID catcher); 37 | 38 | int fusion_ref_zero_lock(FusionDev * dev, int id, FusionID fusion_id); 39 | 40 | int fusion_ref_zero_trylock(FusionDev * dev, int id, FusionID fusion_id); 41 | 42 | int fusion_ref_zero_unlock(FusionDev * dev, int id, FusionID fusion_id); 43 | 44 | int fusion_ref_stat(FusionDev * dev, int id, int *refs); 45 | 46 | int fusion_ref_watch(FusionDev * dev, int id, int call_id, int call_arg); 47 | 48 | int fusion_ref_inherit(FusionDev * dev, int id, int from); 49 | 50 | int fusion_ref_set_sync(FusionDev * dev, int id); 51 | 52 | int fusion_ref_destroy(FusionDev * dev, int id); 53 | 54 | /* internal functions */ 55 | 56 | void fusion_ref_clear_all_local(FusionDev * dev, FusionID fusion_id); 57 | 58 | int fusion_ref_fork_all_local(FusionDev * dev, 59 | FusionID fusion_id, FusionID from_id); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/shmpool.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__SHMPOOL_H__ 16 | #define __FUSION__SHMPOOL_H__ 17 | 18 | #include 19 | 20 | #ifndef FUSION_SHM_PER_WORLD_SPACE 21 | #define FUSION_SHM_PER_WORLD_SPACE (__BITS_PER_LONG == 64) 22 | #endif 23 | 24 | 25 | #include "fusiondev.h" 26 | #include "types.h" 27 | 28 | #if defined(__mips__) 29 | #define FUSION_SHM_BASE_32 0x50010000 /* virtual base address */ 30 | #elif defined(CONFIG_CPU_SH4) 31 | #define FUSION_SHM_BASE_32 0x30000000 /* virtual base address */ 32 | #else 33 | #define FUSION_SHM_BASE_32 0x20000000 /* virtual base address */ 34 | #endif 35 | #define FUSION_SHM_SIZE_32 0x20000000 /* size of virtual address space */ 36 | 37 | #define FUSION_SHM_BASE_64 0x523000000000LL /* virtual base address */ 38 | #define FUSION_SHM_SIZE_64 0x001000000000LL /* size of virtual address space */ 39 | 40 | #ifndef FUSION_SHM_BASE_DEFAULT 41 | #define FUSION_SHM_BASE_DEFAULT (__BITS_PER_LONG == 64 ? (FUSION_SHM_BASE_64) : (FUSION_SHM_BASE_32)) 42 | #endif 43 | 44 | #ifndef FUSION_SHM_SIZE_DEFAULT 45 | #define FUSION_SHM_SIZE_DEFAULT (__BITS_PER_LONG == 64 ? (FUSION_SHM_SIZE_64) : (FUSION_SHM_SIZE_32)) 46 | #endif 47 | 48 | 49 | /* module init/cleanup */ 50 | 51 | int fusion_shmpool_init(FusionDev * dev); 52 | void fusion_shmpool_deinit(FusionDev * dev); 53 | 54 | /* public API */ 55 | 56 | int fusion_shmpool_new(FusionDev * dev, Fusionee *fusionee, FusionSHMPoolNew * pool); 57 | 58 | int fusion_shmpool_attach(FusionDev * dev, 59 | FusionSHMPoolAttach * attach, FusionID fusion_id); 60 | 61 | int fusion_shmpool_detach(FusionDev * dev, int id, FusionID fusion_id); 62 | 63 | int fusion_shmpool_dispatch(FusionDev * dev, 64 | FusionSHMPoolDispatch * dispatch, 65 | Fusionee * fusionee); 66 | 67 | int fusion_shmpool_destroy(FusionDev * dev, int id); 68 | 69 | /* internal functions */ 70 | 71 | void fusion_shmpool_detach_all(FusionDev * dev, FusionID fusion_id); 72 | 73 | int fusion_shmpool_fork_all(FusionDev * dev, 74 | FusionID fusion_id, FusionID from_id); 75 | 76 | #ifdef FUSION_CORE_SHMPOOLS 77 | int fusion_shmpool_map(FusionDev *dev, struct vm_area_struct *vma); 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/single/fusioncore_impl.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #ifdef HAVE_LINUX_CONFIG_H 18 | #include 19 | #endif 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "debug.h" 26 | 27 | #include "fusioncore.h" 28 | 29 | 30 | 31 | FusionCoreResult 32 | fusion_core_enter( int cpu_index, 33 | FusionCore **ret_core ) 34 | { 35 | FusionCore *core; 36 | 37 | D_ASSERT( ret_core != NULL ); 38 | 39 | core = kmalloc( sizeof(FusionCore), GFP_KERNEL ); 40 | if (!core) 41 | return FC_FAILURE; 42 | 43 | core->cpu_index = cpu_index; 44 | 45 | sema_init( &core->lock, 1 ); 46 | 47 | D_MAGIC_SET( core, FusionCore ); 48 | 49 | *ret_core = core; 50 | 51 | return FC_OK; 52 | } 53 | 54 | void 55 | fusion_core_exit( FusionCore *core ) 56 | { 57 | D_MAGIC_ASSERT( core, FusionCore ); 58 | 59 | 60 | D_MAGIC_CLEAR( core ); 61 | 62 | kfree( core ); 63 | } 64 | 65 | // FIXME: in theory pids could be more than 16bit wide, so we'd have to use a 64bit type here 66 | pid_t 67 | fusion_core_pid( FusionCore *core ) 68 | { 69 | D_MAGIC_ASSERT( core, FusionCore ); 70 | 71 | return (core->cpu_index << 16) | current->pid; 72 | } 73 | 74 | 75 | void * 76 | fusion_core_malloc( FusionCore *core, 77 | size_t size ) 78 | { 79 | D_MAGIC_ASSERT( core, FusionCore ); 80 | 81 | return kzalloc( size, GFP_KERNEL ); 82 | } 83 | 84 | void 85 | fusion_core_free( FusionCore *core, 86 | void *ptr ) 87 | { 88 | D_MAGIC_ASSERT( core, FusionCore ); 89 | 90 | kfree( ptr ); 91 | } 92 | 93 | 94 | void 95 | fusion_core_set_pointer( FusionCore *core, 96 | unsigned int index, 97 | void *ptr ) 98 | { 99 | FUSION_DEBUG( "%s( %p, index %d, ptr %p )\n", __FUNCTION__, core, index, ptr ); 100 | 101 | D_MAGIC_ASSERT( core, FusionCore ); 102 | 103 | D_ASSERT( index < sizeof(core->pointers) ); 104 | 105 | core->pointers[index] = ptr; 106 | } 107 | 108 | void * 109 | fusion_core_get_pointer( FusionCore *core, 110 | unsigned int index ) 111 | { 112 | FUSION_DEBUG( "%s( %p, index %d )\n", __FUNCTION__, core, index ); 113 | 114 | D_MAGIC_ASSERT( core, FusionCore ); 115 | 116 | D_ASSERT( index < sizeof(core->pointers) ); 117 | 118 | FUSION_DEBUG( " -> returning %p\n", core->pointers[index] ); 119 | 120 | return core->pointers[index]; 121 | } 122 | 123 | 124 | void 125 | fusion_core_lock( FusionCore *core ) 126 | { 127 | D_MAGIC_ASSERT( core, FusionCore ); 128 | 129 | down( &core->lock ); 130 | } 131 | 132 | void 133 | fusion_core_unlock( FusionCore *core ) 134 | { 135 | D_MAGIC_ASSERT( core, FusionCore ); 136 | 137 | up( &core->lock ); 138 | } 139 | 140 | 141 | FusionCoreResult 142 | fusion_core_wq_init( FusionCore *core, 143 | FusionWaitQueue *queue ) 144 | { 145 | D_MAGIC_ASSERT( core, FusionCore ); 146 | 147 | memset( queue, 0, sizeof(FusionWaitQueue) ); 148 | 149 | init_waitqueue_head( &queue->queue ); 150 | 151 | D_MAGIC_SET( queue, FusionWaitQueue ); 152 | 153 | return FC_OK; 154 | } 155 | 156 | void 157 | fusion_core_wq_deinit( FusionCore *core, 158 | FusionWaitQueue *queue ) 159 | { 160 | D_MAGIC_ASSERT( core, FusionCore ); 161 | D_MAGIC_ASSERT( queue, FusionWaitQueue ); 162 | 163 | D_MAGIC_CLEAR( queue ); 164 | } 165 | 166 | void 167 | fusion_core_wq_wait( FusionCore *core, 168 | FusionWaitQueue *queue, 169 | int *timeout_ms, 170 | bool interruptible ) 171 | { 172 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 173 | DEFINE_WAIT(wait); 174 | 175 | D_MAGIC_ASSERT( core, FusionCore ); 176 | D_MAGIC_ASSERT( queue, FusionWaitQueue ); 177 | 178 | prepare_to_wait( &queue->queue, &wait, interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE ); 179 | 180 | fusion_core_unlock( core ); 181 | 182 | if (timeout_ms) 183 | *timeout_ms = schedule_timeout(*timeout_ms); 184 | else 185 | schedule(); 186 | 187 | finish_wait( &queue->queue, &wait ); 188 | 189 | fusion_core_lock( core ); 190 | #else 191 | wait_queue_t wait; 192 | 193 | D_MAGIC_ASSERT( core, FusionCore ); 194 | D_MAGIC_ASSERT( queue, FusionWaitQueue ); 195 | 196 | init_waitqueue_entry(&wait, current); 197 | 198 | current->state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; 199 | 200 | write_lock( &queue->queue.lock); 201 | __add_wait_queue( &queue->queue, &wait); 202 | write_unlock( &queue->queue.lock ); 203 | 204 | fusion_core_unlock( core ); 205 | 206 | if (timeout_ms) 207 | *timeout_ms = schedule_timeout(*timeout_ms); 208 | else 209 | schedule(); 210 | 211 | fusion_core_lock( core ); 212 | 213 | write_lock( &queue->queue.lock ); 214 | __remove_wait_queue( &queue->queue, &wait ); 215 | write_unlock( &queue->queue.lock ); 216 | #endif 217 | } 218 | 219 | void 220 | fusion_core_wq_wake( FusionCore *core, 221 | FusionWaitQueue *queue ) 222 | { 223 | D_MAGIC_ASSERT( core, FusionCore ); 224 | D_MAGIC_ASSERT( queue, FusionWaitQueue ); 225 | 226 | wake_up_all( &queue->queue ); 227 | } 228 | 229 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/single/fusioncore_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__FUSIONCORE_IMPL_H__ 16 | #define __FUSION__FUSIONCORE_IMPL_H__ 17 | 18 | #include 19 | 20 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) 21 | #include 22 | #else 23 | #include 24 | #endif 25 | 26 | #include 27 | 28 | 29 | struct __Fusion_FusionCore { 30 | int magic; 31 | 32 | int cpu_index; 33 | 34 | struct semaphore lock; 35 | 36 | void *pointers[10]; 37 | }; 38 | 39 | 40 | typedef struct { 41 | int magic; 42 | 43 | wait_queue_head_t queue; 44 | } FusionWaitQueue; 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/skirmish.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__SKIRMISH_H__ 16 | #define __FUSION__SKIRMISH_H__ 17 | 18 | #include "fusiondev.h" 19 | #include "types.h" 20 | 21 | /* module init/cleanup */ 22 | 23 | int fusion_skirmish_init(FusionDev * dev); 24 | void fusion_skirmish_deinit(FusionDev * dev); 25 | 26 | /* public API */ 27 | 28 | int fusion_skirmish_new(FusionDev * dev, Fusionee *fusionee, int *id); 29 | 30 | int fusion_skirmish_prevail(FusionDev * dev, int id, int fusion_id); 31 | 32 | int fusion_skirmish_swoop(FusionDev * dev, int id, int fusion_id); 33 | 34 | int fusion_skirmish_lock_count(FusionDev * dev, 35 | int id, int fusion_id, int *ret_lock_count); 36 | 37 | int fusion_skirmish_dismiss(FusionDev * dev, int id, int fusion_id); 38 | 39 | int fusion_skirmish_destroy(FusionDev * dev, int id); 40 | 41 | int fusion_skirmish_wait_(FusionDev * dev, 42 | FusionSkirmishWait * wait, FusionID fusion_id); 43 | 44 | int fusion_skirmish_notify_(FusionDev * dev, int id, FusionID fusion_id); 45 | 46 | /* internal functions */ 47 | 48 | void fusion_skirmish_dismiss_all(FusionDev * dev, int fusion_id); 49 | 50 | void fusion_skirmish_dismiss_all_from_pid(FusionDev * dev, int pid); 51 | 52 | void fusion_skirmish_transfer_all(FusionDev * dev, 53 | FusionID to, FusionID from, int from_pid, unsigned int serial); 54 | 55 | void fusion_skirmish_reclaim_all(FusionDev * dev, int from_pid); 56 | 57 | void fusion_skirmish_return_all(FusionDev * dev, int from_fusion_id, int to_fusion_id, unsigned int serial); 58 | void fusion_skirmish_return_all_from(FusionDev * dev, int from_fusion_id); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /linux/drivers/char/fusion/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __FUSION__TYPES_H__ 16 | #define __FUSION__TYPES_H__ 17 | 18 | #include 19 | 20 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) 21 | typedef enum { 22 | false = 0, 23 | true = !false 24 | } bool; 25 | #endif 26 | 27 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) 28 | #define PDE_DATA(x) (PDE(x)->data) 29 | #endif 30 | 31 | typedef struct __Fusion_FusionDev FusionDev; 32 | typedef struct __Fusion_Fusionee Fusionee; 33 | 34 | typedef void (*MessageCallbackFunc)( FusionDev * dev, int msg_id, void *ctx, int param ); 35 | 36 | 37 | 38 | typedef struct __Fusion_FusionUDP FusionUDP; 39 | 40 | 41 | typedef struct __Fusion_FusionHash FusionHash; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /one/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | -------------------------------------------------------------------------------- /one/Kconfig: -------------------------------------------------------------------------------- 1 | config LINUX_ONE 2 | tristate "Linux One IPC" 3 | ---help--- 4 | Linux One is the new IPC API used by Coma 5 | -------------------------------------------------------------------------------- /one/Makefile-2.4: -------------------------------------------------------------------------------- 1 | O_TARGET := linux-one.o 2 | 3 | obj-y := $(ONECORE)/onecore_impl.o app.o debug.o entries.o fifo.o list.o onedev.o one_udp.o packet.o queue.o target.o 4 | obj-$(CONFIG_LINUX_ONE) := $(O_TARGET) 5 | 6 | include $(TOPDIR)/Rules.make 7 | -------------------------------------------------------------------------------- /one/Makefile-2.6: -------------------------------------------------------------------------------- 1 | obj-$(CONFIG_LINUX_ONE) += linux-one.o 2 | 3 | linux-one-y := $(ONECORE)/onecore_impl.o app.o debug.o entries.o fifo.o list.o onedev.o one_udp.o packet.o queue.o target.o 4 | -------------------------------------------------------------------------------- /one/OneTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE_TYPES_H__ 13 | #define __ONE_TYPES_H__ 14 | 15 | 16 | /********************************************************************************************************************** 17 | ** Queues 18 | */ 19 | 20 | 21 | /* 22 | * The One Queue ID is a unique identifier for one queue. 23 | */ 24 | typedef uint32_t OneQID; 25 | 26 | #define ONE_QID_NONE 0 27 | 28 | 29 | /* 30 | * Queue Flags 31 | */ 32 | typedef enum { 33 | ONE_QUEUE_NO_FLAGS = 0x00000000, 34 | 35 | ONE_QUEUE_VIRTUAL = 0x00000001, /* Virtual Queue, has no receive buffers, only forwards to attached queues */ 36 | } OneQueueFlags; 37 | 38 | 39 | /* 40 | * Packet Header Flags 41 | */ 42 | typedef enum { 43 | ONE_PACKET_NO_FLAGS = 0x00000000, 44 | 45 | ONE_PACKET_COMPRESSED = 0x00000001 /* Compressed Packet */ 46 | } OnePacketHeaderFlags; 47 | 48 | 49 | /* 50 | * Packet Header 51 | */ 52 | typedef struct { 53 | OneQID queue_id; /* Queue ID this packet is sent to */ 54 | 55 | OnePacketHeaderFlags flags; /* Packet Flags */ 56 | uint32_t size; /* Packet Size */ 57 | uint32_t uncompressed; /* Packet Size after decompression */ 58 | } OnePacketHeader; 59 | 60 | 61 | 62 | 63 | 64 | /* 65 | 66 | New QID for global messaging 67 | 68 | 69 | 16-byte 70 | 71 | 2 byte reserved 72 | 2 byte name space 73 | 8 byte system within name space (one kernel module instance for example) 74 | 4 byte queue id within system 75 | 76 | 77 | Public name space "MAC" with system IDs 78 | 79 | 6 byte MAC address 80 | 2 byte sub address (e.g. multiple systems on a board with one ethernet connection) 81 | 82 | 83 | Public name space "random" ?? 84 | 85 | 8 byte random 86 | 87 | 88 | Private name spaces could be defined, e.g. for systems without a MAC address. 89 | */ 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /one/app.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | One Application is a user (process) of One 14 | */ 15 | 16 | //#define ONE_ENABLE_DEBUG 17 | 18 | #include 19 | #include 20 | #ifdef HAVE_LINUX_CONFIG_H 21 | #include 22 | #endif 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #include "app.h" 32 | #include "fifo.h" 33 | #include "onedev.h" 34 | #include "packet.h" 35 | #include "queue.h" 36 | #include "target.h" 37 | 38 | 39 | /******************************************************************************/ 40 | 41 | static void 42 | OneAppTarget_Destroy( OneTarget *target ) 43 | { 44 | OneAppTargetData *data = (OneAppTargetData*) target->data; 45 | OnePacket *packet; 46 | 47 | D_MAGIC_ASSERT( target, OneTarget ); 48 | 49 | while ((packet = (OnePacket *) one_fifo_get(&data->packets)) != NULL) { 50 | D_MAGIC_ASSERT( packet, OnePacket ); 51 | 52 | OnePacket_Free( packet ); 53 | } 54 | 55 | while ((packet = (OnePacket *) one_fifo_get(&data->free_packets)) != NULL) { 56 | D_MAGIC_ASSERT( packet, OnePacket ); 57 | 58 | OnePacket_Free( packet ); 59 | } 60 | 61 | if (data->link.prev) 62 | direct_list_remove( &data->app->recv_data, &data->link ); 63 | 64 | OneTarget_Destroy( target ); 65 | } 66 | 67 | static int 68 | OneAppTarget_Dispatch( OneTarget *target, 69 | OnePacketHeader *header, 70 | const struct iovec *iov, 71 | size_t iov_count ) 72 | { 73 | int ret; 74 | OneAppTargetData *data = (OneAppTargetData*) target->data; 75 | OnePacket *packet; 76 | 77 | ONE_DEBUG( "%s( %p, header %p, iov %p, iov_count %zu )\n", __FUNCTION__, target, header, iov, iov_count ); 78 | 79 | D_MAGIC_ASSERT( target, OneTarget ); 80 | 81 | while (data->packets.count > 100) { 82 | one_core_wq_wait( one_core, &data->app->wait_for_free, NULL ); 83 | 84 | if (signal_pending( current )) 85 | return -EINTR; 86 | } 87 | 88 | if (0&&data->packets.items) { 89 | packet = (OnePacket*) data->packets.items->prev; 90 | if (packet) { 91 | ret = OnePacket_Write( packet, header, iov, iov_count ); 92 | if (ret == 0) { 93 | printk(KERN_DEBUG "%s: successfully appended data (once this works, remove message)\n",__FUNCTION__); 94 | goto out; 95 | } 96 | 97 | one_core_wq_wake( one_core, &data->app->wait_for_packets ); 98 | } 99 | } 100 | 101 | packet = OnePacket_New(); 102 | if (!packet) 103 | return -ENOMEM; 104 | 105 | packet->header.queue_id = data->queue_id; 106 | 107 | ret = OnePacket_Write( packet, header, iov, iov_count ); 108 | if (ret) { 109 | OnePacket_Free( packet ); 110 | return ret; 111 | } 112 | 113 | packet->flush = true; 114 | 115 | one_fifo_put( &data->packets, &packet->link ); 116 | 117 | out: 118 | /* 119 | * Link data to list of receiving targets if needed 120 | */ 121 | if (!data->link.prev) 122 | direct_list_append( &data->app->recv_data, &data->link ); 123 | 124 | one_core_wq_wake( one_core, &data->app->wait_for_packets ); 125 | 126 | return 0; 127 | } 128 | 129 | static int 130 | OneAppTarget_WakeUp( OneTarget *target ) 131 | { 132 | OneAppTargetData *data = (OneAppTargetData*) target->data; 133 | 134 | ONE_DEBUG( "%s( %p )\n", __FUNCTION__, target ); 135 | 136 | D_MAGIC_ASSERT( target, OneTarget ); 137 | 138 | /* 139 | * Set wake up flag for receiver 140 | */ 141 | data->wakeup = true; 142 | 143 | /* 144 | * Link data to list of receiving targets if needed 145 | */ 146 | if (!data->link.prev) 147 | direct_list_append( &data->app->recv_data, &data->link ); 148 | 149 | /* 150 | * Wake up all receivers to check for wake up 151 | */ 152 | one_core_wq_wake( one_core, &data->app->wait_for_packets ); 153 | 154 | return 0; 155 | } 156 | 157 | typedef struct { 158 | OneApp *app; 159 | OneQID queue_id; 160 | } OneAppTarget_InitContext; 161 | 162 | static int 163 | OneAppTarget_Init( OneTarget *target, 164 | void *ctx ) 165 | { 166 | OneAppTarget_InitContext *context = (OneAppTarget_InitContext*) ctx; 167 | OneAppTargetData *data = (OneAppTargetData*) target->data; 168 | 169 | data->app = context->app; 170 | data->queue_id = context->queue_id; 171 | 172 | one_fifo_reset( &data->packets ); 173 | one_fifo_reset( &data->free_packets ); 174 | 175 | target->Destroy = OneAppTarget_Destroy; 176 | target->Dispatch = OneAppTarget_Dispatch; 177 | target->WakeUp = OneAppTarget_WakeUp; 178 | 179 | return 0; 180 | } 181 | 182 | /******************************************************************************/ 183 | 184 | int 185 | OneApp_New( OneDev *dev, 186 | OneID one_id, 187 | OneApp **ret_oneapp ) 188 | { 189 | OneApp *oneapp; 190 | 191 | oneapp = one_core_malloc( one_core, sizeof(OneApp) ); 192 | if (!oneapp) 193 | return -ENOMEM; 194 | 195 | oneapp->dev = dev; 196 | oneapp->one_id = one_id; 197 | oneapp->recv_data = NULL; 198 | 199 | oneapp->link.magic = 0; 200 | oneapp->magic = 0; 201 | 202 | one_core_wq_init( one_core, &oneapp->wait_for_free ); 203 | one_core_wq_init( one_core, &oneapp->wait_for_packets ); 204 | 205 | D_MAGIC_SET( oneapp, OneApp ); 206 | 207 | *ret_oneapp = oneapp; 208 | 209 | return 0; 210 | } 211 | 212 | void 213 | OneApp_Destroy( OneApp *oneapp ) 214 | { 215 | D_MAGIC_ASSERT( oneapp, OneApp ); 216 | 217 | one_queue_destroy_all( oneapp ); 218 | 219 | one_core_wq_deinit( one_core, &oneapp->wait_for_free ); 220 | one_core_wq_deinit( one_core, &oneapp->wait_for_packets ); 221 | 222 | D_MAGIC_CLEAR( oneapp ); 223 | 224 | one_core_free( one_core, oneapp ); 225 | } 226 | 227 | int 228 | OneApp_CreateTarget( OneApp *oneapp, 229 | OneQueue *queue, 230 | OneTarget **ret_target ) 231 | { 232 | int ret; 233 | OneTarget *target; 234 | OneAppTarget_InitContext context; 235 | 236 | D_MAGIC_ASSERT( oneapp, OneApp ); 237 | 238 | context.app = oneapp; 239 | context.queue_id = queue->entry.id; 240 | 241 | ret = OneTarget_New( OneAppTarget_Init, &context, sizeof(OneAppTargetData), &target ); 242 | if (ret) 243 | return ret; 244 | 245 | *ret_target = target; 246 | 247 | return 0; 248 | } 249 | 250 | static int 251 | receive_from( OneApp *oneapp, 252 | OneAppTargetData *data, 253 | const struct iovec *iov, 254 | size_t iov_count, 255 | size_t offset, 256 | size_t length, 257 | size_t *ret_received ) 258 | { 259 | int ret = 0; 260 | size_t received = 0; 261 | 262 | while (data->packets.count) { 263 | OnePacket *packet = (OnePacket*) data->packets.items; 264 | 265 | if (sizeof(OnePacketHeader) + packet->header.size > length) { 266 | ret = -E2BIG; 267 | goto out; 268 | } 269 | 270 | ret = OnePacket_Read( packet, iov, iov_count, offset + received ); 271 | if (ret) 272 | goto out; 273 | 274 | one_fifo_get( &data->packets ); 275 | 276 | OnePacket_Free( packet ); 277 | 278 | received += packet->header.size + sizeof(OnePacketHeader); 279 | length -= packet->header.size + sizeof(OnePacketHeader); 280 | } 281 | 282 | direct_list_remove( &oneapp->recv_data, &data->link ); 283 | 284 | one_core_wq_wake( one_core, &data->app->wait_for_free ); 285 | 286 | out: 287 | *ret_received = received; 288 | 289 | return ret; 290 | } 291 | 292 | int 293 | OneApp_Receive( OneApp *oneapp, 294 | const OneQID *ids, 295 | size_t ids_count, 296 | const struct iovec *iov, 297 | size_t iov_count, 298 | size_t *ret_received, 299 | int timeout_ms ) 300 | { 301 | int ret = 0; 302 | size_t i; 303 | bool wakeup = false; 304 | size_t received = 0; 305 | size_t length = 0; 306 | OneAppTargetData *data; 307 | 308 | /* 309 | * Calculate total length of IO vector 310 | */ 311 | for (i=0; irecv_data) { 326 | for (i=0; iqueue_id == ids[i]) { 328 | size_t rec = 0; 329 | 330 | /* Check and clear wake up flags */ 331 | if (data->wakeup) { 332 | data->wakeup = false; 333 | 334 | wakeup = true; 335 | } 336 | 337 | one_queue_stamp_receive( oneapp, data->queue_id ); 338 | 339 | /* 340 | * Receive from matching target 341 | */ 342 | ret = receive_from( oneapp, data, iov, iov_count, received, length, &rec ); 343 | 344 | received += rec; 345 | length -= rec; 346 | 347 | if (ret < 0) 348 | goto out; 349 | } 350 | } 351 | } 352 | 353 | /* 354 | * Wait when nothing was received 355 | */ 356 | if (!received && !wakeup) { 357 | if (timeout_ms == 0) { 358 | one_core_wq_wait( one_core, &oneapp->wait_for_packets, NULL ); 359 | } 360 | else if (timeout_ms > 0) { 361 | one_core_wq_wait( one_core, &oneapp->wait_for_packets, &timeout_ms ); 362 | 363 | if (!timeout_ms) { 364 | ret = -ETIMEDOUT; 365 | break; 366 | } 367 | } 368 | else { 369 | ret = 0; 370 | break; 371 | } 372 | } 373 | 374 | if (signal_pending( current )) { 375 | ret = -EINTR; 376 | break; 377 | } 378 | } 379 | 380 | out: 381 | *ret_received = received; 382 | 383 | return received ? 0 : ret; 384 | } 385 | 386 | -------------------------------------------------------------------------------- /one/app.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__APP_H__ 13 | #define __ONE__APP_H__ 14 | 15 | #include 16 | 17 | #include "types.h" 18 | #include "fifo.h" 19 | #include "list.h" 20 | #include "onecore.h" 21 | 22 | 23 | struct __One_OneApp { 24 | DirectLink link; 25 | 26 | int magic; 27 | 28 | OneDev *dev; 29 | 30 | OneID one_id; 31 | 32 | OneWaitQueue wait_for_packets; 33 | OneWaitQueue wait_for_free; 34 | 35 | DirectLink *recv_data; 36 | }; 37 | 38 | 39 | typedef struct { 40 | DirectLink link; 41 | 42 | OneApp *app; 43 | 44 | OneQID queue_id; 45 | 46 | OneFifo packets; 47 | OneFifo free_packets; 48 | 49 | bool wakeup; 50 | } OneAppTargetData; 51 | 52 | 53 | 54 | int OneApp_New ( OneDev *dev, 55 | OneID one_id, 56 | OneApp **ret_oneapp ); 57 | 58 | void OneApp_Destroy( OneApp *oneapp ); 59 | 60 | 61 | int OneApp_CreateTarget( OneApp *oneapp, 62 | OneQueue *queue, 63 | OneTarget **ret_target ); 64 | 65 | int OneApp_Receive ( OneApp *oneapp, 66 | const OneQID *ids, 67 | size_t ids_count, 68 | const struct iovec *iov, 69 | size_t iov_count, 70 | size_t *ret_received, 71 | int timeout_ms ); 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /one/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | Debugging utilities 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "debug.h" 34 | 35 | 36 | 37 | unsigned long 38 | direct_clock_get_micros( void ) 39 | { 40 | unsigned long micros; 41 | struct timespec spec; 42 | 43 | ktime_get_real_ts( &spec ); 44 | 45 | micros = spec.tv_sec * 1000000 + spec.tv_nsec / 1000; 46 | 47 | return micros; 48 | } 49 | 50 | __attribute__((no_instrument_function)) 51 | pid_t 52 | direct_gettid( void ) 53 | { 54 | #if LINUX_VERSION_CODE > KERNEL_VERSION( 2, 6, 18 ) // FIXME: which version? 55 | return task_pid_vnr(current); 56 | #else 57 | return current->tgid; 58 | #endif 59 | } 60 | 61 | 62 | void 63 | one_debug_printk( const char *format, ... ) 64 | { 65 | char buf[512]; 66 | unsigned long micros = direct_clock_get_micros(); 67 | const char *name = "NO NAME"; 68 | 69 | va_list ap; 70 | 71 | va_start( ap, format ); 72 | 73 | vsnprintf( buf, sizeof(buf), format, ap ); 74 | 75 | va_end( ap ); 76 | 77 | printk( KERN_DEBUG "(-) [%-16.16s %03lu] (%5d) %s: %*s%s", 78 | name, micros, 79 | direct_gettid(), "One", /*indent*/ 0, "", buf ); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /one/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__DEBUG_H__ 13 | #define __ONE__DEBUG_H__ 14 | 15 | #include 16 | 17 | #define ONE_ASSERT(exp) do { if (!(exp)) { printk( KERN_ERR "linux-one: Assertion [ " #exp " ] failed! (%s:%d)\n", __FILE__, __LINE__ ); *(char*) 0 = 0; } } while (0) 18 | #define ONE_ASSUME(exp) do { if (!(exp)) printk( KERN_ERR "linux-one: Assumption [ " #exp " ] failed! (%s:%d)\n", __FILE__, __LINE__ ); } while (0) 19 | 20 | #ifdef ONE_ENABLE_DEBUG 21 | #define ONE_DEBUG(x...) one_debug_printk (x) 22 | #else 23 | #define ONE_DEBUG(x...) do {} while (0) 24 | #endif 25 | 26 | void one_debug_printk( const char *format, ... ); 27 | 28 | 29 | #define D_ASSERT ONE_ASSERT 30 | #define D_ASSUME ONE_ASSUME 31 | 32 | unsigned long 33 | direct_clock_get_micros( void ); 34 | 35 | __attribute__((no_instrument_function)) 36 | pid_t 37 | direct_gettid( void ); 38 | 39 | /* 40 | * Magic Assertions & Utilities 41 | */ 42 | 43 | #define D_MAGIC(spell) ( (((spell)[sizeof(spell)*8/9] << 24) | \ 44 | ((spell)[sizeof(spell)*7/9] << 16) | \ 45 | ((spell)[sizeof(spell)*6/9] << 8) | \ 46 | ((spell)[sizeof(spell)*5/9] )) ^ \ 47 | (((spell)[sizeof(spell)*4/9] << 24) | \ 48 | ((spell)[sizeof(spell)*3/9] << 16) | \ 49 | ((spell)[sizeof(spell)*2/9] << 8) | \ 50 | ((spell)[sizeof(spell)*1/9] )) ) 51 | 52 | 53 | #define D_MAGIC_CHECK(o,m) ((o) != NULL && (o)->magic == D_MAGIC(#m)) 54 | 55 | #define D_MAGIC_SET(o,m) do { \ 56 | D_ASSERT( (o) != NULL ); \ 57 | D_ASSUME( (o)->magic != D_MAGIC(#m) ); \ 58 | \ 59 | (o)->magic = D_MAGIC(#m); \ 60 | } while (0) 61 | 62 | #define D_MAGIC_SET_ONLY(o,m) do { \ 63 | D_ASSERT( (o) != NULL ); \ 64 | \ 65 | (o)->magic = D_MAGIC(#m); \ 66 | } while (0) 67 | 68 | #define D_MAGIC_ASSERT(o,m) do { \ 69 | D_ASSERT( (o) != NULL ); \ 70 | D_ASSERT( (o)->magic == D_MAGIC(#m) ); \ 71 | } while (0) 72 | 73 | #define D_MAGIC_ASSUME(o,m) do { \ 74 | D_ASSUME( (o) != NULL ); \ 75 | if (o) \ 76 | D_ASSUME( (o)->magic == D_MAGIC(#m) ); \ 77 | } while (0) 78 | 79 | #define D_MAGIC_ASSERT_IF(o,m) do { \ 80 | if (o) \ 81 | D_ASSERT( (o)->magic == D_MAGIC(#m) ); \ 82 | } while (0) 83 | 84 | #define D_MAGIC_CLEAR(o) do { \ 85 | D_ASSERT( (o) != NULL ); \ 86 | D_ASSUME( (o)->magic != 0 ); \ 87 | \ 88 | (o)->magic = 0; \ 89 | } while (0) 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /one/entries.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | Abstract entry with ID etc. 14 | */ 15 | 16 | #ifdef HAVE_LINUX_CONFIG_H 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | #include 23 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) 24 | #include 25 | #endif 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include "onedev.h" 33 | #include "entries.h" 34 | 35 | 36 | static OneEntryClass *entry_classes[NUM_MINORS][NUM_CLASSES]; 37 | 38 | void 39 | one_entries_init( OneEntries *entries, 40 | OneEntryClass *class, 41 | void *ctx, 42 | OneDev *dev ) 43 | { 44 | 45 | ONE_DEBUG( "%s( entries %p, class %p, ctx %p, dev %p )\n", 46 | __FUNCTION__, entries, class, ctx, dev ); 47 | 48 | ONE_DEBUG( " -> object_size %d, entry size %zu\n", class->object_size, sizeof(OneEntry) ); 49 | 50 | ONE_ASSERT(entries != NULL); 51 | ONE_ASSERT(class != NULL); 52 | ONE_ASSERT(class->object_size >= sizeof(OneEntry)); 53 | 54 | if (!dev->refs) { 55 | memset(entries, 0, sizeof(OneEntries)); 56 | 57 | entries->class_index = dev->next_class_index++; 58 | entries->ctx = ctx; 59 | entries->dev = dev; 60 | } 61 | 62 | entry_classes[dev->index][entries->class_index] = class; 63 | } 64 | 65 | void one_entries_deinit(OneEntries * entries) 66 | { 67 | ONE_ASSERT(entries != NULL); 68 | 69 | if (!entries->dev->refs) { 70 | DirectLink *tmp; 71 | OneEntry *entry; 72 | OneEntryClass *class; 73 | 74 | class = entry_classes[entries->dev->index][entries->class_index]; 75 | 76 | direct_list_foreach_safe(entry, tmp, entries->list) { 77 | if (class->Destroy) 78 | class->Destroy(entry, entries->ctx); 79 | 80 | direct_list_remove( &entries->list, &entry->link ); 81 | 82 | one_core_free( one_core, entry); 83 | } 84 | } 85 | } 86 | 87 | /* reading PROC entries */ 88 | 89 | static void *one_entries_seq_start(struct seq_file *f, loff_t * pos) 90 | { 91 | int i = *pos; 92 | 93 | OneEntry *entry; 94 | OneEntries *entries; 95 | OneEntryClass *class; 96 | 97 | entries = f->private; 98 | 99 | one_core_lock( one_core ); 100 | 101 | entry = (void *)(entries->list); 102 | while (i && entry) { 103 | entry = (void *)(entry->link.next); 104 | i--; 105 | } 106 | 107 | ONE_ASSERT(entries != NULL); 108 | 109 | class = entry_classes[entries->dev->index][entries->class_index]; 110 | if (!class->Print) 111 | return NULL; 112 | 113 | do_gettimeofday(&entries->now); 114 | 115 | return entry; 116 | } 117 | 118 | static void *one_entries_seq_next(struct seq_file *f, void *v, loff_t * pos) 119 | { 120 | OneEntry *entry = v; 121 | 122 | (*pos)++; 123 | return entry->link.next; 124 | } 125 | 126 | static void one_entries_seq_stop(struct seq_file *f, void *v) 127 | { 128 | OneEntries *entries; 129 | 130 | entries = f->private; 131 | (void)v; 132 | 133 | one_core_unlock( one_core ); 134 | } 135 | 136 | int one_entries_show(struct seq_file *p, void *v) 137 | { 138 | OneEntry *entry; 139 | OneEntries *entries; 140 | OneEntryClass *class; 141 | 142 | entries = p->private; 143 | 144 | entry = v; 145 | 146 | class = entry_classes[entries->dev->index][entries->class_index]; 147 | 148 | if (entry->last_lock.tv_sec) { 149 | int diff = ((entry->entries->now.tv_sec - entry->last_lock.tv_sec) * 1000 + 150 | (entry->entries->now.tv_usec - entry->last_lock.tv_usec) / 1000); 151 | 152 | if (diff < 1000) { 153 | seq_printf(p, "%3d ms ", diff); 154 | } else if (diff < 1000000) { 155 | seq_printf(p, "%3d.%d s ", diff / 1000, 156 | (diff % 1000) / 100); 157 | } else { 158 | diff = (entry->entries->now.tv_sec - entry->last_lock.tv_sec + 159 | (entry->entries->now.tv_usec - 160 | entry->last_lock.tv_usec) / 1000000); 161 | 162 | seq_printf(p, "%3d.%d h ", diff / 3600, 163 | (diff % 3600) / 360); 164 | } 165 | } else 166 | seq_printf(p, " -.- "); 167 | 168 | seq_printf(p, "(%5d) 0x%08x ", entry->pid, entry->id); 169 | seq_printf(p, "%-24s ", entry->name[0] ? entry->name : ""); 170 | 171 | class->Print(entry, entry->entries->ctx, p); 172 | 173 | return 0; 174 | } 175 | 176 | static const struct seq_operations one_entries_seq_ops = { 177 | .start = one_entries_seq_start, 178 | .next = one_entries_seq_next, 179 | .stop = one_entries_seq_stop, 180 | .show = one_entries_show 181 | }; 182 | 183 | static int one_entries_open(struct inode *inode, struct file *file) 184 | { 185 | struct seq_file *sf; 186 | int ret; 187 | 188 | ret = seq_open(file, &one_entries_seq_ops); 189 | if (ret < 0) 190 | return ret; 191 | 192 | sf = file->private_data; 193 | sf->private = PDE_DATA(inode); 194 | 195 | return 0; 196 | } 197 | 198 | static const struct file_operations proc_one_entries_operations = { 199 | .open = one_entries_open, 200 | .read = seq_read, 201 | .llseek = seq_lseek, 202 | .release = seq_release, 203 | }; 204 | 205 | void one_entries_create_proc_entry(OneDev * dev, const char *name, 206 | OneEntries * data) 207 | { 208 | proc_create_data(name, 0, one_proc_dir[dev->index], &proc_one_entries_operations, data); 209 | } 210 | 211 | void one_entries_destroy_proc_entry(OneDev * dev, const char *name) 212 | { 213 | remove_proc_entry(name, one_proc_dir[dev->index]); 214 | } 215 | 216 | int one_entry_create(OneEntries * entries, u32 *ret_id, void *create_ctx) 217 | { 218 | int ret; 219 | OneEntry *entry; 220 | OneEntryClass *class; 221 | 222 | ONE_ASSERT(entries != NULL); 223 | ONE_ASSERT(ret_id != NULL); 224 | 225 | class = entry_classes[entries->dev->index][entries->class_index]; 226 | 227 | entry = one_core_malloc( one_core, class->object_size ); 228 | if (!entry) 229 | return -ENOMEM; 230 | 231 | memset(entry, 0, class->object_size); 232 | 233 | entry->entries = entries; 234 | entry->id = one_core_new_id( one_core ); 235 | entry->pid = one_core_pid( one_core ); 236 | 237 | one_core_wq_init( one_core, &entry->wait); 238 | 239 | if (class->Init) { 240 | ret = class->Init(entry, entries->ctx, create_ctx); 241 | if (ret) { 242 | one_core_free( one_core, entry); 243 | return ret; 244 | } 245 | } 246 | 247 | direct_list_prepend(&entries->list, &entry->link); 248 | 249 | *ret_id = entry->id; 250 | 251 | return 0; 252 | } 253 | 254 | int one_entry_destroy(OneEntries * entries, u32 id) 255 | { 256 | OneEntry *entry; 257 | OneEntryClass *class; 258 | 259 | ONE_ASSERT(entries != NULL); 260 | 261 | class = entry_classes[entries->dev->index][entries->class_index]; 262 | 263 | /* Lookup the entry. */ 264 | direct_list_foreach(entry, entries->list) { 265 | if (entry->id == id) 266 | break; 267 | } 268 | 269 | /* Check if no entry was found. */ 270 | if (!entry) { 271 | return -EINVAL; 272 | } 273 | 274 | /* Destroy it now. */ 275 | one_entry_destroy_locked(entries, entry); 276 | 277 | return 0; 278 | } 279 | 280 | void one_entry_destroy_locked(OneEntries * entries, OneEntry * entry) 281 | { 282 | OneEntryClass *class; 283 | 284 | ONE_ASSERT(entries != NULL); 285 | 286 | class = entry_classes[entries->dev->index][entries->class_index]; 287 | 288 | /* Remove the entry from the list. */ 289 | direct_list_remove(&entries->list, &entry->link); 290 | 291 | /* Wake up any waiting process. */ 292 | one_core_wq_wake( one_core, &entry->wait); 293 | 294 | /* Call the destroy function. */ 295 | if (class->Destroy) 296 | class->Destroy(entry, entries->ctx); 297 | 298 | /* Deallocate the entry. */ 299 | one_core_free( one_core, entry); 300 | } 301 | 302 | int one_entry_set_info(OneEntries * entries, const OneEntryInfo * info) 303 | { 304 | int ret; 305 | OneEntry *entry; 306 | 307 | ONE_ASSERT(entries != NULL); 308 | ONE_ASSERT(info != NULL); 309 | 310 | ret = one_entry_lookup(entries, info->id, &entry); 311 | if (ret) 312 | return ret; 313 | 314 | snprintf(entry->name, ONE_ENTRY_INFO_NAME_LENGTH, info->name); 315 | 316 | return 0; 317 | } 318 | 319 | int one_entry_get_info(OneEntries * entries, OneEntryInfo * info) 320 | { 321 | int ret; 322 | OneEntry *entry; 323 | 324 | ONE_ASSERT(entries != NULL); 325 | ONE_ASSERT(info != NULL); 326 | 327 | ret = one_entry_lookup(entries, info->id, &entry); 328 | if (ret) 329 | return ret; 330 | 331 | snprintf(info->name, ONE_ENTRY_INFO_NAME_LENGTH, entry->name); 332 | 333 | return 0; 334 | } 335 | 336 | 337 | int 338 | one_entry_lookup(OneEntries * entries, 339 | u32 id, OneEntry ** ret_entry) 340 | { 341 | OneEntry *entry; 342 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) 343 | struct timespec xtime; 344 | #endif 345 | 346 | ONE_ASSERT(entries != NULL); 347 | ONE_ASSERT(ret_entry != NULL); 348 | 349 | /* Lookup the entry. */ 350 | direct_list_foreach(entry, entries->list) { 351 | if (entry->id == id) 352 | break; 353 | } 354 | 355 | /* Check if no entry was found. */ 356 | if (!entry) { 357 | return -EINVAL; 358 | } 359 | 360 | /* Move the entry to the front of all entries. */ 361 | direct_list_move_to_front(&entries->list, &entry->link); 362 | 363 | /* Keep timestamp, but use the slightly 364 | inexact version to avoid performance impacts. */ 365 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined _STRUCT_TIMESPEC 366 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) 367 | xtime = current_kernel_time(); 368 | #endif 369 | entry->last_lock.tv_sec = xtime.tv_sec; 370 | entry->last_lock.tv_usec = xtime.tv_nsec / 1000; 371 | #else 372 | entry->last_lock = xtime; 373 | #endif 374 | 375 | /* Return the locked entry. */ 376 | *ret_entry = entry; 377 | 378 | return 0; 379 | } 380 | 381 | int one_entry_wait(OneEntry * entry, int *timeout) 382 | { 383 | int ret; 384 | int id; 385 | OneEntries *entries; 386 | OneEntry *entry2; 387 | 388 | ONE_ASSERT(entry != NULL); 389 | ONE_ASSERT(entry->entries != NULL); 390 | 391 | id = entry->id; 392 | entries = entry->entries; 393 | 394 | entry->waiters++; 395 | 396 | one_core_wq_wait( one_core, &entry->wait, timeout ); 397 | 398 | entry->waiters--; 399 | 400 | if (signal_pending(current)) 401 | return -EINTR; 402 | 403 | if (timeout && !*timeout) 404 | return -ETIMEDOUT; 405 | 406 | ret = one_entry_lookup(entries, id, &entry2); 407 | switch (ret) { 408 | case -EINVAL: 409 | return -EIDRM; 410 | 411 | case 0: 412 | if (entry != entry2) 413 | BUG(); 414 | } 415 | 416 | return ret; 417 | } 418 | 419 | void one_entry_notify(OneEntry * entry) 420 | { 421 | ONE_ASSERT(entry != NULL); 422 | 423 | one_core_wq_wake( one_core, &entry->wait); 424 | } 425 | 426 | -------------------------------------------------------------------------------- /one/entries.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__ENTRIES_H__ 13 | #define __ONE__ENTRIES_H__ 14 | 15 | #include 16 | #include 17 | 18 | #include "types.h" 19 | #include "list.h" 20 | 21 | #include "onecore.h" 22 | 23 | 24 | typedef struct __FD_OneEntry OneEntry; 25 | 26 | typedef const struct { 27 | int object_size; 28 | 29 | int (*Init) (OneEntry * entry, void *ctx, void *create_ctx); 30 | void (*Destroy) (OneEntry * entry, void *ctx); 31 | void (*Print) (OneEntry * entry, void *ctx, struct seq_file * p); 32 | } OneEntryClass; 33 | 34 | typedef struct { 35 | unsigned int class_index; 36 | void *ctx; 37 | 38 | DirectLink *list; 39 | 40 | OneDev *dev; 41 | 42 | struct timeval now; /* temporary for /proc code (seq start/show) */ 43 | } OneEntries; 44 | 45 | struct __FD_OneEntry { 46 | DirectLink link; 47 | 48 | OneEntries *entries; 49 | 50 | u32 id; 51 | pid_t pid; 52 | 53 | OneWaitQueue wait; 54 | int waiters; 55 | 56 | struct timeval last_lock; 57 | 58 | char name[ONE_ENTRY_INFO_NAME_LENGTH]; 59 | }; 60 | 61 | /* Entries Init & DeInit */ 62 | 63 | void one_entries_init( OneEntries *entries, 64 | OneEntryClass *class, 65 | void *ctx, 66 | OneDev *dev ); 67 | 68 | void one_entries_deinit(OneEntries * entries); 69 | 70 | /* '/proc' support */ 71 | 72 | void one_entries_create_proc_entry(OneDev * dev, const char *name, 73 | OneEntries * data); 74 | 75 | void one_entries_destroy_proc_entry(OneDev * dev, const char *name); 76 | 77 | /* Create & Destroy */ 78 | 79 | int one_entry_create(OneEntries * entries, u32 *ret_id, void *create_ctx); 80 | 81 | int one_entry_destroy(OneEntries * entries, u32 id); 82 | 83 | void one_entry_destroy_locked(OneEntries * entries, OneEntry * entry); 84 | 85 | /* Information */ 86 | 87 | int one_entry_set_info(OneEntries * entries, 88 | const OneEntryInfo * info); 89 | 90 | int one_entry_get_info(OneEntries * entries, OneEntryInfo * info); 91 | 92 | /* Lookup */ 93 | 94 | int one_entry_lookup(OneEntries * entries, u32 id, OneEntry ** ret_entry); 95 | 96 | /** Wait & Notify **/ 97 | 98 | /* 99 | * Wait for the entry to be notified with an optional timeout. 100 | * 101 | * The entry 102 | * (1) has to be locked prior to calling this function. 103 | * (2) is temporarily unlocked while being waited for. 104 | * 105 | * If this function returns an error, the entry is not locked again! 106 | * 107 | * Possible errors are: 108 | * -EIDRM Entry has been removed while being waited for. 109 | * -ETIMEDOUT Timeout occured. 110 | * -EINTR A signal has been received. 111 | */ 112 | int one_entry_wait(OneEntry * entry, int *timeout); 113 | 114 | /* 115 | * Wake up one or all processes waiting for the entry to be notified. 116 | * 117 | * The entry has to be locked prior to calling this function. 118 | */ 119 | void one_entry_notify(OneEntry * entry); 120 | 121 | #define ONE_ENTRY_CLASS( Type, name, init_func, destroy_func, print_func ) \ 122 | \ 123 | static OneEntryClass name##_class = { \ 124 | .object_size = sizeof(Type), \ 125 | .Init = init_func, \ 126 | .Destroy = destroy_func, \ 127 | .Print = print_func \ 128 | }; \ 129 | \ 130 | static inline int one_##name##_lookup( OneEntries *entries, \ 131 | int id, \ 132 | Type **ret_##name ) \ 133 | { \ 134 | int ret; \ 135 | OneEntry *entry; \ 136 | \ 137 | ret = one_entry_lookup( entries, id, &entry ); \ 138 | \ 139 | if (!ret) \ 140 | *ret_##name = (Type *) entry; \ 141 | \ 142 | return ret; \ 143 | } \ 144 | \ 145 | static inline int one_##name##_wait( Type *name, int *timeout ) \ 146 | { \ 147 | return one_entry_wait( (OneEntry*) name, timeout ); \ 148 | } \ 149 | \ 150 | static inline void one_##name##_notify( Type *name ) \ 151 | { \ 152 | one_entry_notify( (OneEntry*) name ); \ 153 | } 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /one/fifo.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | Simple FIFO built via plain list 14 | */ 15 | 16 | #include 17 | 18 | #include "fifo.h" 19 | 20 | void one_fifo_put(OneFifo * fifo, DirectLink * link) 21 | { 22 | direct_list_append( &fifo->items, link ); 23 | 24 | fifo->count++; 25 | } 26 | 27 | DirectLink *one_fifo_get(OneFifo * fifo) 28 | { 29 | DirectLink *first = fifo->items; 30 | 31 | if (!first) { 32 | D_ASSERT( fifo->count == 0 ); 33 | return NULL; 34 | } 35 | 36 | direct_list_remove( &fifo->items, first ); 37 | 38 | fifo->count--; 39 | 40 | return first; 41 | } 42 | -------------------------------------------------------------------------------- /one/fifo.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__FIFO_H__ 13 | #define __ONE__FIFO_H__ 14 | 15 | #include "types.h" 16 | #include "list.h" 17 | 18 | typedef struct { 19 | DirectLink *items; 20 | int count; 21 | } OneFifo; 22 | 23 | void one_fifo_put(OneFifo * fifo, DirectLink * link); 24 | 25 | DirectLink *one_fifo_get(OneFifo * fifo); 26 | 27 | static inline void one_fifo_reset(OneFifo * fifo) 28 | { 29 | fifo->items = NULL; 30 | fifo->count = 0; 31 | } 32 | 33 | #endif /* __ONE__FIFO_H__ */ 34 | -------------------------------------------------------------------------------- /one/list.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | Doubly linked list implementation with fast append 14 | */ 15 | 16 | //#include 17 | 18 | //#include 19 | 20 | 21 | -------------------------------------------------------------------------------- /one/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __DIRECT__LIST_H__ 13 | #define __DIRECT__LIST_H__ 14 | 15 | #include "debug.h" 16 | 17 | typedef struct __D_DirectLink DirectLink; 18 | 19 | 20 | struct __D_DirectLink { 21 | int magic; 22 | 23 | DirectLink *next; 24 | DirectLink *prev; /* The 'prev' pointer of the first element always points 25 | to the last element of the list, for fast appending ;-) */ 26 | }; 27 | 28 | static __inline__ void 29 | direct_list_prepend( DirectLink **list, DirectLink *link ) 30 | { 31 | DirectLink *first; 32 | 33 | D_ASSERT( list != NULL ); 34 | D_ASSERT( link != NULL ); 35 | 36 | first = *list; 37 | 38 | link->next = first; 39 | 40 | if (first) { 41 | D_MAGIC_ASSERT( first, DirectLink ); 42 | 43 | link->prev = first->prev; 44 | 45 | first->prev = link; 46 | } 47 | else 48 | link->prev = link; 49 | 50 | *list = link; 51 | 52 | D_MAGIC_SET( link, DirectLink ); 53 | } 54 | 55 | static __inline__ void 56 | direct_list_append( DirectLink **list, DirectLink *link ) 57 | { 58 | DirectLink *first; 59 | 60 | D_ASSERT( list != NULL ); 61 | D_ASSERT( link != NULL ); 62 | 63 | first = *list; 64 | 65 | link->next = NULL; 66 | 67 | if (first) { 68 | DirectLink *last = first->prev; 69 | 70 | D_MAGIC_ASSERT( first, DirectLink ); 71 | D_MAGIC_ASSERT( last, DirectLink ); 72 | 73 | link->prev = last; 74 | 75 | last->next = first->prev = link; 76 | } 77 | else 78 | *list = link->prev = link; 79 | 80 | D_MAGIC_SET( link, DirectLink ); 81 | } 82 | 83 | static __inline__ void 84 | direct_list_insert( DirectLink **list, DirectLink *link, DirectLink *before ) 85 | { 86 | DirectLink *first; 87 | 88 | D_ASSERT( list != NULL ); 89 | D_ASSERT( link != NULL ); 90 | 91 | first = *list; 92 | 93 | D_MAGIC_ASSERT_IF( first, DirectLink ); 94 | D_MAGIC_ASSERT_IF( before, DirectLink ); 95 | 96 | if (first == before) { 97 | direct_list_prepend( list, link ); 98 | } 99 | else if (first == NULL || before == NULL) { 100 | direct_list_append( list, link ); 101 | } 102 | else { 103 | DirectLink *prev = before->prev; 104 | 105 | D_MAGIC_ASSERT( prev, DirectLink ); 106 | 107 | prev->next = link; 108 | 109 | link->prev = prev; 110 | link->next = before; 111 | 112 | before->prev = link; 113 | 114 | D_MAGIC_SET( link, DirectLink ); 115 | } 116 | } 117 | 118 | static __inline__ bool 119 | direct_list_contains_element_EXPENSIVE( DirectLink *list, DirectLink *link ) 120 | { 121 | D_MAGIC_ASSERT_IF( list, DirectLink ); 122 | 123 | while (list) { 124 | if (list == link) 125 | return true; 126 | 127 | list = list->next; 128 | } 129 | 130 | return false; 131 | } 132 | 133 | static __inline__ int 134 | direct_list_count_elements_EXPENSIVE( DirectLink *list ) 135 | { 136 | int count = 0; 137 | 138 | while (list) { 139 | D_MAGIC_ASSERT( list, DirectLink ); 140 | 141 | count++; 142 | 143 | list = list->next; 144 | } 145 | 146 | return count; 147 | } 148 | 149 | static __inline__ bool 150 | direct_list_remove( DirectLink **list, DirectLink *link ) 151 | { 152 | DirectLink *next; 153 | DirectLink *prev; 154 | 155 | D_ASSERT( list != NULL ); 156 | 157 | D_ASSERT( direct_list_contains_element_EXPENSIVE( *list, link ) ); 158 | 159 | D_MAGIC_ASSERT( *list, DirectLink ); 160 | D_MAGIC_ASSERT( link, DirectLink ); 161 | 162 | next = link->next; 163 | prev = link->prev; 164 | 165 | if (next) { 166 | D_MAGIC_ASSERT( next, DirectLink ); 167 | 168 | next->prev = prev; 169 | } 170 | else 171 | (*list)->prev = prev; 172 | 173 | if (link == *list) 174 | *list = next; 175 | else { 176 | D_MAGIC_ASSERT( prev, DirectLink ); 177 | 178 | prev->next = next; 179 | } 180 | 181 | link->next = link->prev = NULL; 182 | 183 | D_MAGIC_CLEAR( link ); 184 | 185 | return true; 186 | } 187 | 188 | static __inline__ DirectLink * 189 | direct_list_last( DirectLink *list ) 190 | { 191 | if (!list) 192 | return NULL; 193 | 194 | D_MAGIC_ASSERT( list, DirectLink ); 195 | 196 | return list->prev; 197 | } 198 | 199 | static __inline__ void 200 | direct_list_move_to_front( DirectLink **list, DirectLink *link ) 201 | { 202 | DirectLink *next; 203 | DirectLink *prev; 204 | DirectLink *first; 205 | 206 | D_ASSERT( list != NULL ); 207 | 208 | first = *list; 209 | 210 | D_ASSERT( direct_list_contains_element_EXPENSIVE( first, link ) ); 211 | 212 | D_MAGIC_ASSERT( first, DirectLink ); 213 | D_MAGIC_ASSERT( link, DirectLink ); 214 | 215 | if (first == link) 216 | return; 217 | 218 | next = link->next; 219 | prev = link->prev; 220 | 221 | D_MAGIC_ASSERT_IF( next, DirectLink ); 222 | D_MAGIC_ASSERT( prev, DirectLink ); 223 | 224 | if (next) { 225 | next->prev = prev; 226 | 227 | link->prev = first->prev; 228 | } 229 | else 230 | link->prev = prev; 231 | 232 | prev->next = next; 233 | 234 | link->next = first; 235 | 236 | first->prev = link; 237 | 238 | *list = link; 239 | } 240 | 241 | #ifdef __GNUC__ 242 | #define direct_list_check_link( link ) \ 243 | ({ \ 244 | D_MAGIC_ASSERT_IF( link, DirectLink ); \ 245 | link != NULL; \ 246 | }) 247 | #else 248 | #define direct_list_check_link( link ) \ 249 | (link != NULL) 250 | #endif 251 | 252 | #define direct_list_foreach(elem, list) \ 253 | for (elem = (__typeof__(elem))(list); \ 254 | direct_list_check_link( (DirectLink*)(elem) ); \ 255 | elem = (__typeof__(elem))(((DirectLink*)(elem))->next)) 256 | 257 | #define direct_list_foreach_via(elem, list, _link) \ 258 | for (elem = (list) ? (__typeof__(elem)) ((void*)(list) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL; \ 259 | direct_list_check_link( (elem) ? &(elem)->_link : NULL ); \ 260 | elem = ((elem)->_link.next) ? (__typeof__(elem)) ((void*)((elem)->_link.next) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL ) 261 | 262 | #define direct_list_foreach_via_safe(elem, temp, list, _link) \ 263 | for (elem = (list) ? (__typeof__(elem)) ((void*)(list) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL, temp = ((elem) ? (((elem)->_link.next) ? (__typeof__(elem)) ((void*)((elem)->_link.next) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL) : NULL); \ 264 | direct_list_check_link( (elem) ? &(elem)->_link : NULL ); \ 265 | elem = (__typeof__(elem))(temp), temp = ((elem) ? (((elem)->_link.next) ? (__typeof__(elem)) ((void*)((elem)->_link.next) - (long)(&((__typeof__(elem)) NULL)->_link)) : NULL) : NULL) ) 266 | 267 | #define direct_list_foreach_reverse(elem, list) \ 268 | for (elem = (__typeof__(elem))((list) ? (list)->prev : NULL); \ 269 | direct_list_check_link( (DirectLink*)(elem) ); \ 270 | elem = (__typeof__(elem))((((DirectLink*)(elem))->prev->next) ? ((DirectLink*)(elem))->prev : NULL)) 271 | 272 | #define direct_list_foreach_safe(elem, temp, list) \ 273 | for (elem = (__typeof__(elem))(list), temp = ((__typeof__(temp))(elem) ? (__typeof__(temp))(((DirectLink*)(elem))->next) : NULL); \ 274 | direct_list_check_link( (DirectLink*)(elem) ); \ 275 | elem = (__typeof__(elem))(temp), temp = ((__typeof__(temp))(elem) ? (__typeof__(temp))(((DirectLink*)(elem))->next) : NULL)) 276 | 277 | #define direct_list_foreach_remove(elem, list) \ 278 | while ((elem = (__typeof__(elem))(list)) && direct_list_remove( &(list), (DirectLink*)(elem) )) 279 | 280 | 281 | #endif 282 | 283 | -------------------------------------------------------------------------------- /one/one_udp.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | Written by Denis Oliver Kropp 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 11 | 2 of the License, or (at your option) any later version. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include "onecore.h" 29 | #include "onecore_impl.h" 30 | #include "one_udp.h" 31 | #include "packet.h" 32 | #include "queue.h" 33 | 34 | 35 | #define ONE_PORT 0x4F4C // 'O' 'L' - One Link 36 | 37 | 38 | 39 | struct __One_OneUDP { 40 | OneCore *core; 41 | struct task_struct *thread; 42 | struct socket *sock; 43 | struct sockaddr_in addr; 44 | struct socket *sock_send; 45 | struct sockaddr_in addr_send; 46 | int running; 47 | }; 48 | 49 | 50 | /* function prototypes */ 51 | static int ksocket_receive(struct socket *sock, struct sockaddr_in *addr, void *buf, int len); 52 | static int ksocket_send_iov(struct socket *sock, 53 | struct sockaddr_in *addr, 54 | const struct iovec *iov, 55 | size_t iov_count); 56 | 57 | 58 | static int 59 | one_udp_thread( void *arg ) 60 | { 61 | OneUDP *udp = arg; 62 | int size; 63 | OneUDPMessage *message; 64 | 65 | struct sched_param param; 66 | 67 | param.sched_priority = 50; 68 | 69 | sched_setscheduler( current, SCHED_FIFO, ¶m ); 70 | 71 | /* kernel thread initialization */ 72 | udp->running = 1; 73 | 74 | printk(KERN_DEBUG "One/UDP: listening on port %d\n", ONE_PORT); 75 | 76 | message = kmalloc( sizeof(OneUDPMessage), GFP_KERNEL ); 77 | if (!message) { 78 | printk( KERN_ERR "One/UDP: could not allocate %zu bytes for receiving messages\n", sizeof(OneUDPMessage) ); 79 | return -ENOMEM; 80 | } 81 | 82 | /* main loop */ 83 | while (!kthread_should_stop()) { 84 | size = ksocket_receive( udp->sock, &udp->addr, message, sizeof(OneUDPMessage) ); 85 | 86 | if (signal_pending(current)) 87 | break; 88 | 89 | if (size < 0) 90 | printk(KERN_DEBUG "One/UDP: error getting datagram, sock_recvmsg error = %d\n", size); 91 | else { 92 | int ret; 93 | OneQueueDispatch dispatch; 94 | struct iovec iov; 95 | 96 | ONE_DEBUG( "UDP: Received %d bytes\n", size); 97 | 98 | switch (message->type) { 99 | case OUMT_DISPATCH: 100 | ONE_DEBUG( " -> DISPATCH\n" ); 101 | ONE_DEBUG( " queue_id: 0x%08x\n", message->dispatch.header.queue_id ); 102 | ONE_DEBUG( " flags: 0x%08x\n", message->dispatch.header.flags ); 103 | ONE_DEBUG( " size: %u\n", message->dispatch.header.size ); 104 | ONE_DEBUG( " uncompressed: %u\n", message->dispatch.header.uncompressed ); 105 | 106 | if (message->dispatch.header.flags) { 107 | printk(KERN_ERR "One/UDP: unsupported flags!\n" ); 108 | break; 109 | } 110 | 111 | if (message->dispatch.header.uncompressed > ONE_MAX_PACKET_SIZE) { 112 | printk(KERN_ERR "One/UDP: uncompressed > ONE_MAX_PACKET_SIZE!\n" ); 113 | break; 114 | } 115 | 116 | if (message->dispatch.header.size > message->dispatch.header.uncompressed) { 117 | printk(KERN_ERR "One/UDP: size (%u) > uncompressed (%u)!\n", 118 | message->dispatch.header.size, message->dispatch.header.uncompressed ); 119 | break; 120 | } 121 | 122 | one_core_lock( one_core ); 123 | 124 | dispatch.header = message->dispatch.header; 125 | dispatch.iov = &iov; 126 | dispatch.iov_count = 1; 127 | 128 | iov.iov_base = message->dispatch.buf; 129 | iov.iov_len = message->dispatch.header.size; 130 | 131 | ret = one_queue_dispatch( NULL, &dispatch ); 132 | if (ret) 133 | printk(KERN_ERR "One/UDP: dispatch error %d!\n", ret ); 134 | 135 | one_core_unlock( one_core ); 136 | break; 137 | 138 | case OUMT_ATTACH: 139 | ONE_DEBUG( " -> ATTACH\n" ); 140 | break; 141 | 142 | case OUMT_DETACH: 143 | ONE_DEBUG( " -> DETACH\n" ); 144 | break; 145 | 146 | default: 147 | printk(KERN_ERR "One/UDP: unknown message type 0x%08x!\n", message->type ); 148 | break; 149 | } 150 | } 151 | } 152 | 153 | kfree( message ); 154 | 155 | return 0; 156 | } 157 | 158 | static int 159 | ksocket_send_iov( struct socket *sock, 160 | struct sockaddr_in *addr, 161 | const struct iovec *iov, 162 | size_t iov_count ) 163 | { 164 | struct msghdr msg; 165 | mm_segment_t oldfs; 166 | int size = 0; 167 | size_t len = 0; 168 | int i; 169 | 170 | D_ASSERT( sock != NULL ); 171 | D_ASSERT( addr != NULL ); 172 | D_ASSERT( iov != NULL ); 173 | D_ASSERT( iov_count > 0 ); 174 | 175 | if (sock->sk==NULL) 176 | return 0; 177 | 178 | for (i=0; i 0 ); 210 | 211 | if (sock->sk==NULL) return 0; 212 | 213 | iov.iov_base = buf; 214 | iov.iov_len = len; 215 | 216 | msg.msg_flags = 0; 217 | msg.msg_name = addr; 218 | msg.msg_namelen = sizeof(struct sockaddr_in); 219 | msg.msg_control = NULL; 220 | msg.msg_controllen = 0; 221 | msg.msg_iov = &iov; 222 | msg.msg_iovlen = 1; 223 | msg.msg_control = NULL; 224 | 225 | oldfs = get_fs(); 226 | set_fs(KERNEL_DS); 227 | size = sock_recvmsg(sock,&msg,len,msg.msg_flags); 228 | set_fs(oldfs); 229 | 230 | return size; 231 | } 232 | 233 | int 234 | one_udp_create( OneCore *core, 235 | u32 other_ip, 236 | OneUDP **ret_udp ) 237 | { 238 | OneUDP *udp; 239 | int ret; 240 | 241 | ONE_DEBUG( "%s( other 0x%08x )\n", __FUNCTION__, other_ip ); 242 | 243 | udp = kmalloc(sizeof(OneUDP), GFP_KERNEL); 244 | 245 | memset( udp, 0, sizeof(OneUDP) ); 246 | 247 | udp->core = core; 248 | 249 | memset( &udp->addr, 0, sizeof(struct sockaddr) ); 250 | memset( &udp->addr_send, 0, sizeof(struct sockaddr) ); 251 | 252 | udp->addr.sin_family = AF_INET; 253 | udp->addr_send.sin_family = AF_INET; 254 | 255 | udp->addr.sin_addr.s_addr = htonl(INADDR_ANY); 256 | udp->addr_send.sin_addr.s_addr = htonl(other_ip); 257 | 258 | udp->addr.sin_port = htons(ONE_PORT); 259 | udp->addr_send.sin_port = htons(ONE_PORT); 260 | 261 | 262 | /* create a socket */ 263 | ret = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp->sock); 264 | if (ret) { 265 | printk(KERN_INFO "One/UDP: Could not create a datagram socket, error = %d\n", -ENXIO); 266 | goto error; 267 | } 268 | 269 | ret = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp->sock_send); 270 | if (ret) { 271 | printk(KERN_INFO "One/UDP: Could not create a datagram socket, error = %d\n", -ENXIO); 272 | goto error; 273 | } 274 | 275 | ret = udp->sock->ops->bind( udp->sock, (struct sockaddr *)&udp->addr, sizeof(struct sockaddr) ); 276 | if (ret) { 277 | printk(KERN_INFO "One/UDP: Could not bind the socket, error = %d\n", -ret); 278 | goto error; 279 | } 280 | 281 | ret = udp->sock->ops->connect( udp->sock_send, (struct sockaddr *)&udp->addr_send, sizeof(struct sockaddr), 0 ); 282 | if (ret) { 283 | printk(KERN_INFO "One/UDP: Could not connect the socket, error = %d\n", -ret); 284 | goto error; 285 | } 286 | 287 | 288 | /* start kernel thread */ 289 | udp->thread = kthread_run( one_udp_thread, udp, "One/UDP" ); 290 | if (IS_ERR(udp->thread)) { 291 | printk(KERN_INFO "One/UDP: unable to start kernel thread\n"); 292 | kfree(udp); 293 | ret = -ENOMEM; 294 | goto error; 295 | } 296 | 297 | *ret_udp = udp; 298 | 299 | return 0; 300 | 301 | 302 | error: 303 | if (udp->sock) 304 | sock_release(udp->sock); 305 | 306 | if (udp->sock_send) 307 | sock_release(udp->sock_send); 308 | 309 | return ret; 310 | } 311 | 312 | void 313 | one_udp_destroy( OneUDP *udp ) 314 | { 315 | if (udp->thread==NULL) 316 | printk(KERN_INFO "One/UDP: no kernel thread to kill\n"); 317 | else { 318 | force_sig( SIGTERM, udp->thread ); 319 | kthread_stop( udp->thread ); 320 | } 321 | 322 | /* free allocated resources before exit */ 323 | if (udp->sock != NULL) { 324 | sock_release(udp->sock); 325 | udp->sock = NULL; 326 | } 327 | 328 | kfree(udp); 329 | } 330 | 331 | int 332 | one_udp_send_message( OneUDP *udp, 333 | const struct iovec *iov, 334 | size_t iov_count ) 335 | { 336 | ONE_DEBUG( "%s( iov %p, count %u )\n", __FUNCTION__, iov, iov_count ); 337 | 338 | return ksocket_send_iov( udp->sock_send, &udp->addr_send, iov, iov_count ); 339 | } 340 | 341 | int 342 | one_udp_dispatch( OneUDP *udp, 343 | OneApp *app, 344 | const OnePacketHeader *header, 345 | const struct iovec *iov, 346 | size_t iov_count ) 347 | { 348 | int ret; 349 | struct iovec *iov_copy; 350 | OneUDPMessageType type = OUMT_DISPATCH; 351 | 352 | ONE_DEBUG( "%s()\n", __FUNCTION__ ); 353 | 354 | iov_copy = kmalloc( sizeof(struct iovec) * (iov_count + 2), GFP_KERNEL ); 355 | if (!iov_copy) 356 | return -ENOMEM; 357 | 358 | iov_copy[0].iov_base = (void*) &type; 359 | iov_copy[0].iov_len = sizeof(OneUDPMessageType); 360 | 361 | iov_copy[1].iov_base = (void*) header; 362 | iov_copy[1].iov_len = sizeof(OnePacketHeader); 363 | 364 | memcpy( iov_copy + 2, iov, sizeof(struct iovec) * iov_count ); 365 | 366 | ret = one_udp_send_message( udp, iov_copy, iov_count + 2 ); 367 | if (ret < 0) 368 | printk( KERN_ERR "One/Core: one_udp_send_message() failed! (error %d)\n", ret ); 369 | 370 | kfree( iov_copy ); 371 | 372 | return ret; 373 | } 374 | 375 | -------------------------------------------------------------------------------- /one/one_udp.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2002-2011 The world wide DirectFB Open Source Community (directfb.org) 3 | (c) Copyright 2002-2004 Convergence (integrated media) GmbH 4 | 5 | All rights reserved. 6 | 7 | Written by Denis Oliver Kropp 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 12 | 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #ifndef __ONE__ONE_UDP_H__ 16 | #define __ONE__ONE_UDP_H__ 17 | 18 | #include 19 | 20 | #include "packet.h" 21 | #include "types.h" 22 | 23 | 24 | int one_udp_create ( OneCore *core, 25 | u32 other_ip, 26 | OneUDP **ret_udp ); 27 | 28 | void one_udp_destroy ( OneUDP *udp ); 29 | 30 | int one_udp_send_message( OneUDP *udp, 31 | const struct iovec *iov, 32 | size_t iov_count ); 33 | 34 | int 35 | one_udp_dispatch( OneUDP *core, 36 | OneApp *app, 37 | const OnePacketHeader *header, 38 | const struct iovec *iov, 39 | size_t iov_count ); 40 | 41 | 42 | typedef enum { 43 | OUMT_DISPATCH = 1, 44 | OUMT_ATTACH = 2, 45 | OUMT_DETACH = 3, 46 | } OneUDPMessageType; 47 | 48 | typedef struct { 49 | OneUDPMessageType type; 50 | 51 | union { 52 | struct { 53 | OnePacketHeader header; 54 | 55 | char buf[ONE_MAX_PACKET_SIZE]; 56 | } dispatch; 57 | 58 | struct { 59 | OneQID queue_id; 60 | OneQID target_id; 61 | } attach; 62 | 63 | struct { 64 | OneQID queue_id; 65 | OneQID target_id; 66 | } detach; 67 | }; 68 | } OneUDPMessage; 69 | 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /one/onecore.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__ONECORE_H__ 13 | #define __ONE__ONECORE_H__ 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include "onecore_impl.h" 20 | #include "app.h" 21 | 22 | 23 | typedef struct __One_OneCore OneCore; 24 | 25 | 26 | int one_core_enter ( OneCore **ret_core ); 27 | 28 | void one_core_cleanup ( OneCore *core ); 29 | 30 | void one_core_exit ( OneCore *core ); 31 | 32 | pid_t one_core_pid ( OneCore *core ); 33 | 34 | long long one_core_stamp ( OneCore *core ); 35 | 36 | 37 | /* 38 | * Returns a new ID 39 | */ 40 | u32 one_core_new_id ( OneCore *core ); 41 | 42 | bool one_core_is_local ( OneCore *core, 43 | u32 id ); 44 | 45 | int one_core_dispatch ( OneCore *core, 46 | OneApp *app, 47 | const OnePacketHeader *header, 48 | const struct iovec *iov, 49 | size_t iov_count ); 50 | 51 | int one_core_attach ( OneCore *core, 52 | OneApp *app, 53 | OneQueueAttach *queue_attach ); 54 | 55 | int one_core_detach ( OneCore *core, 56 | OneApp *app, 57 | OneQueueDetach *queue_detach ); 58 | 59 | 60 | void *one_core_malloc ( OneCore *core, 61 | size_t size ); 62 | 63 | void one_core_free ( OneCore *core, 64 | void *ptr ); 65 | 66 | 67 | void one_core_lock ( OneCore *core ); 68 | void one_core_unlock ( OneCore *core ); 69 | 70 | 71 | int one_core_wq_init ( OneCore *core, 72 | OneWaitQueue *queue ); 73 | 74 | void one_core_wq_deinit ( OneCore *core, 75 | OneWaitQueue *queue ); 76 | 77 | void one_core_wq_wait ( OneCore *core, 78 | OneWaitQueue *queue, 79 | int *timeout_ms ); 80 | 81 | void one_core_wq_wake ( OneCore *core, 82 | OneWaitQueue *queue ); 83 | 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /one/onedev.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__ONEDEV_H__ 13 | #define __ONE__ONEDEV_H__ 14 | 15 | #include 16 | 17 | #include "debug.h" 18 | #include "entries.h" 19 | #include "list.h" 20 | #include "types.h" 21 | 22 | #define D_ARRAY_SIZE(array) ((int)(sizeof(array) / sizeof((array)[0]))) 23 | 24 | #define NUM_MINORS 8 25 | #define NUM_CLASSES 8 26 | 27 | struct __One_OneDev { 28 | OneID one_ids; 29 | 30 | int refs; 31 | int index; 32 | 33 | DirectLink *apps; 34 | 35 | struct { 36 | int major; 37 | int minor; 38 | } api; 39 | 40 | struct { 41 | int queue_attach; 42 | int queue_detach; 43 | int queue_dispatch; 44 | } stat; 45 | 46 | OneEntries queue; 47 | 48 | unsigned int next_class_index; 49 | }; 50 | 51 | 52 | extern OneDev one_devs[NUM_MINORS]; 53 | extern OneCore *one_core; 54 | extern struct proc_dir_entry *one_proc_dir[NUM_MINORS]; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /one/packet.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | Packet holds data to be transferred 14 | */ 15 | 16 | #ifdef HAVE_LINUX_CONFIG_H 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include "debug.h" 30 | #include "onedev.h" 31 | #include "list.h" 32 | #include "packet.h" 33 | 34 | 35 | 36 | 37 | /******************************************************************************/ 38 | 39 | OnePacket * 40 | OnePacket_New() 41 | { 42 | OnePacket *packet; 43 | 44 | ONE_DEBUG( "%s()\n", __FUNCTION__ ); 45 | 46 | packet = one_core_malloc( one_core, sizeof(OnePacket) ); 47 | if (!packet) 48 | return NULL; 49 | 50 | packet->link.magic = 0; 51 | packet->link.prev = NULL; 52 | packet->link.next = NULL; 53 | 54 | packet->magic = 0; 55 | packet->flush = false; 56 | 57 | memset( &packet->header, 0, sizeof(packet->header) ); 58 | 59 | D_MAGIC_SET( packet, OnePacket ); 60 | 61 | return packet; 62 | } 63 | 64 | void 65 | OnePacket_Free( OnePacket *packet ) 66 | { 67 | ONE_DEBUG( "%s( %p )\n", __FUNCTION__, packet ); 68 | 69 | D_MAGIC_ASSERT( packet, OnePacket ); 70 | 71 | D_ASSERT( packet->link.prev == NULL ); 72 | D_ASSERT( packet->link.next == NULL ); 73 | 74 | D_MAGIC_CLEAR( packet ); 75 | 76 | one_core_free( one_core, packet ); 77 | } 78 | 79 | int 80 | OnePacket_Write( OnePacket *packet, 81 | OnePacketHeader *header, 82 | const struct iovec *iov, 83 | size_t iov_count ) 84 | { 85 | size_t i, len, offset; 86 | 87 | ONE_DEBUG( "%s( packet %p, queue_id %u, flags 0x%x, size %u, uncompressed %u, iov %p, iov_count %zu )\n", 88 | __FUNCTION__, packet, header->queue_id, header->flags, header->size, header->uncompressed, iov, iov_count ); 89 | 90 | D_MAGIC_ASSERT( packet, OnePacket ); 91 | 92 | /* Queue ID must already be set */ 93 | D_ASSERT( packet->header.queue_id == header->queue_id ); 94 | 95 | /* When appending, check certain limitations */ 96 | if (packet->header.size) { 97 | D_ASSERT( !(packet->header.flags & ONE_PACKET_COMPRESSED) ); 98 | 99 | /* Cannot append to compressed packets */ 100 | if (packet->header.flags & ONE_PACKET_COMPRESSED) 101 | return -EIO; 102 | 103 | /* Cannot append with different flags, e.g. compression */ 104 | if (packet->header.flags != header->flags) 105 | return -EIO; 106 | } 107 | 108 | /* Check if packet has enough free space */ 109 | if (packet->header.size + header->size > ONE_MAX_PACKET_SIZE) 110 | return -E2BIG; 111 | 112 | D_ASSERT( (header->size == header->uncompressed) || (header->flags & ONE_PACKET_COMPRESSED) ); 113 | 114 | len = header->size; 115 | offset = packet->header.size; 116 | 117 | for (i=0; i len) 119 | return -EINVAL; 120 | 121 | if (copy_from_user( packet->buf + offset, iov[i].iov_base, iov[i].iov_len )) 122 | return -EFAULT; 123 | 124 | offset += iov[i].iov_len; 125 | len -= iov[i].iov_len; 126 | } 127 | 128 | /* Insufficient data from iovec? */ 129 | if (len) 130 | return -EINVAL; 131 | 132 | /* Update packet header */ 133 | packet->header.flags = header->flags; 134 | packet->header.size += header->size; 135 | packet->header.uncompressed += header->uncompressed; 136 | 137 | return 0; 138 | } 139 | 140 | int 141 | OnePacket_Read( OnePacket *packet, 142 | const struct iovec *iov, 143 | size_t iov_count, 144 | size_t offset ) 145 | { 146 | size_t i, iov_start = 0, read_offset = 0, left; 147 | 148 | ONE_DEBUG( "%s( packet %p, queue_id %u, flags 0x%x, size %u, uncompressed %u, iov %p, iov_count %zu, offset %zu )\n", __FUNCTION__, 149 | packet, packet->header.queue_id, packet->header.flags, packet->header.size, packet->header.uncompressed, iov, iov_count, offset ); 150 | 151 | D_MAGIC_ASSERT( packet, OnePacket ); 152 | 153 | left = sizeof(OnePacketHeader) + packet->header.size; 154 | 155 | for (i=0; i offset) { 157 | size_t iov_offset = offset - iov_start; 158 | size_t copy = iov[i].iov_len - iov_offset; 159 | 160 | if (copy > left) 161 | copy = left; 162 | 163 | if (read_offset < sizeof(OnePacketHeader)) { 164 | size_t header_copy = sizeof(OnePacketHeader) - read_offset; 165 | 166 | if (header_copy > copy) 167 | header_copy = copy; 168 | 169 | if (copy_to_user( iov[i].iov_base + iov_offset, &packet->header + read_offset, header_copy )) 170 | return -EFAULT; 171 | 172 | iov_offset += header_copy; 173 | copy -= header_copy; 174 | 175 | offset += header_copy; 176 | read_offset += header_copy; 177 | left -= header_copy; 178 | } 179 | 180 | if (copy) { 181 | if (copy_to_user( iov[i].iov_base + iov_offset, packet->buf + read_offset - sizeof(OnePacketHeader), copy )) 182 | return -EFAULT; 183 | 184 | offset += copy; 185 | read_offset += copy; 186 | left -= copy; 187 | } 188 | } 189 | 190 | iov_start += iov[i].iov_len; 191 | } 192 | 193 | D_ASSERT( left == 0 ); 194 | 195 | return 0; 196 | } 197 | 198 | -------------------------------------------------------------------------------- /one/packet.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__PACKET_H__ 13 | #define __ONE__PACKET_H__ 14 | 15 | #include "onedev.h" 16 | #include "types.h" 17 | 18 | 19 | struct __One_OnePacket { 20 | DirectLink link; 21 | 22 | int magic; 23 | 24 | bool flush; 25 | 26 | OnePacketHeader header; 27 | 28 | char buf[ONE_MAX_PACKET_SIZE]; 29 | }; 30 | 31 | 32 | OnePacket *OnePacket_New ( void ); 33 | 34 | void OnePacket_Free ( OnePacket *packet ); 35 | 36 | int OnePacket_Write( OnePacket *packet, 37 | OnePacketHeader *header, 38 | const struct iovec *iov, 39 | size_t iov_count ); 40 | 41 | int OnePacket_Read ( OnePacket *packet, 42 | const struct iovec *iov, 43 | size_t iov_count, 44 | size_t offset ); 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /one/queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__QUEUE_H__ 13 | #define __ONE__QUEUE_H__ 14 | 15 | #include "onedev.h" 16 | #include "types.h" 17 | 18 | 19 | 20 | struct __One_OneQueue { 21 | OneEntry entry; 22 | 23 | OneID one_id; 24 | 25 | OneQueueFlags flags; 26 | 27 | DirectLink *nodes; /* target nodes for a virtual queue (forwards) */ 28 | 29 | int dispatch_count; 30 | 31 | bool destroyed; 32 | 33 | OneTarget *target; 34 | 35 | long long receive_us; 36 | int receive_tid; 37 | 38 | long long dispatch_us; 39 | int dispatch_tid; 40 | }; 41 | 42 | 43 | /* module init/cleanup */ 44 | 45 | int one_queue_init ( OneDev *dev ); 46 | void one_queue_deinit( OneDev *dev ); 47 | 48 | 49 | /* public API */ 50 | 51 | int one_queue_new ( OneApp *oneapp, 52 | OneQueueNew *queue_new ); 53 | 54 | int one_queue_destroy ( OneApp *oneapp, 55 | OneQueueDestroy *queue_destroy ); 56 | 57 | int one_queue_attach ( OneApp *oneapp, 58 | OneQueueAttach *queue_attach ); 59 | 60 | int one_queue_detach ( OneApp *oneapp, 61 | OneQueueDetach *queue_detach ); 62 | 63 | int one_queue_dispatch ( OneApp *oneapp, 64 | OneQueueDispatch *queue_dispatch ); 65 | 66 | int one_queue_receive ( OneApp *oneapp, 67 | OneQueueReceive *queue_receive ); 68 | 69 | int one_queue_dispatch_receive( OneApp *oneapp, 70 | OneQueueDispatchReceive *queue_dispatch_receive ); 71 | 72 | int one_queue_wakeup ( OneApp *oneapp, 73 | OneQueueWakeUp *queue_wakeup ); 74 | 75 | int one_queue_stamp_receive ( OneApp *oneapp, 76 | OneQID queue_id ); 77 | 78 | 79 | /* internal functions */ 80 | 81 | void one_queue_destroy_all ( OneApp *oneapp ); 82 | 83 | void one_queue_detach_all ( OneDev *dev, 84 | OneQID queue_id ); 85 | 86 | 87 | int one_queue_add_target ( OneQID queue_id, 88 | OneQID target_id, 89 | OneTarget *target ); 90 | 91 | int one_queue_remove_target ( OneQID queue_id, 92 | OneQID target_id, 93 | OneTarget *target ); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /one/single/onecore_impl.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | Written by Denis Oliver Kropp 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 11 | 2 of the License, or (at your option) any later version. 12 | */ 13 | 14 | #include 15 | #include 16 | #ifdef HAVE_LINUX_CONFIG_H 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "debug.h" 25 | 26 | #include "onecore.h" 27 | #include "one_udp.h" 28 | 29 | 30 | int 31 | one_core_enter( OneCore **ret_core ) 32 | { 33 | OneCore *core; 34 | 35 | ONE_DEBUG( "%s()\n", __FUNCTION__ ); 36 | 37 | D_ASSERT( ret_core != NULL ); 38 | 39 | core = kzalloc( sizeof(OneCore), GFP_KERNEL ); 40 | if (!core) 41 | return -ENOMEM; 42 | 43 | /* Initialise IDs with 1000, below is reserved for static IDs */ 44 | core->ids = 1000; 45 | 46 | sema_init( &core->lock, 1 ); 47 | 48 | D_MAGIC_SET( core, OneCore ); 49 | 50 | *ret_core = core; 51 | 52 | return 0; 53 | } 54 | 55 | void 56 | one_core_exit( OneCore *core ) 57 | { 58 | ONE_DEBUG( "%s()\n", __FUNCTION__ ); 59 | 60 | D_MAGIC_ASSERT( core, OneCore ); 61 | 62 | 63 | D_MAGIC_CLEAR( core ); 64 | 65 | kfree( core ); 66 | } 67 | 68 | void 69 | one_core_cleanup( OneCore *core ) 70 | { 71 | ONE_DEBUG( "%s()\n", __FUNCTION__ ); 72 | 73 | D_MAGIC_ASSERT( core, OneCore ); 74 | } 75 | 76 | pid_t 77 | one_core_pid( OneCore *core ) 78 | { 79 | D_MAGIC_ASSERT( core, OneCore ); 80 | 81 | return current->pid; 82 | } 83 | 84 | u32 85 | one_core_new_id( OneCore *core ) 86 | { 87 | D_MAGIC_ASSERT( core, OneCore ); 88 | 89 | return ++core->ids; 90 | } 91 | 92 | bool 93 | one_core_is_local( OneCore *core, 94 | u32 id ) 95 | { 96 | return true; 97 | } 98 | 99 | int 100 | one_core_dispatch( OneCore *core, 101 | OneApp *app, 102 | const OnePacketHeader *header, 103 | const struct iovec *iov, 104 | size_t iov_count ) 105 | { 106 | return -EIO; 107 | } 108 | 109 | int 110 | one_core_attach( OneCore *core, 111 | OneApp *app, 112 | OneQueueAttach *queue_attach ) 113 | { 114 | return -EIO; 115 | } 116 | 117 | int 118 | one_core_detach( OneCore *core, 119 | OneApp *app, 120 | OneQueueDetach *queue_detach ) 121 | { 122 | return -EIO; 123 | } 124 | 125 | 126 | void * 127 | one_core_malloc( OneCore *core, 128 | size_t size ) 129 | { 130 | D_MAGIC_ASSERT( core, OneCore ); 131 | 132 | return kmalloc( size, GFP_KERNEL ); 133 | } 134 | 135 | void 136 | one_core_free( OneCore *core, 137 | void *ptr ) 138 | { 139 | D_MAGIC_ASSERT( core, OneCore ); 140 | 141 | kfree( ptr ); 142 | } 143 | 144 | 145 | void 146 | one_core_lock( OneCore *core ) 147 | { 148 | D_MAGIC_ASSERT( core, OneCore ); 149 | 150 | down( &core->lock ); 151 | } 152 | 153 | void 154 | one_core_unlock( OneCore *core ) 155 | { 156 | D_MAGIC_ASSERT( core, OneCore ); 157 | 158 | up( &core->lock ); 159 | } 160 | 161 | 162 | int 163 | one_core_wq_init( OneCore *core, 164 | OneWaitQueue *queue ) 165 | { 166 | D_MAGIC_ASSERT( core, OneCore ); 167 | 168 | memset( queue, 0, sizeof(OneWaitQueue) ); 169 | 170 | init_waitqueue_head( &queue->queue ); 171 | 172 | D_MAGIC_SET( queue, OneWaitQueue ); 173 | 174 | return 0; 175 | } 176 | 177 | void 178 | one_core_wq_deinit( OneCore *core, 179 | OneWaitQueue *queue ) 180 | { 181 | D_MAGIC_ASSERT( core, OneCore ); 182 | D_MAGIC_ASSERT( queue, OneWaitQueue ); 183 | 184 | D_MAGIC_CLEAR( queue ); 185 | } 186 | 187 | void 188 | one_core_wq_wait( OneCore *core, 189 | OneWaitQueue *queue, 190 | int *timeout_ms ) 191 | { 192 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 193 | DEFINE_WAIT(wait); 194 | 195 | int timeout = 0; 196 | 197 | if (timeout_ms) 198 | timeout = *timeout_ms * HZ / 1000; 199 | 200 | 201 | D_MAGIC_ASSERT( core, OneCore ); 202 | D_MAGIC_ASSERT( queue, OneWaitQueue ); 203 | 204 | prepare_to_wait( &queue->queue, &wait, TASK_INTERRUPTIBLE ); 205 | 206 | one_core_unlock( core ); 207 | 208 | if (timeout_ms) { 209 | timeout = schedule_timeout(timeout); 210 | if (timeout) { 211 | timeout = timeout * 1000 / HZ; 212 | 213 | *timeout_ms = timeout ? timeout : 1; 214 | } 215 | else 216 | *timeout_ms = 0; 217 | } 218 | else 219 | schedule(); 220 | 221 | one_core_lock( core ); 222 | 223 | finish_wait( &queue->queue, &wait ); 224 | #else 225 | wait_queue_t wait; 226 | int timeout = 0; 227 | 228 | if (timeout_ms) 229 | timeout = *timeout_ms * HZ / 1000; 230 | 231 | 232 | D_MAGIC_ASSERT( core, OneCore ); 233 | D_MAGIC_ASSERT( queue, OneWaitQueue ); 234 | 235 | init_waitqueue_entry(&wait, current); 236 | 237 | current->state = TASK_INTERRUPTIBLE; 238 | 239 | write_lock( &queue->queue.lock); 240 | __add_wait_queue( &queue->queue, &wait); 241 | write_unlock( &queue->queue.lock ); 242 | 243 | one_core_unlock( core ); 244 | 245 | if (timeout_ms) { 246 | timeout = schedule_timeout(timeout); 247 | if (timeout) { 248 | timeout = timeout * 1000 / HZ; 249 | 250 | *timeout_ms = timeout ? timeout : 1; 251 | } 252 | else 253 | *timeout_ms = 0; 254 | } 255 | else 256 | schedule(); 257 | 258 | one_core_lock( core ); 259 | 260 | write_lock( &queue->queue.lock ); 261 | __remove_wait_queue( &queue->queue, &wait ); 262 | write_unlock( &queue->queue.lock ); 263 | #endif 264 | } 265 | 266 | void 267 | one_core_wq_wake( OneCore *core, 268 | OneWaitQueue *queue ) 269 | { 270 | D_MAGIC_ASSERT( core, OneCore ); 271 | D_MAGIC_ASSERT( queue, OneWaitQueue ); 272 | 273 | wake_up_all( &queue->queue ); 274 | } 275 | 276 | long long 277 | one_core_stamp( OneCore *core ) 278 | { 279 | return direct_clock_get_micros(); 280 | } 281 | 282 | -------------------------------------------------------------------------------- /one/single/onecore_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | Written by Denis Oliver Kropp 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 11 | 2 of the License, or (at your option) any later version. 12 | */ 13 | 14 | #ifndef __ONE__ONECORE_IMPL_H__ 15 | #define __ONE__ONECORE_IMPL_H__ 16 | 17 | #include 18 | 19 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) 20 | #include 21 | #else 22 | #include 23 | #endif 24 | 25 | #include 26 | 27 | #include "types.h" 28 | 29 | 30 | struct __One_OneCore { 31 | int magic; 32 | 33 | u32 ids; 34 | 35 | struct semaphore lock; 36 | }; 37 | 38 | 39 | typedef struct { 40 | int magic; 41 | 42 | wait_queue_head_t queue; 43 | } OneWaitQueue; 44 | 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /one/target.c: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | 11 | -- 12 | 13 | Target is an abstracted storage for packets sent via a Queue 14 | */ 15 | 16 | #ifdef HAVE_LINUX_CONFIG_H 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | #include 23 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) 24 | #include 25 | #endif 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include "debug.h" 33 | #include "onedev.h" 34 | #include "target.h" 35 | 36 | 37 | /******************************************************************************/ 38 | 39 | int 40 | OneTarget_New( OneTarget_InitFunc Init, 41 | void *ctx, 42 | size_t data_size, 43 | OneTarget **ret_target ) 44 | { 45 | int ret; 46 | OneTarget *target; 47 | 48 | ONE_DEBUG( "%s()\n", __FUNCTION__ ); 49 | 50 | target = one_core_malloc( one_core, sizeof(OneTarget) + data_size ); 51 | if (!target) 52 | return -ENOMEM; 53 | 54 | memset( target, 0, sizeof(OneTarget) + data_size ); 55 | 56 | target->data = target + 1; 57 | 58 | ret = Init( target, ctx ); 59 | if (ret) { 60 | one_core_free( one_core, target ); 61 | return ret; 62 | } 63 | 64 | D_MAGIC_SET( target, OneTarget ); 65 | 66 | *ret_target = target; 67 | 68 | return 0; 69 | } 70 | 71 | void 72 | OneTarget_Destroy( OneTarget *target ) 73 | { 74 | ONE_DEBUG( "%s( %p )\n", __FUNCTION__, target ); 75 | 76 | D_MAGIC_ASSERT( target, OneTarget ); 77 | 78 | 79 | D_MAGIC_CLEAR( target ); 80 | 81 | one_core_free( one_core, target ); 82 | } 83 | 84 | -------------------------------------------------------------------------------- /one/target.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__TARGET_H__ 13 | #define __ONE__TARGET_H__ 14 | 15 | #include "onedev.h" 16 | #include "types.h" 17 | 18 | 19 | 20 | typedef void (*OneTarget_DestroyFunc) ( OneTarget *target ); 21 | 22 | typedef int (*OneTarget_DispatchFunc)( OneTarget *target, 23 | OnePacketHeader *header, 24 | const struct iovec *iov, 25 | size_t iov_count ); 26 | 27 | typedef int (*OneTarget_WakeUpFunc) ( OneTarget *target ); 28 | 29 | typedef int (*OneTarget_InitFunc) ( OneTarget *target, 30 | void *ctx ); 31 | 32 | 33 | struct __One_OneTarget { 34 | int magic; 35 | 36 | void *data; 37 | 38 | OneTarget_DestroyFunc Destroy; 39 | OneTarget_DispatchFunc Dispatch; 40 | OneTarget_WakeUpFunc WakeUp; 41 | }; 42 | 43 | 44 | int OneTarget_New ( OneTarget_InitFunc Init, 45 | void *ctx, 46 | size_t data_size, 47 | OneTarget **ret_target ); 48 | 49 | void OneTarget_Destroy( OneTarget *target ); 50 | 51 | 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /one/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | (c) Copyright 2011 Denis Oliver Kropp 3 | 4 | All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 9 | 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __ONE__TYPES_H__ 13 | #define __ONE__TYPES_H__ 14 | 15 | #include 16 | 17 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) 18 | typedef enum { 19 | false = 0, 20 | true = !false 21 | } bool; 22 | #endif 23 | 24 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) 25 | #define PDE_DATA(x) (PDE(x)->data) 26 | #endif 27 | 28 | typedef struct __One_OneApp OneApp; 29 | typedef struct __One_OneDev OneDev; 30 | typedef struct __One_OnePacket OnePacket; 31 | typedef struct __One_OneQueue OneQueue; 32 | typedef struct __One_OneTarget OneTarget; 33 | typedef struct __One_OneUDP OneUDP; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /tests/.cvsignore: -------------------------------------------------------------------------------- 1 | calls 2 | latency 3 | throughput 4 | throughput_pipe 5 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += `pkg-config --cflags direct` 2 | LDFLAGS += `pkg-config --libs direct` 3 | 4 | CFLAGS += -Wall -O3 5 | LDFLAGS += -lpthread 6 | 7 | all: calls latency throughput throughput_pipe 8 | 9 | clean: 10 | rm -f calls latency throughput throughput_pipe 11 | -------------------------------------------------------------------------------- /tests/calls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Fusion Kernel Module 3 | * 4 | * (c) Copyright 2002 Convergence GmbH 5 | * 6 | * Written by Denis Oliver Kropp 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 12 | * 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | 36 | static int fd; /* File descriptor of the Fusion Kernel Device */ 37 | static pthread_t receiver; /* Thread reading messages from the device. */ 38 | 39 | static int counter = 0; 40 | static volatile int last_count = 0; 41 | 42 | /* 43 | * A simple example call handler 44 | */ 45 | typedef int (*CallHandler)(int caller, /* fusion id of the caller */ 46 | int call_arg, /* optional call parameter */ 47 | void *call_ptr, /* optional call parameter */ 48 | void *ctx /* optional handler context */); 49 | 50 | static int 51 | call_handler (int caller, /* fusion id of the caller */ 52 | int call_arg, /* optional call parameter */ 53 | void *call_ptr, /* optional call parameter */ 54 | void *ctx /* optional handler context */) 55 | { 56 | counter++; 57 | 58 | if (counter == 1) 59 | D_INFO( "FusionTest/Calls: Processed first call...\n" ); 60 | 61 | if (counter == last_count) 62 | D_INFO( "FusionTest/Calls: Processed last (%dth) call...\n", last_count ); 63 | else if (counter % 1000 == 0) 64 | D_INFO( "FusionTest/Calls: Processed %dth call...\n", counter ); 65 | 66 | return 0; 67 | } 68 | 69 | /* 70 | * Generic call dispatcher 71 | */ 72 | static void 73 | process_call_message (int call_id, FusionCallMessage *msg) 74 | { 75 | FusionCallReturn call_ret; 76 | CallHandler handler = msg->handler; 77 | 78 | call_ret.call_id = call_id; 79 | call_ret.serial = msg->serial; 80 | call_ret.val = handler (msg->caller, 81 | msg->call_arg, 82 | msg->call_ptr, 83 | msg->ctx); 84 | 85 | if (ioctl (fd, FUSION_CALL_RETURN, &call_ret)) 86 | perror ("FUSION_CALL_RETURN"); 87 | } 88 | 89 | /* 90 | * Message receiver thread 91 | */ 92 | static void * 93 | receiver_thread (void *arg) 94 | { 95 | int len; 96 | char buf[1024]; 97 | 98 | D_INFO( "FusionTest/Calls: Running dispatcher loop...\n" ); 99 | 100 | /* Read as many messages as possible at once. */ 101 | while ((len = read (fd, buf, 1024)) > 0 || errno == EINTR) 102 | { 103 | /* Current position within the buffer. */ 104 | char *buf_p = buf; 105 | 106 | /* Shutdown? */ 107 | pthread_testcancel(); 108 | 109 | /* Possibly interrupted during blocking read. */ 110 | if (len <= 0) 111 | continue; 112 | 113 | /* While there are still messages in the buffer... */ 114 | while (buf_p < buf + len) 115 | { 116 | /* Header of next message is at the current buffer location. */ 117 | FusionReadMessage *header = (FusionReadMessage*) buf_p; 118 | 119 | /* Its data follows immediately. */ 120 | void *data = buf_p + sizeof(FusionReadMessage); 121 | 122 | /* Process the message depending on its type (origin). */ 123 | switch (header->msg_type) 124 | { 125 | case FMT_CALL: 126 | process_call_message (header->msg_id, data); 127 | break; 128 | default: 129 | break; 130 | } 131 | 132 | /* Shutdown? */ 133 | pthread_testcancel(); 134 | 135 | /* Next message header follows immediately. */ 136 | buf_p = data + header->msg_size; 137 | } 138 | } 139 | 140 | perror ("receiver thread failure"); 141 | 142 | return NULL; 143 | } 144 | 145 | int 146 | main (int argc, char *argv[]) 147 | { 148 | long c = 0, d = 0; 149 | FusionCallNew call_new; 150 | FusionCallExecute call_exec; 151 | struct timeval t1, t2; 152 | 153 | FusionEnter enter = {{ FUSION_API_MAJOR, FUSION_API_MINOR }}; 154 | 155 | direct_initialize(); 156 | 157 | D_INFO( "FusionTest/Calls: Opening Fusion Device...\n" ); 158 | 159 | /* Open the Fusion Kernel Device. */ 160 | fd = open ("/dev/fusion0", O_RDWR | O_EXCL); 161 | if (fd < 0) 162 | fd = open ("/dev/fusion/0", O_RDWR | O_EXCL); 163 | if (fd < 0) 164 | { 165 | perror ("opening /dev/fusion failed"); 166 | return -1; 167 | } 168 | 169 | D_INFO( "FusionTest/Calls: Entering Fusion World...\n" ); 170 | 171 | /* Query our fusion id. */ 172 | if (ioctl (fd, FUSION_ENTER, &enter)) 173 | { 174 | perror ("FUSION_ENTER failed"); 175 | close (fd); 176 | return -2; 177 | } 178 | 179 | D_INFO( "FusionTest/Calls: Entered as Fusionee with ID %lu.\n", enter.fusion_id ); 180 | 181 | /* Install the call handler. */ 182 | call_new.handler = call_handler; 183 | call_new.ctx = NULL; 184 | 185 | if (ioctl (fd, FUSION_CALL_NEW, &call_new)) 186 | { 187 | perror ("FUSION_CALL_NEW failed"); 188 | close (fd); 189 | return -3; 190 | } 191 | 192 | D_INFO( "FusionTest/Calls: Created Call with ID %d.\n", call_new.call_id ); 193 | 194 | /* Start the receiver thread. */ 195 | D_INFO( "FusionTest/Calls: Starting thread...\n" ); 196 | pthread_create (&receiver, NULL, receiver_thread, NULL); 197 | 198 | /* Flush disk buffers and wait for the receiver being up. */ 199 | D_INFO( "FusionTest/Calls: Syncing disks...\n" ); 200 | sync(); 201 | usleep (100000); 202 | 203 | /* Specify call id to execute. */ 204 | call_exec.call_id = call_new.call_id; 205 | call_exec.flags = FCEF_ONEWAY; 206 | 207 | /* Stop time before call loop. */ 208 | gettimeofday (&t1, NULL); 209 | 210 | D_INFO( "FusionTest/Calls: Running calling loop...\n" ); 211 | 212 | /* Do as many calls as possible (in 3 seconds). */ 213 | while (d < 3000000) 214 | { 215 | if (ioctl (fd, FUSION_CALL_EXECUTE, &call_exec)) 216 | perror ("FUSION_CALL_EXECUTE"); 217 | 218 | /* Stop time every 1000 calls. */ 219 | if (++c % 1000 == 0) 220 | { 221 | gettimeofday (&t2, NULL); 222 | 223 | d = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec); 224 | } 225 | } 226 | 227 | last_count = c; 228 | 229 | D_INFO( "FusionTest/Calls: Destroying call...\n" ); 230 | 231 | /* Destroy the call. */ 232 | if (ioctl (fd, FUSION_CALL_DESTROY, &call_new.call_id)) 233 | perror ("FUSION_CALL_DESTROY"); 234 | 235 | gettimeofday (&t2, NULL); 236 | 237 | D_INFO( "FusionTest/Calls: Destroyed call.\n" ); 238 | 239 | /* Print message. */ 240 | D_INFO ("FusionTest/Calls: Executed %llu asynchronous RPC calls per second.\n", 241 | counter * 1000000ULL / ((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec))); 242 | 243 | /* Stop the receiver. */ 244 | pthread_cancel (receiver); 245 | pthread_join (receiver, NULL); 246 | 247 | /* Close the Fusion Kernel Device. */ 248 | close (fd); 249 | 250 | return 0; 251 | } 252 | -------------------------------------------------------------------------------- /tests/latency.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Fusion Kernel Module 3 | * 4 | * (c) Copyright 2002 Convergence GmbH 5 | * 6 | * Written by Denis Oliver Kropp 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 12 | * 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | typedef struct { 31 | int nr; 32 | struct timeval stamp; 33 | } TestMessage; 34 | 35 | static int fd; /* File descriptor of the Fusion Kernel Device */ 36 | static pthread_t receiver; /* Thread reading messages from the device. */ 37 | 38 | static void 39 | process_sent_message (int msg_id, int msg_size, void *msg_data) 40 | { 41 | long d; 42 | struct timeval t; 43 | TestMessage *message = (TestMessage*) msg_data; 44 | 45 | /* Stop time of arrival. */ 46 | gettimeofday (&t, NULL); 47 | 48 | /* Calculate latency. */ 49 | d = ((t.tv_sec - message->stamp.tv_sec) * 1000000 + 50 | (t.tv_usec - message->stamp.tv_usec)); 51 | 52 | /* Print message. */ 53 | printf ("Got message with %ld.%03ld ms latency.\n", 54 | d / 1000, d % 1000); 55 | } 56 | 57 | static void 58 | process_reactor_message (int reactor_id, int msg_size, void *msg_data) 59 | { 60 | /* This program doesn't make use of reactors. */ 61 | } 62 | 63 | static void * 64 | receiver_thread (void *arg) 65 | { 66 | int len; 67 | char buf[1024]; 68 | 69 | /* Read as many messages as possible at once. */ 70 | while ((len = read (fd, buf, 1024)) > 0 || errno == EINTR) 71 | { 72 | /* Current position within the buffer. */ 73 | char *buf_p = buf; 74 | 75 | /* Shutdown? */ 76 | pthread_testcancel(); 77 | 78 | /* Possibly interrupted during blocking read. */ 79 | if (len <= 0) 80 | continue; 81 | 82 | /* While there are still messages in the buffer... */ 83 | while (buf_p < buf + len) 84 | { 85 | /* Header of next message is at the current buffer location. */ 86 | FusionReadMessage *header = (FusionReadMessage*) buf_p; 87 | 88 | /* Its data follows immediately. */ 89 | void *data = buf_p + sizeof(FusionReadMessage); 90 | 91 | /* Process the message depending on its type (origin). */ 92 | switch (header->msg_type) 93 | { 94 | case FMT_SEND: 95 | process_sent_message (header->msg_id, 96 | header->msg_size, data); 97 | break; 98 | case FMT_REACTOR: 99 | process_reactor_message (header->msg_id, 100 | header->msg_size, data); 101 | break; 102 | default: 103 | break; 104 | } 105 | 106 | /* Shutdown? */ 107 | pthread_testcancel(); 108 | 109 | /* Next message header follows immediately. */ 110 | buf_p = data + header->msg_size; 111 | } 112 | } 113 | 114 | perror ("receiver thread failure"); 115 | 116 | return NULL; 117 | } 118 | 119 | int 120 | main (int argc, char *argv[]) 121 | { 122 | int n; 123 | FusionEnter enter = {{ FUSION_API_MAJOR, FUSION_API_MINOR }}; 124 | 125 | /* Open the Fusion Kernel Device. */ 126 | fd = open ("/dev/fusion0", O_RDWR); 127 | if (fd < 0) 128 | fd = open ("/dev/fusion/0", O_RDWR); 129 | if (fd < 0) 130 | { 131 | perror ("opening /dev/fusion failed"); 132 | return -1; 133 | } 134 | 135 | /* Query our fusion id. */ 136 | if (ioctl (fd, FUSION_ENTER, &enter)) 137 | { 138 | perror ("FUSION_ENTER failed"); 139 | close (fd); 140 | return -2; 141 | } 142 | 143 | /* Start the receiver thread. */ 144 | pthread_create (&receiver, NULL, receiver_thread, NULL); 145 | 146 | /* Wait for the receiver being up. */ 147 | usleep (100000); 148 | 149 | /* Send some messages. */ 150 | for (n = 0; n < 10; n++) 151 | { 152 | FusionSendMessage send; /* Message header. */ 153 | TestMessage message; /* Message data. */ 154 | 155 | /* Fill message header. */ 156 | send.fusion_id = enter.fusion_id; /* recipient */ 157 | send.msg_id = 0; /* optional */ 158 | send.msg_size = sizeof(TestMessage); 159 | send.msg_data = &message; 160 | 161 | /* Set message number. */ 162 | message.nr = n; 163 | 164 | /* Stop time of departure. */ 165 | gettimeofday (&message.stamp, NULL); 166 | 167 | /* Post the message. */ 168 | if (ioctl (fd, FUSION_SEND_MESSAGE, &send)) 169 | perror ("FUSION_SEND_MESSAGE failed"); 170 | 171 | /* Wait some random time. */ 172 | usleep (rand()%100000 + 100000); 173 | } 174 | 175 | /* Stop the receiver. */ 176 | pthread_cancel (receiver); 177 | pthread_join (receiver, NULL); 178 | 179 | /* Close the Fusion Kernel Device. */ 180 | close (fd); 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /tests/throughput.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Fusion Kernel Module 3 | * 4 | * (c) Copyright 2002 Convergence GmbH 5 | * 6 | * Written by Denis Oliver Kropp 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 12 | * 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | typedef struct { 33 | int nr; 34 | } TestMessage; 35 | 36 | static int fd; /* File descriptor of the Fusion Kernel Device */ 37 | static pthread_t receiver; /* Thread reading messages from the device. */ 38 | 39 | static int last_nr = 0; 40 | 41 | static void 42 | process_sent_message (int msg_id, int msg_size, void *msg_data) 43 | { 44 | TestMessage *message = (TestMessage*) msg_data; 45 | 46 | last_nr = message->nr; 47 | } 48 | 49 | static void 50 | process_reactor_message (int reactor_id, int msg_size, void *msg_data) 51 | { 52 | /* This program doesn't make use of reactors. */ 53 | } 54 | 55 | static void * 56 | receiver_thread (void *arg) 57 | { 58 | int len; 59 | char buf[1024]; 60 | 61 | #if 0 62 | struct sched_param param; 63 | 64 | param.sched_priority = 1; 65 | 66 | if (sched_setscheduler (0, SCHED_FIFO, ¶m)) 67 | perror ("sched_setscheduler"); 68 | #endif 69 | 70 | /* Read as many messages as possible at once. */ 71 | while ((len = read (fd, buf, 1024)) > 0 || errno == EINTR) 72 | { 73 | /* Current position within the buffer. */ 74 | char *buf_p = buf; 75 | 76 | /* Shutdown? */ 77 | pthread_testcancel(); 78 | 79 | /* Possibly interrupted during blocking read. */ 80 | if (len <= 0) 81 | continue; 82 | 83 | /* While there are still messages in the buffer... */ 84 | while (buf_p < buf + len) 85 | { 86 | /* Header of next message is at the current buffer location. */ 87 | FusionReadMessage *header = (FusionReadMessage*) buf_p; 88 | 89 | /* Its data follows immediately. */ 90 | void *data = buf_p + sizeof(FusionReadMessage); 91 | 92 | /* Process the message depending on its type (origin). */ 93 | switch (header->msg_type) 94 | { 95 | case FMT_SEND: 96 | process_sent_message (header->msg_id, 97 | header->msg_size, data); 98 | break; 99 | case FMT_REACTOR: 100 | process_reactor_message (header->msg_id, 101 | header->msg_size, data); 102 | break; 103 | default: 104 | break; 105 | } 106 | 107 | /* Shutdown? */ 108 | pthread_testcancel(); 109 | 110 | /* Next message header follows immediately. */ 111 | buf_p = data + header->msg_size; 112 | } 113 | } 114 | 115 | perror ("receiver thread failure"); 116 | 117 | return NULL; 118 | } 119 | 120 | int 121 | main (int argc, char *argv[]) 122 | { 123 | int n; 124 | int synchronous = 0; 125 | long d; 126 | struct timeval t1, t2; 127 | 128 | FusionEnter enter = {{ FUSION_API_MAJOR, FUSION_API_MINOR }}; 129 | 130 | /* Open the Fusion Kernel Device. */ 131 | fd = open ("/dev/fusion0", O_RDWR); 132 | if (fd < 0) 133 | fd = open ("/dev/fusion/0", O_RDWR); 134 | if (fd < 0) 135 | { 136 | perror ("opening /dev/fusion failed"); 137 | return -1; 138 | } 139 | 140 | /* Query our fusion id. */ 141 | if (ioctl (fd, FUSION_ENTER, &enter)) 142 | { 143 | perror ("FUSION_ENTER failed"); 144 | close (fd); 145 | return -2; 146 | } 147 | 148 | /* Start the receiver thread. */ 149 | pthread_create (&receiver, NULL, receiver_thread, NULL); 150 | 151 | /* Wait for the receiver being up. */ 152 | usleep (100000); 153 | 154 | /* Stop time before sending the messages. */ 155 | gettimeofday (&t1, NULL); 156 | 157 | /* Send some messages. */ 158 | for (n = 0; n < 4000000; n++) 159 | { 160 | FusionSendMessage send; /* Message header. */ 161 | TestMessage message; /* Message data. */ 162 | 163 | /* Fill message header. */ 164 | send.fusion_id = enter.fusion_id; /* recipient */ 165 | send.msg_id = 0; /* optional */ 166 | send.msg_size = sizeof(TestMessage); 167 | send.msg_data = &message; 168 | 169 | /* Set message number. */ 170 | message.nr = n; 171 | 172 | /* Post the message. */ 173 | if (ioctl (fd, FUSION_SEND_MESSAGE, &send)) 174 | perror ("FUSION_SEND_MESSAGE failed"); 175 | 176 | if (last_nr == n) 177 | synchronous++; 178 | } 179 | 180 | /* Wait for all messages to arrive. */ 181 | while (last_nr < n-1) 182 | sched_yield(); 183 | 184 | /* Stop time after having received all messages. */ 185 | gettimeofday (&t2, NULL); 186 | 187 | /* Calculate time it took. */ 188 | d = (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000; 189 | 190 | /* Print message. */ 191 | printf ("Sent/received %lu messages per second (%d%% synchronous).\n", 192 | 4000000000U / d, synchronous * 100 / 4000000); 193 | 194 | /* Stop the receiver. */ 195 | pthread_cancel (receiver); 196 | pthread_join (receiver, NULL); 197 | 198 | /* Close the Fusion Kernel Device. */ 199 | close (fd); 200 | 201 | return 0; 202 | } 203 | -------------------------------------------------------------------------------- /tests/throughput_pipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Fusion Kernel Module 3 | * 4 | * (c) Copyright 2002 Convergence GmbH 5 | * 6 | * Written by Denis Oliver Kropp 7 | * 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 12 | * 2 of the License, or (at your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | typedef struct { 33 | int nr; 34 | } TestMessage; 35 | 36 | static int fd[2]; /* File descriptors of the pipe */ 37 | static pthread_t receiver; /* Thread reading messages from the pipe. */ 38 | 39 | static int last_nr = 0; 40 | 41 | static void 42 | process_sent_message (int msg_id, int msg_size, void *msg_data) 43 | { 44 | TestMessage *message = (TestMessage*) msg_data; 45 | 46 | last_nr = message->nr; 47 | } 48 | 49 | static void 50 | process_reactor_message (int reactor_id, int msg_size, void *msg_data) 51 | { 52 | /* This program doesn't make use of reactors. */ 53 | } 54 | 55 | static void * 56 | receiver_thread (void *arg) 57 | { 58 | int len; 59 | char buf[1024]; 60 | 61 | #if 0 62 | struct sched_param param; 63 | 64 | param.sched_priority = 1; 65 | 66 | if (sched_setscheduler (0, SCHED_FIFO, ¶m)) 67 | perror ("sched_setscheduler"); 68 | #endif 69 | 70 | /* Read as many messages as possible at once. */ 71 | while ((len = read (fd[0], buf, 1024)) > 0 || errno == EINTR) 72 | { 73 | /* Current position within the buffer. */ 74 | char *buf_p = buf; 75 | 76 | /* Shutdown? */ 77 | pthread_testcancel(); 78 | 79 | /* Possibly interrupted during blocking read. */ 80 | if (len <= 0) 81 | continue; 82 | 83 | /* While there are still messages in the buffer... */ 84 | while (buf_p < buf + len) 85 | { 86 | /* Header of next message is at the current buffer location. */ 87 | FusionReadMessage *header = (FusionReadMessage*) buf_p; 88 | 89 | /* Its data follows immediately. */ 90 | void *data = buf_p + sizeof(FusionReadMessage); 91 | 92 | /* Process the message depending on its type (origin). */ 93 | switch (header->msg_type) 94 | { 95 | case FMT_SEND: 96 | process_sent_message (header->msg_id, 97 | header->msg_size, data); 98 | break; 99 | case FMT_REACTOR: 100 | process_reactor_message (header->msg_id, 101 | header->msg_size, data); 102 | break; 103 | default: 104 | break; 105 | } 106 | 107 | /* Shutdown? */ 108 | pthread_testcancel(); 109 | 110 | /* Next message header follows immediately. */ 111 | buf_p = data + header->msg_size; 112 | } 113 | } 114 | 115 | perror ("receiver thread failure"); 116 | 117 | return NULL; 118 | } 119 | 120 | int 121 | main (int argc, char *argv[]) 122 | { 123 | int n; 124 | int synchronous = 0; 125 | long d; 126 | struct timeval t1, t2; 127 | 128 | /* Open the pipe. */ 129 | if (pipe (fd)) 130 | { 131 | perror ("pipe() failed"); 132 | return -1; 133 | } 134 | 135 | /* Start the receiver thread. */ 136 | pthread_create (&receiver, NULL, receiver_thread, NULL); 137 | 138 | /* Wait for the receiver being up. */ 139 | usleep (100000); 140 | 141 | /* Stop time before sending the messages. */ 142 | gettimeofday (&t1, NULL); 143 | 144 | /* Send some messages. */ 145 | for (n = 0; n < 4000000; n++) 146 | { 147 | struct { 148 | FusionReadMessage header; /* Message header. */ 149 | TestMessage message; /* Message data. */ 150 | } data; 151 | 152 | /* Fill message header. */ 153 | data.header.msg_type = FMT_SEND; 154 | data.header.msg_id = 0; 155 | data.header.msg_size = sizeof(TestMessage); 156 | 157 | /* Set message number. */ 158 | data.message.nr = n; 159 | 160 | /* Post the message. */ 161 | if (write (fd[1], &data, sizeof(data)) < 0) 162 | { 163 | perror ("write() failed"); 164 | return -1; 165 | } 166 | 167 | if (last_nr == n) 168 | synchronous++; 169 | } 170 | 171 | /* Wait for all messages to arrive. */ 172 | while (last_nr < n-1) 173 | sched_yield(); 174 | 175 | /* Stop time after having received all messages. */ 176 | gettimeofday (&t2, NULL); 177 | 178 | /* Calculate time it took. */ 179 | d = (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000; 180 | 181 | /* Print message. */ 182 | printf ("Sent/received %lu messages per second (%d%% synchronous).\n", 183 | 4000000000U / d, synchronous * 100 / 4000000); 184 | 185 | /* Stop the receiver. */ 186 | pthread_cancel (receiver); 187 | pthread_join (receiver, NULL); 188 | 189 | /* Close the pipe. */ 190 | close (fd[0]); 191 | close (fd[1]); 192 | 193 | return 0; 194 | } 195 | --------------------------------------------------------------------------------