summaryrefslogtreecommitdiff
path: root/Source/DirectFB/lib
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/lib')
-rwxr-xr-xSource/DirectFB/lib/Makefile.am7
-rwxr-xr-xSource/DirectFB/lib/Makefile.in557
-rwxr-xr-xSource/DirectFB/lib/direct/Makefile.am138
-rwxr-xr-xSource/DirectFB/lib/direct/Makefile.in769
-rwxr-xr-xSource/DirectFB/lib/direct/armasm_memcpy.S421
-rwxr-xr-xSource/DirectFB/lib/direct/armasm_memcpy.h32
-rwxr-xr-xSource/DirectFB/lib/direct/build.h.in51
-rwxr-xr-xSource/DirectFB/lib/direct/clock.c135
-rwxr-xr-xSource/DirectFB/lib/direct/clock.h45
-rwxr-xr-xSource/DirectFB/lib/direct/conf.c348
-rwxr-xr-xSource/DirectFB/lib/direct/conf.h92
-rwxr-xr-xSource/DirectFB/lib/direct/debug.c430
-rwxr-xr-xSource/DirectFB/lib/direct/debug.h287
-rwxr-xr-xSource/DirectFB/lib/direct/direct.c197
-rwxr-xr-xSource/DirectFB/lib/direct/direct.h49
-rwxr-xr-xSource/DirectFB/lib/direct/direct.pc.in13
-rwxr-xr-xSource/DirectFB/lib/direct/fastlz.c97
-rwxr-xr-xSource/DirectFB/lib/direct/fastlz.h52
-rwxr-xr-xSource/DirectFB/lib/direct/flz.c555
-rwxr-xr-xSource/DirectFB/lib/direct/flz.h100
-rwxr-xr-xSource/DirectFB/lib/direct/hash.c268
-rwxr-xr-xSource/DirectFB/lib/direct/hash.h61
-rwxr-xr-xSource/DirectFB/lib/direct/interface.c474
-rwxr-xr-xSource/DirectFB/lib/direct/interface.h215
-rwxr-xr-xSource/DirectFB/lib/direct/interface_implementation.h91
-rwxr-xr-xSource/DirectFB/lib/direct/list.c35
-rwxr-xr-xSource/DirectFB/lib/direct/list.h224
-rwxr-xr-xSource/DirectFB/lib/direct/log.c414
-rwxr-xr-xSource/DirectFB/lib/direct/log.h89
-rwxr-xr-xSource/DirectFB/lib/direct/mem.c350
-rwxr-xr-xSource/DirectFB/lib/direct/mem.h84
-rwxr-xr-xSource/DirectFB/lib/direct/memcpy.c265
-rwxr-xr-xSource/DirectFB/lib/direct/memcpy.h51
-rwxr-xr-xSource/DirectFB/lib/direct/messages.c215
-rwxr-xr-xSource/DirectFB/lib/direct/messages.h173
-rwxr-xr-xSource/DirectFB/lib/direct/modules.c463
-rwxr-xr-xSource/DirectFB/lib/direct/modules.h95
-rwxr-xr-xSource/DirectFB/lib/direct/ppc_asm.h115
-rwxr-xr-xSource/DirectFB/lib/direct/ppcasm_memcpy.S77
-rwxr-xr-xSource/DirectFB/lib/direct/ppcasm_memcpy.h7
-rwxr-xr-xSource/DirectFB/lib/direct/ppcasm_memcpy_cachable.S180
-rwxr-xr-xSource/DirectFB/lib/direct/serial.h118
-rwxr-xr-xSource/DirectFB/lib/direct/signals.c480
-rwxr-xr-xSource/DirectFB/lib/direct/signals.h70
-rwxr-xr-xSource/DirectFB/lib/direct/stream.c2286
-rwxr-xr-xSource/DirectFB/lib/direct/stream.h129
-rwxr-xr-xSource/DirectFB/lib/direct/system.c68
-rwxr-xr-xSource/DirectFB/lib/direct/system.h40
-rwxr-xr-xSource/DirectFB/lib/direct/thread.c795
-rwxr-xr-xSource/DirectFB/lib/direct/thread.h168
-rwxr-xr-xSource/DirectFB/lib/direct/trace.c676
-rwxr-xr-xSource/DirectFB/lib/direct/trace.h98
-rwxr-xr-xSource/DirectFB/lib/direct/tree.c307
-rwxr-xr-xSource/DirectFB/lib/direct/tree.h67
-rwxr-xr-xSource/DirectFB/lib/direct/types.h169
-rwxr-xr-xSource/DirectFB/lib/direct/utf8.c36
-rwxr-xr-xSource/DirectFB/lib/direct/utf8.h80
-rwxr-xr-xSource/DirectFB/lib/direct/util.c519
-rwxr-xr-xSource/DirectFB/lib/direct/util.h330
-rwxr-xr-xSource/DirectFB/lib/fusion/Makefile.am100
-rwxr-xr-xSource/DirectFB/lib/fusion/Makefile.in804
-rwxr-xr-xSource/DirectFB/lib/fusion/arena.c566
-rwxr-xr-xSource/DirectFB/lib/fusion/arena.h62
-rwxr-xr-xSource/DirectFB/lib/fusion/build.h.in36
-rwxr-xr-xSource/DirectFB/lib/fusion/call.c581
-rwxr-xr-xSource/DirectFB/lib/fusion/call.h74
-rwxr-xr-xSource/DirectFB/lib/fusion/conf.c113
-rwxr-xr-xSource/DirectFB/lib/fusion/conf.h55
-rwxr-xr-xSource/DirectFB/lib/fusion/fusion.c2658
-rwxr-xr-xSource/DirectFB/lib/fusion/fusion.h142
-rwxr-xr-xSource/DirectFB/lib/fusion/fusion.pc.in11
-rwxr-xr-xSource/DirectFB/lib/fusion/fusion_internal.h185
-rwxr-xr-xSource/DirectFB/lib/fusion/hash.c560
-rwxr-xr-xSource/DirectFB/lib/fusion/hash.h179
-rwxr-xr-xSource/DirectFB/lib/fusion/lock.c687
-rwxr-xr-xSource/DirectFB/lib/fusion/lock.h122
-rwxr-xr-xSource/DirectFB/lib/fusion/object.c640
-rwxr-xr-xSource/DirectFB/lib/fusion/object.h279
-rwxr-xr-xSource/DirectFB/lib/fusion/property.c530
-rwxr-xr-xSource/DirectFB/lib/fusion/property.h114
-rwxr-xr-xSource/DirectFB/lib/fusion/protocol.h119
-rwxr-xr-xSource/DirectFB/lib/fusion/reactor.c1868
-rwxr-xr-xSource/DirectFB/lib/fusion/reactor.h197
-rwxr-xr-xSource/DirectFB/lib/fusion/ref.c849
-rwxr-xr-xSource/DirectFB/lib/fusion/ref.h134
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/Makefile.am31
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/Makefile.in565
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/fake.c163
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/heap.c802
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/pool.c954
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/pool.h69
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/shm.c337
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/shm.h48
-rwxr-xr-xSource/DirectFB/lib/fusion/shm/shm_internal.h264
-rwxr-xr-xSource/DirectFB/lib/fusion/shmalloc.c679
-rwxr-xr-xSource/DirectFB/lib/fusion/shmalloc.h124
-rwxr-xr-xSource/DirectFB/lib/fusion/types.h87
-rwxr-xr-xSource/DirectFB/lib/fusion/vector.c230
-rwxr-xr-xSource/DirectFB/lib/fusion/vector.h164
-rwxr-xr-xSource/DirectFB/lib/voodoo/Makefile.am82
-rwxr-xr-xSource/DirectFB/lib/voodoo/Makefile.in666
-rwxr-xr-xSource/DirectFB/lib/voodoo/app.h66
-rwxr-xr-xSource/DirectFB/lib/voodoo/build.h.in34
-rwxr-xr-xSource/DirectFB/lib/voodoo/client.c208
-rwxr-xr-xSource/DirectFB/lib/voodoo/client.h44
-rwxr-xr-xSource/DirectFB/lib/voodoo/compat.h8
-rwxr-xr-xSource/DirectFB/lib/voodoo/conf.c253
-rwxr-xr-xSource/DirectFB/lib/voodoo/conf.h58
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection.cpp70
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection.h60
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_link.cpp331
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_link.h106
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_packet.cpp368
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_packet.h61
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_packet_old.cpp433
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_packet_old.h87
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_raw.cpp341
-rwxr-xr-xSource/DirectFB/lib/voodoo/connection_raw.h60
-rwxr-xr-xSource/DirectFB/lib/voodoo/dispatcher.cpp231
-rwxr-xr-xSource/DirectFB/lib/voodoo/dispatcher.h71
-rwxr-xr-xSource/DirectFB/lib/voodoo/instance.cpp107
-rwxr-xr-xSource/DirectFB/lib/voodoo/instance.h61
-rwxr-xr-xSource/DirectFB/lib/voodoo/interface.c114
-rwxr-xr-xSource/DirectFB/lib/voodoo/interface.h52
-rwxr-xr-xSource/DirectFB/lib/voodoo/internal.h40
-rwxr-xr-xSource/DirectFB/lib/voodoo/ivoodooplayer.c247
-rwxr-xr-xSource/DirectFB/lib/voodoo/ivoodooplayer.h74
-rwxr-xr-xSource/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.c359
-rwxr-xr-xSource/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.h41
-rwxr-xr-xSource/DirectFB/lib/voodoo/ivoodooplayer_requestor.c330
-rwxr-xr-xSource/DirectFB/lib/voodoo/link.h78
-rwxr-xr-xSource/DirectFB/lib/voodoo/manager.cpp937
-rwxr-xr-xSource/DirectFB/lib/voodoo/manager.h279
-rwxr-xr-xSource/DirectFB/lib/voodoo/manager_c.cpp553
-rwxr-xr-xSource/DirectFB/lib/voodoo/message.h258
-rwxr-xr-xSource/DirectFB/lib/voodoo/mutex.c105
-rwxr-xr-xSource/DirectFB/lib/voodoo/mutex.h142
-rwxr-xr-xSource/DirectFB/lib/voodoo/packet.h285
-rwxr-xr-xSource/DirectFB/lib/voodoo/play.c935
-rwxr-xr-xSource/DirectFB/lib/voodoo/play.h146
-rwxr-xr-xSource/DirectFB/lib/voodoo/play_internal.h89
-rwxr-xr-xSource/DirectFB/lib/voodoo/play_server.c430
-rwxr-xr-xSource/DirectFB/lib/voodoo/play_server.h79
-rwxr-xr-xSource/DirectFB/lib/voodoo/server.c459
-rwxr-xr-xSource/DirectFB/lib/voodoo/server.h52
-rwxr-xr-xSource/DirectFB/lib/voodoo/types.h97
-rwxr-xr-xSource/DirectFB/lib/voodoo/unix/interfaces_unix.c237
-rwxr-xr-xSource/DirectFB/lib/voodoo/unix/link_unix.c567
-rwxr-xr-xSource/DirectFB/lib/voodoo/unix/link_unix_1408limit.c422
-rwxr-xr-xSource/DirectFB/lib/voodoo/voodoo.pc.in11
-rwxr-xr-xSource/DirectFB/lib/voodoo/waitqueue.h117
151 files changed, 42280 insertions, 0 deletions
diff --git a/Source/DirectFB/lib/Makefile.am b/Source/DirectFB/lib/Makefile.am
new file mode 100755
index 0000000..89ac43d
--- /dev/null
+++ b/Source/DirectFB/lib/Makefile.am
@@ -0,0 +1,7 @@
+## Makefile.am for DirectFB/lib
+
+if ENABLE_VOODOO
+VOODOO_DIR = voodoo
+endif
+
+SUBDIRS = direct fusion $(VOODOO_DIR)
diff --git a/Source/DirectFB/lib/Makefile.in b/Source/DirectFB/lib/Makefile.in
new file mode 100755
index 0000000..5c1ee83
--- /dev/null
+++ b/Source/DirectFB/lib/Makefile.in
@@ -0,0 +1,557 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = lib
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = direct fusion voodoo
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@ENABLE_VOODOO_TRUE@VOODOO_DIR = voodoo
+SUBDIRS = direct fusion $(VOODOO_DIR)
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/lib/direct/Makefile.am b/Source/DirectFB/lib/direct/Makefile.am
new file mode 100755
index 0000000..c7604cd
--- /dev/null
+++ b/Source/DirectFB/lib/direct/Makefile.am
@@ -0,0 +1,138 @@
+## Makefile.am for DirectFB/lib/direct
+
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\"
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = direct.pc
+
+EXTRA_DIST = \
+ armasm_memcpy.S \
+ armasm_memcpy.h \
+ ppcasm_memcpy.S \
+ ppcasm_memcpy_cachable.S \
+ ppcasm_memcpy.h \
+ ppc_asm.h
+
+if BUILDPPCASM
+if HAVE_LINUX
+ppcasm_sources = ppcasm_memcpy.S ppcasm_memcpy_cachable.S
+else
+ppcasm_sources = ppcasm_memcpy.S
+endif
+
+ppcasm_headers = ppcasm_memcpy.h ppc_asm.h
+endif
+
+if BUILDARMASM
+armasm_sources = armasm_memcpy.S
+armasm_header = armasm_memcpy.h
+endif
+
+# If the old location isn't cleared, builds of external modules fail
+install-exec-local:
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/direct
+
+
+includedir = @INCLUDEDIR@/direct
+
+include_HEADERS = \
+ $(ppcasm_headers) \
+ $(armasm_headers) \
+ build.h \
+ clock.h \
+ conf.h \
+ debug.h \
+ direct.h \
+ hash.h \
+ interface.h \
+ interface_implementation.h \
+ list.h \
+ log.h \
+ mem.h \
+ memcpy.h \
+ messages.h \
+ modules.h \
+ serial.h \
+ signals.h \
+ stream.h \
+ system.h \
+ thread.h \
+ trace.h \
+ tree.h \
+ types.h \
+ utf8.h \
+ fastlz.h \
+ flz.h \
+ util.h
+
+
+lib_LTLIBRARIES = libdirect.la
+
+libdirect_la_SOURCES = \
+ $(ppcasm_sources) \
+ $(armasm_sources) \
+ clock.c \
+ conf.c \
+ debug.c \
+ direct.c \
+ hash.c \
+ interface.c \
+ list.c \
+ log.c \
+ mem.c \
+ memcpy.c \
+ messages.c \
+ modules.c \
+ signals.c \
+ stream.c \
+ system.c \
+ trace.c \
+ tree.c \
+ thread.c \
+ utf8.c \
+ fastlz.c \
+ flz.c \
+ util.c
+
+libdirect_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ $(DFB_LDFLAGS)
+
+
+#
+## and now rebuild the static version with the *correct* object files
+#
+if BUILD_STATIC
+
+clean-local:
+ rm -f libdirect_fixed.a
+
+all-local: libdirect_fixed.a
+
+libdirect_fixed.a: .libs/libdirect.a
+ rm -f libdirect_fixed.a
+ ${AR} cru libdirect_fixed.a `find . -name "*.o" | grep -v '.libs' | grep -v dtest`
+ ${RANLIB} libdirect_fixed.a
+ cp -pf libdirect_fixed.a .libs/libdirect.a
+
+.libs/libdirect.a: libdirect.la
+
+else
+
+clean-local:
+
+all-local:
+
+endif
+
+
+include $(top_srcdir)/rules/nmfile.make
diff --git a/Source/DirectFB/lib/direct/Makefile.in b/Source/DirectFB/lib/direct/Makefile.in
new file mode 100755
index 0000000..efb1a74
--- /dev/null
+++ b/Source/DirectFB/lib/direct/Makefile.in
@@ -0,0 +1,769 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = $(am__include_HEADERS_DIST) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/build.h.in \
+ $(srcdir)/direct.pc.in $(top_srcdir)/rules/nmfile.make
+subdir = lib/direct
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = build.h direct.pc
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(includedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libdirect_la_LIBADD =
+am__libdirect_la_SOURCES_DIST = ppcasm_memcpy.S \
+ ppcasm_memcpy_cachable.S armasm_memcpy.S clock.c conf.c \
+ debug.c direct.c hash.c interface.c list.c log.c mem.c \
+ memcpy.c messages.c modules.c signals.c stream.c system.c \
+ trace.c tree.c thread.c utf8.c util.c
+@BUILDPPCASM_TRUE@@HAVE_LINUX_FALSE@am__objects_1 = ppcasm_memcpy.lo
+@BUILDPPCASM_TRUE@@HAVE_LINUX_TRUE@am__objects_1 = ppcasm_memcpy.lo \
+@BUILDPPCASM_TRUE@@HAVE_LINUX_TRUE@ ppcasm_memcpy_cachable.lo
+@BUILDARMASM_TRUE@am__objects_2 = armasm_memcpy.lo
+am_libdirect_la_OBJECTS = $(am__objects_1) $(am__objects_2) clock.lo \
+ conf.lo debug.lo direct.lo hash.lo interface.lo list.lo log.lo \
+ mem.lo memcpy.lo messages.lo modules.lo signals.lo stream.lo \
+ system.lo trace.lo tree.lo thread.lo utf8.lo util.lo
+libdirect_la_OBJECTS = $(am_libdirect_la_OBJECTS)
+libdirect_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libdirect_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
+LTCPPASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libdirect_la_SOURCES)
+DIST_SOURCES = $(am__libdirect_la_SOURCES_DIST)
+pkgconfigDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(pkgconfig_DATA)
+am__include_HEADERS_DIST = ppcasm_memcpy.h ppc_asm.h build.h clock.h \
+ conf.h debug.h direct.h hash.h interface.h \
+ interface_implementation.h list.h log.h mem.h memcpy.h \
+ messages.h modules.h serial.h signals.h stream.h system.h \
+ thread.h trace.h tree.h types.h utf8.h util.h
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @INCLUDEDIR@/direct
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\"
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = direct.pc
+EXTRA_DIST = \
+ armasm_memcpy.S \
+ armasm_memcpy.h \
+ ppcasm_memcpy.S \
+ ppcasm_memcpy_cachable.S \
+ ppcasm_memcpy.h \
+ ppc_asm.h
+
+@BUILDPPCASM_TRUE@@HAVE_LINUX_FALSE@ppcasm_sources = ppcasm_memcpy.S
+@BUILDPPCASM_TRUE@@HAVE_LINUX_TRUE@ppcasm_sources = ppcasm_memcpy.S ppcasm_memcpy_cachable.S
+@BUILDPPCASM_TRUE@ppcasm_headers = ppcasm_memcpy.h ppc_asm.h
+@BUILDARMASM_TRUE@armasm_sources = armasm_memcpy.S
+@BUILDARMASM_TRUE@armasm_header = armasm_memcpy.h
+include_HEADERS = \
+ $(ppcasm_headers) \
+ $(armasm_headers) \
+ build.h \
+ clock.h \
+ conf.h \
+ debug.h \
+ direct.h \
+ hash.h \
+ interface.h \
+ interface_implementation.h \
+ list.h \
+ log.h \
+ mem.h \
+ memcpy.h \
+ messages.h \
+ modules.h \
+ serial.h \
+ signals.h \
+ stream.h \
+ system.h \
+ thread.h \
+ trace.h \
+ tree.h \
+ types.h \
+ utf8.h \
+ util.h
+
+lib_LTLIBRARIES = libdirect.la
+libdirect_la_SOURCES = \
+ $(ppcasm_sources) \
+ $(armasm_sources) \
+ clock.c \
+ conf.c \
+ debug.c \
+ direct.c \
+ hash.c \
+ interface.c \
+ list.c \
+ log.c \
+ mem.c \
+ memcpy.c \
+ messages.c \
+ modules.c \
+ signals.c \
+ stream.c \
+ system.c \
+ trace.c \
+ tree.c \
+ thread.c \
+ utf8.c \
+ util.c
+
+libdirect_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ $(DFB_LDFLAGS)
+
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@LIBTONM = $(LTLIBRARIES:.la=-$(LT_RELEASE).so.$(LT_BINARY))
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/nmfile.make $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/direct/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lib/direct/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+build.h: $(top_builddir)/config.status $(srcdir)/build.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+direct.pc: $(top_builddir)/config.status $(srcdir)/direct.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libdirect.la: $(libdirect_la_OBJECTS) $(libdirect_la_DEPENDENCIES)
+ $(libdirect_la_LINK) -rpath $(libdir) $(libdirect_la_OBJECTS) $(libdirect_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armasm_memcpy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/direct.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcpy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modules.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ppcasm_memcpy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ppcasm_memcpy_cachable.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signals.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@
+
+.S.o:
+@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCCAS_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ $<
+
+.S.obj:
+@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCCAS_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.S.lo:
+@am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCCAS_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(LTCPPASCOMPILE) -c -o $@ $<
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) all-local
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@BUILD_SHARED_FALSE@install-data-local:
+@ENABLE_TRACE_FALSE@install-data-local:
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-includeHEADERS \
+ install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-exec-local install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-pkgconfigDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am all-local check check-am clean \
+ clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-data-local install-dvi install-dvi-am \
+ install-exec install-exec-am install-exec-local install-html \
+ install-html-am install-includeHEADERS install-info \
+ install-info-am install-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-pkgconfigDATA
+
+
+# If the old location isn't cleared, builds of external modules fail
+install-exec-local:
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/direct
+
+#
+#
+
+@BUILD_STATIC_TRUE@clean-local:
+@BUILD_STATIC_TRUE@ rm -f libdirect_fixed.a
+
+@BUILD_STATIC_TRUE@all-local: libdirect_fixed.a
+
+@BUILD_STATIC_TRUE@libdirect_fixed.a: .libs/libdirect.a
+@BUILD_STATIC_TRUE@ rm -f libdirect_fixed.a
+@BUILD_STATIC_TRUE@ ${AR} cru libdirect_fixed.a `find . -name "*.o" | grep -v '.libs' | grep -v dtest`
+@BUILD_STATIC_TRUE@ ${RANLIB} libdirect_fixed.a
+@BUILD_STATIC_TRUE@ cp -pf libdirect_fixed.a .libs/libdirect.a
+
+@BUILD_STATIC_TRUE@.libs/libdirect.a: libdirect.la
+
+@BUILD_STATIC_FALSE@clean-local:
+
+@BUILD_STATIC_FALSE@all-local:
+
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@install-data-local:
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ mkdir -p -- "$(DESTDIR)$(libdir)"
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ nm -n ".libs/$(LIBTONM)" > "$(DESTDIR)$(libdir)/nm-n.$(LIBTONM)"
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/lib/direct/armasm_memcpy.S b/Source/DirectFB/lib/direct/armasm_memcpy.S
new file mode 100755
index 0000000..e422168
--- /dev/null
+++ b/Source/DirectFB/lib/direct/armasm_memcpy.S
@@ -0,0 +1,421 @@
+/*
+ * ARM memcpy asm replacement.
+ *
+ * Copyright (C) 2009 Bluush Dev Team.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#if USE_ARMASM && !WORDS_BIGENDIAN
+
+#define _LABEL(f) f :
+
+.global direct_armasm_memcpy
+
+ .code 32
+
+_LABEL(direct_armasm_memcpy)
+ cmp r1, r0
+ bcc Lmemcpy_backwards
+
+ moveq r0, #0
+ moveq pc, lr
+
+ stmdb sp!, {r0, lr}
+ subs r2, r2, #4
+ blt Lmemcpy_fl4
+ ands r12, r0, #3
+ bne Lmemcpy_fdestul
+ ands r12, r1, #3
+ bne Lmemcpy_fsrcul
+
+_LABEL(Lmemcpy_ft8)
+ subs r2, r2, #8
+ blt Lmemcpy_fl12
+ subs r2, r2, #0x14
+ blt Lmemcpy_fl32
+ stmdb sp!, {r4}
+
+_LABEL(Lmemcpy_floop32)
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge Lmemcpy_floop32
+
+ cmn r2, #0x10
+ ldmgeia r1!, {r3, r4, r12, lr}
+ stmgeia r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ ldmia sp!, {r4}
+
+_LABEL(Lmemcpy_fl32)
+ adds r2, r2, #0x14
+
+
+_LABEL(Lmemcpy_floop12)
+ ldmgeia r1!, {r3, r12, lr}
+ stmgeia r0!, {r3, r12, lr}
+ subges r2, r2, #0x0c
+ bge Lmemcpy_floop12
+
+_LABEL(Lmemcpy_fl12)
+ adds r2, r2, #8
+ blt Lmemcpy_fl4
+
+ subs r2, r2, #4
+ ldrlt r3, [r1], #4
+ strlt r3, [r0], #4
+ ldmgeia r1!, {r3, r12}
+ stmgeia r0!, {r3, r12}
+ subge r2, r2, #4
+
+_LABEL(Lmemcpy_fl4)
+ adds r2, r2, #4
+ ldmeqia sp!, {r0, pc}
+
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ ldmia sp!, {r0, pc}
+
+
+_LABEL(Lmemcpy_fdestul)
+ rsb r12, r12, #4
+ cmp r12, #2
+
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ subs r2, r2, r12
+ blt Lmemcpy_fl4
+
+ ands r12, r1, #3
+ beq Lmemcpy_ft8
+
+
+_LABEL(Lmemcpy_fsrcul)
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ cmp r12, #2
+ bgt Lmemcpy_fsrcul3
+ beq Lmemcpy_fsrcul2
+ cmp r2, #0x0c
+ blt Lmemcpy_fsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+_LABEL(Lmemcpy_fsrcul1loop16)
+ mov r3, lr, lsr #8
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, lr, lsl #24
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge Lmemcpy_fsrcul1loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_fsrcul1l4
+
+_LABEL(Lmemcpy_fsrcul1loop4)
+ mov r12, lr, lsr #8
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #24
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge Lmemcpy_fsrcul1loop4
+
+_LABEL(Lmemcpy_fsrcul1l4)
+ sub r1, r1, #3
+ b Lmemcpy_fl4
+
+_LABEL(Lmemcpy_fsrcul2)
+ cmp r2, #0x0c
+ blt Lmemcpy_fsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+_LABEL(Lmemcpy_fsrcul2loop16)
+ mov r3, lr, lsr #16
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, lr, lsl #16
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge Lmemcpy_fsrcul2loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_fsrcul2l4
+
+_LABEL(Lmemcpy_fsrcul2loop4)
+ mov r12, lr, lsr #16
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #16
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge Lmemcpy_fsrcul2loop4
+
+_LABEL(Lmemcpy_fsrcul2l4)
+ sub r1, r1, #2
+ b Lmemcpy_fl4
+
+_LABEL(Lmemcpy_fsrcul3)
+ cmp r2, #0x0c
+ blt Lmemcpy_fsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+_LABEL(Lmemcpy_fsrcul3loop16)
+ mov r3, lr, lsr #24
+ ldmia r1!, {r4, r5, r12, lr}
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, lr, lsl #8
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge Lmemcpy_fsrcul3loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_fsrcul3l4
+
+_LABEL(Lmemcpy_fsrcul3loop4)
+ mov r12, lr, lsr #24
+ ldr lr, [r1], #4
+ orr r12, r12, lr, lsl #8
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge Lmemcpy_fsrcul3loop4
+
+_LABEL(Lmemcpy_fsrcul3l4)
+ sub r1, r1, #1
+ b Lmemcpy_fl4
+
+_LABEL(Lmemcpy_backwards)
+ add r1, r1, r2
+ add r0, r0, r2
+ subs r2, r2, #4
+ blt Lmemcpy_bl4
+ ands r12, r0, #3
+ bne Lmemcpy_bdestul
+ ands r12, r1, #3
+ bne Lmemcpy_bsrcul
+
+_LABEL(Lmemcpy_bt8)
+ subs r2, r2, #8
+ blt Lmemcpy_bl12
+ stmdb sp!, {r4, lr}
+ subs r2, r2, #0x14
+ blt Lmemcpy_bl32
+
+
+_LABEL(Lmemcpy_bloop32)
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge Lmemcpy_bloop32
+
+_LABEL(Lmemcpy_bl32)
+ cmn r2, #0x10
+ ldmgedb r1!, {r3, r4, r12, lr}
+ stmgedb r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ adds r2, r2, #0x14
+ ldmgedb r1!, {r3, r12, lr}
+ stmgedb r0!, {r3, r12, lr}
+ subge r2, r2, #0x0c
+ ldmia sp!, {r4, lr}
+
+_LABEL(Lmemcpy_bl12)
+ adds r2, r2, #8
+ blt Lmemcpy_bl4
+ subs r2, r2, #4
+ ldrlt r3, [r1, #-4]!
+ strlt r3, [r0, #-4]!
+ ldmgedb r1!, {r3, r12}
+ stmgedb r0!, {r3, r12}
+ subge r2, r2, #4
+
+_LABEL(Lmemcpy_bl4)
+ adds r2, r2, #4
+ moveq pc, lr
+
+ cmp r2, #2
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrgeb r3, [r1, #-1]!
+ strgeb r3, [r0, #-1]!
+ ldrgtb r3, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ mov pc, lr
+
+
+_LABEL(Lmemcpy_bdestul)
+ cmp r12, #2
+
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrgeb r3, [r1, #-1]!
+ strgeb r3, [r0, #-1]!
+ ldrgtb r3, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ subs r2, r2, r12
+ blt Lmemcpy_bl4
+ ands r12, r1, #3
+ beq Lmemcpy_bt8
+
+
+_LABEL(Lmemcpy_bsrcul)
+ bic r1, r1, #3
+ ldr r3, [r1, #0]
+ cmp r12, #2
+ blt Lmemcpy_bsrcul1
+ beq Lmemcpy_bsrcul2
+ cmp r2, #0x0c
+ blt Lmemcpy_bsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+_LABEL(Lmemcpy_bsrcul3loop16)
+ mov lr, r3, lsl #8
+ ldmdb r1!, {r3-r5, r12}
+ orr lr, lr, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r3, lsr #24
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge Lmemcpy_bsrcul3loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_bsrcul3l4
+
+_LABEL(Lmemcpy_bsrcul3loop4)
+ mov r12, r3, lsl #8
+ ldr r3, [r1, #-4]!
+ orr r12, r12, r3, lsr #24
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge Lmemcpy_bsrcul3loop4
+
+_LABEL(Lmemcpy_bsrcul3l4)
+ add r1, r1, #3
+ b Lmemcpy_bl4
+
+_LABEL(Lmemcpy_bsrcul2)
+ cmp r2, #0x0c
+ blt Lmemcpy_bsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+_LABEL(Lmemcpy_bsrcul2loop16)
+ mov lr, r3, lsl #16
+ ldmdb r1!, {r3-r5, r12}
+ orr lr, lr, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r3, lsr #16
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge Lmemcpy_bsrcul2loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_bsrcul2l4
+
+_LABEL(Lmemcpy_bsrcul2loop4)
+ mov r12, r3, lsl #16
+ ldr r3, [r1, #-4]!
+ orr r12, r12, r3, lsr #16
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge Lmemcpy_bsrcul2loop4
+
+_LABEL(Lmemcpy_bsrcul2l4)
+ add r1, r1, #2
+ b Lmemcpy_bl4
+
+_LABEL(Lmemcpy_bsrcul1)
+ cmp r2, #0x0c
+ blt Lmemcpy_bsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+_LABEL(Lmemcpy_bsrcul1loop32)
+ mov lr, r3, lsl #24
+ ldmdb r1!, {r3-r5, r12}
+ orr lr, lr, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r3, lsr #8
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge Lmemcpy_bsrcul1loop32
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt Lmemcpy_bsrcul1l4
+
+_LABEL(Lmemcpy_bsrcul1loop4)
+ mov r12, r3, lsl #24
+ ldr r3, [r1, #-4]!
+ orr r12, r12, r3, lsr #8
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge Lmemcpy_bsrcul1loop4
+
+_LABEL(Lmemcpy_bsrcul1l4)
+ add r1, r1, #1
+ b Lmemcpy_bl4
+
+
+ .ltorg
+
+#endif /* USE_ARMASM && !WORDS_BIGENDIAN */
+
+
diff --git a/Source/DirectFB/lib/direct/armasm_memcpy.h b/Source/DirectFB/lib/direct/armasm_memcpy.h
new file mode 100755
index 0000000..27138ab
--- /dev/null
+++ b/Source/DirectFB/lib/direct/armasm_memcpy.h
@@ -0,0 +1,32 @@
+/*
+ * ARM memcpy asm replacement.
+ *
+ * Copyright (C) 2009 Bluush Dev Team.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ARMASM_MEMCPY_H__
+#define __ARMASM_MEMCPY_H__
+
+#if USE_ARMASM && !WORDS_BIGENDIAN
+
+void *direct_armasm_memcpy ( void *dest, const void *src, size_t n);
+
+#endif /* USE_ARMASM && !WORDS_BIGENDIAN */
+
+#endif /* __ARMASM_MEMCPY_H__ */
+
diff --git a/Source/DirectFB/lib/direct/build.h.in b/Source/DirectFB/lib/direct/build.h.in
new file mode 100755
index 0000000..926cea5
--- /dev/null
+++ b/Source/DirectFB/lib/direct/build.h.in
@@ -0,0 +1,51 @@
+/*
+ (c) Copyright 2000-2002 convergence integrated media GmbH.
+ (c) Copyright 2002-2004 convergence GmbH.
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org> and
+ Ville Syrjälä <syrjala@sci.fi>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__BUILD_H__
+#define __DIRECT__BUILD_H__
+
+#define DIRECT_BUILD_DEBUG (@DIRECT_BUILD_DEBUG@)
+#define DIRECT_BUILD_DEBUGS (@DIRECT_BUILD_DEBUGS@)
+#define DIRECT_BUILD_TRACE (@DIRECT_BUILD_TRACE@)
+#define DIRECT_BUILD_TEXT (@DIRECT_BUILD_TEXT@)
+#define DIRECT_BUILD_GETTID (@DIRECT_BUILD_GETTID@)
+#define DIRECT_BUILD_NETWORK (@DIRECT_BUILD_NETWORK@)
+#define DIRECT_BUILD_STDBOOL (@DIRECT_BUILD_STDBOOL@)
+
+
+#if !DIRECT_BUILD_DEBUGS
+#if defined(DIRECT_ENABLE_DEBUG) || defined(DIRECT_FORCE_DEBUG)
+#define DIRECT_MINI_DEBUG
+#endif
+#undef DIRECT_ENABLE_DEBUG
+#ifdef DIRECT_FORCE_DEBUG
+#warning DIRECT_FORCE_DEBUG used with 'pure release' library headers.
+#undef DIRECT_FORCE_DEBUG
+#endif
+#endif
+
+#endif
diff --git a/Source/DirectFB/lib/direct/clock.c b/Source/DirectFB/lib/direct/clock.c
new file mode 100755
index 0000000..e77bfe2
--- /dev/null
+++ b/Source/DirectFB/lib/direct/clock.c
@@ -0,0 +1,135 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/util.h>
+
+#ifdef CLOCK_MONOTONIC
+#include <sys/syscall.h>
+#endif
+#include <sys/time.h>
+#include <time.h>
+
+D_DEBUG_DOMAIN( Direct_Clock, "Direct/Clock", "Time measurement etc." );
+
+static struct timeval start_time = { 0, 0 };
+
+/* libc has incredibly messy way of doing this,
+ * typically requiring -lrt. We just skip all this mess */
+struct timeval*
+direct_monotonic_gettimeofday( struct timeval *tv )
+{
+ struct timespec ts;
+
+#ifdef CLOCK_MONOTONIC
+ /* No locking or atomic ops for no_monotonic here */
+ static int no_monotonic = 0;
+
+ if (!no_monotonic)
+ if(syscall( __NR_clock_gettime, CLOCK_MONOTONIC, &ts ))
+ no_monotonic = 1;
+
+ if (no_monotonic)
+ if(syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts))
+#endif
+ {
+ gettimeofday( tv, NULL );
+ return tv;
+ }
+
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+
+ return tv;
+}
+
+long long
+direct_clock_get_micros( void )
+{
+ struct timeval tv;
+ long long ret;
+
+ if (start_time.tv_sec == 0) {
+ direct_monotonic_gettimeofday( &start_time );
+ return 0;
+ }
+
+ direct_monotonic_gettimeofday( &tv );
+
+ ret = (long long)(tv.tv_sec - start_time.tv_sec) * 1000000LL +
+ (long long)(tv.tv_usec - start_time.tv_usec);
+ if (ret < 0) {
+ D_DEBUG_AT( Direct_Clock, "Clock skew detected (%lld in the past)!\n", -ret );
+ start_time = tv;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+long long
+direct_clock_get_millis( void )
+{
+ return direct_clock_get_micros() / 1000LL;
+}
+
+void
+direct_clock_set_start( const struct timeval *start )
+{
+ long long diff;
+
+ D_ASSERT( start != NULL );
+
+ diff = (long long)(start->tv_sec - start_time.tv_sec) * 1000LL +
+ (long long)(start->tv_usec - start_time.tv_usec) / 1000LL;
+
+ D_DEBUG_AT( Direct_Clock, "Adjusting start time "
+ "(%lld.%lld seconds diff)\n", diff / 1000LL, ABS(diff) % 1000LL );
+
+ start_time = *start;
+}
+
+long long
+direct_clock_get_abs_micros( void )
+{
+ struct timeval tv;
+
+ direct_monotonic_gettimeofday( &tv );
+
+ return (long long)(tv.tv_sec) * 1000000LL + (long long)(tv.tv_usec);
+}
+
+long long
+direct_clock_get_abs_millis( void )
+{
+ return direct_clock_get_abs_micros() / 1000LL;
+}
+
diff --git a/Source/DirectFB/lib/direct/clock.h b/Source/DirectFB/lib/direct/clock.h
new file mode 100755
index 0000000..dca6ea9
--- /dev/null
+++ b/Source/DirectFB/lib/direct/clock.h
@@ -0,0 +1,45 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__CLOCK_H__
+#define __DIRECT__CLOCK_H__
+
+#include <sys/time.h>
+
+struct timeval* direct_monotonic_gettimeofday( struct timeval *tv );
+
+long long direct_clock_get_micros( void );
+long long direct_clock_get_millis( void );
+
+void direct_clock_set_start( const struct timeval *start );
+
+long long direct_clock_get_abs_micros( void );
+long long direct_clock_get_abs_millis( void );
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/conf.c b/Source/DirectFB/lib/direct/conf.c
new file mode 100755
index 0000000..8be92af
--- /dev/null
+++ b/Source/DirectFB/lib/direct/conf.c
@@ -0,0 +1,348 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <direct/conf.h>
+#include <direct/mem.h>
+#include <direct/util.h>
+
+
+static DirectConfig config = {
+ .debug = false,
+ .trace = true,
+ .sighandler = true,
+
+ .fatal = DCFL_ASSERT,
+ .fatal_break = true,
+ .thread_block_signals = true,
+ .thread_priority_scale = 100,
+};
+
+DirectConfig *direct_config = &config;
+const char *direct_config_usage =
+ "libdirect options:\n"
+ " memcpy=<method> Skip memcpy() probing (help = show list)\n"
+ " [no-]quiet Disable text output except debug messages or direct logs\n"
+ " [no-]quiet=<type> Only quiet certain types (cumulative with 'quiet')\n"
+ " [ info | warning | error | once | unimplemented ]\n"
+ " [no-]debug Enable debug output\n"
+ " [no-]debugmem Enable memory allocation tracking\n"
+ " [no-]trace Enable stack trace support\n"
+ " log-file=<name> Write all messages to a file\n"
+ " log-udp=<host>:<port> Send all messages via UDP to host:port\n"
+ " fatal-level=<level> Abort on NONE, ASSERT (default) or ASSUME (incl. assert)\n"
+ " [no-]fatal-break Abort on BREAK (default)\n"
+ " dont-catch=<num>[[,<num>]...] Don't catch these signals\n"
+ " [no-]sighandler Enable signal handler\n"
+ " [no-]thread-block-signals Block all signals in new threads?\n"
+ " disable-module=<module_name> suppress loading this module\n"
+ " module-dir=<directory> Override default module search directory (default = $libdir/directfb-x.y-z)\n"
+ " thread-priority-scale=<100th> Apply scaling factor on thread type based priorities\n"
+ "\n";
+
+/**********************************************************************************************************************/
+
+DirectResult
+direct_config_set( const char *name, const char *value )
+{
+ if (strcmp (name, "disable-module" ) == 0) {
+ if (value) {
+ int n = 0;
+
+ while (direct_config->disable_module &&
+ direct_config->disable_module[n])
+ n++;
+
+ direct_config->disable_module = D_REALLOC( direct_config->disable_module,
+ sizeof(char*) * (n + 2) );
+
+ direct_config->disable_module[n] = D_STRDUP( value );
+ direct_config->disable_module[n+1] = NULL;
+ }
+ else {
+ D_ERROR("Direct/Config '%s': No module name specified!\n", name);
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "module-dir" ) == 0) {
+ if (value) {
+ if (direct_config->module_dir)
+ D_FREE( direct_config->module_dir );
+ direct_config->module_dir = D_STRDUP( value );
+ }
+ else {
+ D_ERROR("Direct/Config 'module-dir': No directory name specified!\n");
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "memcpy" ) == 0) {
+ if (value) {
+ if (direct_config->memcpy)
+ D_FREE( direct_config->memcpy );
+ direct_config->memcpy = D_STRDUP( value );
+ }
+ else {
+ D_ERROR("Direct/Config '%s': No method specified!\n", name);
+ return DR_INVARG;
+ }
+ }
+ else
+ if (strcmp (name, "quiet" ) == 0 || strcmp (name, "no-quiet" ) == 0) {
+ /* Enable/disable all at once by default. */
+ DirectMessageType type = DMT_ALL;
+
+ /* Find out the specific message type being configured. */
+ if (value) {
+ if (!strcmp( value, "info" )) type = DMT_INFO; else
+ if (!strcmp( value, "warning" )) type = DMT_WARNING; else
+ if (!strcmp( value, "error" )) type = DMT_ERROR; else
+ if (!strcmp( value, "once" )) type = DMT_ONCE; else
+ if (!strcmp( value, "unimplemented" )) type = DMT_UNIMPLEMENTED;
+ else {
+ D_ERROR( "DirectFB/Config '%s': Unknown message type '%s'!\n", name, value );
+ return DR_INVARG;
+ }
+ }
+
+ /* Set/clear the corresponding flag in the configuration. */
+ if (name[0] == 'q')
+ direct_config->quiet |= type;
+ else
+ direct_config->quiet &= ~type;
+ }
+ else
+ if (strcmp (name, "no-quiet" ) == 0) {
+ direct_config->quiet = false;
+ }
+ else
+ if (strcmp (name, "debug" ) == 0) {
+ if (value)
+ direct_debug_config_domain( value, true );
+ else
+ direct_config->debug = true;
+ }
+ else
+ if (strcmp (name, "no-debug" ) == 0) {
+ if (value)
+ direct_debug_config_domain( value, false );
+ else
+ direct_config->debug = false;
+ }
+ else
+ if (strcmp (name, "debugmem" ) == 0) {
+ direct_config->debugmem = true;
+ }
+ else
+ if (strcmp (name, "no-debugmem" ) == 0) {
+ direct_config->debugmem = false;
+ }
+ else
+ if (strcmp (name, "trace" ) == 0) {
+ direct_config->trace = true;
+ }
+ else
+ if (strcmp (name, "no-trace" ) == 0) {
+ direct_config->trace = false;
+ }
+ else
+ if (strcmp (name, "log-file" ) == 0 || strcmp (name, "log-udp" ) == 0) {
+ if (value) {
+ DirectResult ret;
+ DirectLog *log;
+
+ ret = direct_log_create( strcmp(name,"log-udp") ? DLT_FILE : DLT_UDP, value, &log );
+ if (ret)
+ return ret;
+
+ if (direct_config->log)
+ direct_log_destroy( direct_config->log );
+
+ direct_config->log = log;
+
+ direct_log_set_default( log );
+ }
+ else {
+ if (strcmp(name,"log-udp"))
+ D_ERROR("Direct/Config '%s': No file name specified!\n", name);
+ else
+ D_ERROR("Direct/Config '%s': No host and port specified!\n", name);
+ return DR_INVARG;
+ }
+ }
+ else
+ if (strcmp (name, "fatal-level" ) == 0) {
+ if (strcasecmp (value, "none" ) == 0) {
+ direct_config->fatal = DCFL_NONE;
+ }
+ else
+ if (strcasecmp (value, "assert" ) == 0) {
+ direct_config->fatal = DCFL_ASSERT;
+ }
+ else
+ if (strcasecmp (value, "assume" ) == 0) {
+ direct_config->fatal = DCFL_ASSUME;
+ }
+ else {
+ D_ERROR("Direct/Config '%s': Unknown level specified (use 'none', 'assert', 'assume')!\n", name);
+ return DR_INVARG;
+ }
+ }
+ else
+ if (strcmp (name, "fatal-break" ) == 0) {
+ direct_config->fatal_break = true;
+ }
+ else
+ if (strcmp (name, "no-fatal-break" ) == 0) {
+ direct_config->fatal_break = false;
+ }
+ else
+ if (strcmp (name, "sighandler" ) == 0) {
+ direct_config->sighandler = true;
+ }
+ else
+ if (strcmp (name, "no-sighandler" ) == 0) {
+ direct_config->sighandler = false;
+ }
+ else
+ if (strcmp (name, "dont-catch" ) == 0) {
+ if (value) {
+ char *signals = D_STRDUP( value );
+ char *p = NULL, *r, *s = signals;
+
+ while ((r = strtok_r( s, ",", &p ))) {
+ char *error;
+ unsigned long signum;
+
+ direct_trim( &r );
+
+ signum = strtoul( r, &error, 10 );
+
+ if (*error) {
+ D_ERROR( "Direct/Config '%s': Error in number at '%s'!\n", name, error );
+ D_FREE( signals );
+ return DR_INVARG;
+ }
+
+ sigaddset( &direct_config->dont_catch, signum );
+
+ s = NULL;
+ }
+
+ D_FREE( signals );
+ }
+ else {
+ D_ERROR("Direct/Config '%s': No signals specified!\n", name);
+ return DR_INVARG;
+ }
+ }
+ else
+ if (strcmp (name, "thread_block_signals") == 0) {
+ direct_config->thread_block_signals = true;
+ }
+ else
+ if (strcmp (name, "no-thread_block_signals") == 0) {
+ direct_config->thread_block_signals = false;
+ } else
+ if (strcmp (name, "thread-priority-scale" ) == 0) {
+ if (value) {
+ int scale;
+
+ if (sscanf( value, "%d", &scale ) < 1) {
+ D_ERROR("Direct/Config '%s': Could not parse value!\n", name);
+ return DR_INVARG;
+ }
+
+ direct_config->thread_priority_scale = scale;
+ }
+ else {
+ D_ERROR("Direct/Config '%s': No value specified!\n", name);
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "thread-priority" ) == 0) { /* Must be moved to lib/direct/conf.c in trunk! */
+ if (value) {
+ int priority;
+
+ if (sscanf( value, "%d", &priority ) < 1) {
+ D_ERROR("Direct/Config '%s': Could not parse value!\n", name);
+ return DR_INVARG;
+ }
+
+ direct_config->thread_priority = priority;
+ }
+ else {
+ D_ERROR("Direct/Config '%s': No value specified!\n", name);
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "thread-scheduler" ) == 0) { /* Must be moved to lib/direct/conf.c in trunk! */
+ if (value) {
+ if (strcmp( value, "other" ) == 0) {
+ direct_config->thread_scheduler = DCTS_OTHER;
+ } else
+ if (strcmp( value, "fifo" ) == 0) {
+ direct_config->thread_scheduler = DCTS_FIFO;
+ } else
+ if (strcmp( value, "rr" ) == 0) {
+ direct_config->thread_scheduler = DCTS_RR;
+ } else {
+ D_ERROR( "Direct/Config '%s': Unknown scheduler '%s'!\n", name, value );
+ return DR_INVARG;
+ }
+ }
+ else {
+ D_ERROR( "Direct/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "thread-stacksize" ) == 0) { /* Must be moved to lib/direct/conf.c in trunk! */
+ if (value) {
+ int size;
+
+ if (sscanf( value, "%d", &size ) < 1) {
+ D_ERROR( "Direct/Config '%s': Could not parse value!\n", name );
+ return DR_INVARG;
+ }
+
+ direct_config->thread_stack_size = size;
+ }
+ else {
+ D_ERROR( "Direct/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ }
+ else
+ return DR_UNSUPPORTED;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/direct/conf.h b/Source/DirectFB/lib/direct/conf.h
new file mode 100755
index 0000000..ef1230e
--- /dev/null
+++ b/Source/DirectFB/lib/direct/conf.h
@@ -0,0 +1,92 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__CONF_H__
+#define __DIRECT__CONF_H__
+
+
+#include <direct/messages.h>
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#else
+#include <sys/signal.h>
+#endif
+
+typedef enum {
+ DCFL_NONE, /* None is fatal. */
+ DCFL_ASSERT, /* ASSERT is fatal. */
+ DCFL_ASSUME /* ASSERT and ASSUME are fatal. */
+} DirectConfigFatalLevel;
+
+typedef enum {
+ DCTS_OTHER,
+ DCTS_FIFO,
+ DCTS_RR
+} DirectConfigThreadScheduler;
+
+struct __D_DirectConfig {
+ DirectMessageType quiet;
+ bool debug;
+ bool trace;
+
+ char *memcpy; /* Don't probe for memcpy routines to save a lot of
+ startup time. Use this one instead if it's set. */
+
+ char **disable_module; /* Never load these modules. */
+ char *module_dir; /* module dir override */
+
+ bool sighandler;
+ sigset_t dont_catch; /* don't catch these signals */
+
+ DirectLog *log;
+
+ DirectConfigFatalLevel fatal;
+
+ bool debugmem;
+
+ bool thread_block_signals;
+
+ bool fatal_break; /* Should D_BREAK() cause a trap? */
+
+ int thread_priority;
+ DirectConfigThreadScheduler thread_scheduler;
+ int thread_stack_size;
+ int thread_priority_scale;
+};
+
+extern DirectConfig *direct_config;
+
+extern const char *direct_config_usage;
+
+
+DirectResult direct_config_set( const char *name, const char *value );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/debug.c b/Source/DirectFB/lib/direct/debug.c
new file mode 100755
index 0000000..6aad0a1
--- /dev/null
+++ b/Source/DirectFB/lib/direct/debug.c
@@ -0,0 +1,430 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/build.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/log.h>
+#include <direct/thread.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+
+#if DIRECT_BUILD_TEXT
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+typedef struct {
+ DirectLink link;
+ char *name;
+ bool enabled;
+} DebugDomainEntry;
+
+/**************************************************************************************************/
+
+static pthread_mutex_t domains_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int domains_age = 1;
+static DirectLink *domains = NULL;
+
+/**************************************************************************************************/
+
+__attribute__((no_instrument_function))
+static inline DebugDomainEntry *
+lookup_domain( const char *name, bool sub )
+{
+ DebugDomainEntry *entry;
+
+ direct_list_foreach (entry, domains) {
+ if (! strcasecmp( entry->name, name ))
+ return entry;
+ }
+
+ /*
+ * If the domain being registered contains a slash, but didn't exactly match an entry
+ * in directfbrc, check to see if the domain is descended from an entry in directfbrc
+ * (e.g. 'ui/field/messages' matches 'ui' or 'ui/field')
+ */
+ if (sub && strchr(name, '/')) {
+ int passed_name_len = strlen( name );
+
+ direct_list_foreach (entry, domains) {
+ int entry_len = strlen( entry->name );
+ if ((passed_name_len > entry_len) &&
+ (name[entry_len] == '/') &&
+ (! strncasecmp( entry->name, name, entry_len))) {
+ return entry;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+__attribute__((no_instrument_function))
+static inline bool
+check_domain( DirectDebugDomain *domain )
+{
+ if (domain->age != domains_age) {
+ DebugDomainEntry *entry = lookup_domain( domain->name, true );
+
+ domain->age = domains_age;
+
+ if (entry) {
+ domain->registered = true;
+ domain->enabled = entry->enabled;
+ }
+ }
+
+ return domain->registered ? domain->enabled : direct_config->debug;
+}
+
+#endif /* DIRECT_BUILD_DEBUGS */
+
+/**************************************************************************************************/
+
+void
+direct_debug_config_domain( const char *name, bool enable )
+{
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+ DebugDomainEntry *entry;
+
+ pthread_mutex_lock( &domains_lock );
+
+ entry = lookup_domain( name, false );
+ if (!entry) {
+ entry = calloc( 1, sizeof(DebugDomainEntry) );
+ if (!entry) {
+ D_WARN( "out of memory" );
+ pthread_mutex_unlock( &domains_lock );
+ return;
+ }
+
+ entry->name = strdup( name );
+
+ direct_list_prepend( &domains, &entry->link );
+ }
+
+ entry->enabled = enable;
+
+ if (! ++domains_age)
+ domains_age++;
+
+ pthread_mutex_unlock( &domains_lock );
+#endif /* DIRECT_BUILD_DEBUGS */
+}
+
+/**************************************************************************************************/
+
+__attribute__((no_instrument_function))
+static inline void
+debug_domain_vprintf( const char *name,
+ int name_len,
+ const char *format,
+ va_list ap )
+{
+ char buf[512];
+ long long millis = direct_clock_get_millis();
+ const char *thread = direct_thread_self_name();
+ int indent = direct_trace_debug_indent() * 4;
+
+ /* Prepare user message. */
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ /* Fill up domain name column after the colon, prepending remaining space (excl. ': ') to indent. */
+ indent += (name_len < 20 ? 20 : 36) - name_len - 2;
+
+ /* Print full message. */
+ direct_log_printf( NULL, "(-) [%-15s %3lld.%03lld] (%5d) %s: %*s%s", thread ? thread : " NO NAME",
+ millis / 1000LL, millis % 1000LL, direct_gettid(), name, indent, "", buf );
+}
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+__attribute__((no_instrument_function))
+void
+direct_debug( const char *format, ... )
+{
+ va_list ap;
+
+ va_start( ap, format );
+
+ debug_domain_vprintf( "- - ", 4, format, ap );
+
+ va_end( ap );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_debug_at( DirectDebugDomain *domain,
+ const char *format, ... )
+{
+ bool enabled;
+
+ pthread_mutex_lock( &domains_lock );
+
+ enabled = check_domain( domain );
+
+ pthread_mutex_unlock( &domains_lock );
+
+ if (enabled) {
+ va_list ap;
+
+ va_start( ap, format );
+
+ debug_domain_vprintf( domain->name, domain->name_len, format, ap );
+
+ va_end( ap );
+ }
+}
+
+#endif /* DIRECT_BUILD_DEBUGS */
+
+__attribute__((no_instrument_function))
+void
+direct_debug_at_always( DirectDebugDomain *domain,
+ const char *format, ... )
+{
+ va_list ap;
+
+ va_start( ap, format );
+
+ debug_domain_vprintf( domain->name, domain->name_len, format, ap );
+
+ va_end( ap );
+}
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+__attribute__((no_instrument_function))
+void
+direct_debug_enter( DirectDebugDomain *domain,
+ const char *func,
+ const char *file,
+ int line,
+ const char *format, ... )
+{
+ bool enabled;
+
+ pthread_mutex_lock( &domains_lock );
+
+ enabled = check_domain( domain );
+
+ pthread_mutex_unlock( &domains_lock );
+
+ if (enabled) {
+ int len;
+ char dom[48];
+ char fmt[128];
+ char buf[512];
+ long long millis = direct_clock_get_millis();
+ const char *name = direct_thread_self_name();
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+
+ len = snprintf( dom, sizeof(dom), "%s:", domain->name );
+
+ if (len < 18)
+ len = 18;
+ else
+ len = 28;
+
+ len += direct_trace_debug_indent() * 4;
+
+ snprintf( fmt, sizeof(fmt), "(>) [%%-15s %%3lld.%%03lld] (%%5d) %%-%ds Entering %%s%%s [%%s:%%d]\n", len );
+
+ direct_log_printf( NULL, fmt, name ? name : " NO NAME ",
+ millis / 1000LL, millis % 1000LL, direct_gettid(), dom,
+ func, buf, file, line );
+ }
+}
+
+__attribute__((no_instrument_function))
+void
+direct_debug_exit( DirectDebugDomain *domain,
+ const char *func,
+ const char *file,
+ int line,
+ const char *format, ... )
+{
+ bool enabled;
+
+ pthread_mutex_lock( &domains_lock );
+
+ enabled = check_domain( domain );
+
+ pthread_mutex_unlock( &domains_lock );
+
+ if (enabled) {
+ int len;
+ char dom[48];
+ char fmt[128];
+ char buf[512];
+ long long millis = direct_clock_get_millis();
+ const char *name = direct_thread_self_name();
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+
+ len = snprintf( dom, sizeof(dom), "%s:", domain->name );
+
+ if (len < 18)
+ len = 18;
+ else
+ len = 28;
+
+ len += direct_trace_debug_indent() * 4;
+
+ snprintf( fmt, sizeof(fmt), "(<) [%%-15s %%3lld.%%03lld] (%%5d) %%-%ds Returning from %%s%%s [%%s:%%d]\n", len );
+
+ direct_log_printf( NULL, fmt, name ? name : " NO NAME ",
+ millis / 1000LL, millis % 1000LL, direct_gettid(), dom,
+ func, buf, file, line );
+ }
+}
+
+__attribute__((no_instrument_function))
+static void
+trap( const char *domain )
+{
+ D_DEBUG( "Direct/%s: Raising SIGTRAP...\n", domain );
+
+ raise( SIGTRAP );
+
+ D_DEBUG( "Direct/%s: ...didn't catch signal on my own, calling killpg().\n", domain );
+
+ kill( direct_gettid(), SIGTRAP );
+
+ D_DEBUG( "Direct/%s: ...still running, calling pthread_exit().\n", domain );
+
+ pthread_exit( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_break( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... )
+{
+ char buf[512];
+ long long millis = direct_clock_get_millis();
+ const char *name = direct_thread_self_name();
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL,
+ "(!) [%-15s %3lld.%03lld] (%5d) *** Break [%s] *** [%s:%d in %s()]\n",
+ name ? name : " NO NAME ", millis / 1000LL, millis % 1000LL,
+ direct_gettid(), buf, file, line, func );
+
+ direct_trace_print_stack( NULL );
+
+ if (direct_config->fatal_break)
+ trap( "Break" );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_assertion( const char *exp,
+ const char *func,
+ const char *file,
+ int line )
+{
+ long long millis = direct_clock_get_millis();
+ const char *name = direct_thread_self_name();
+
+ direct_log_printf( NULL,
+ "(!) [%-15s %3lld.%03lld] (%5d) *** Assertion [%s] failed *** [%s:%d in %s()]\n",
+ name ? name : " NO NAME ", millis / 1000LL, millis % 1000LL,
+ direct_gettid(), exp, file, line, func );
+
+ direct_trace_print_stack( NULL );
+
+ if (direct_config->fatal >= DCFL_ASSERT)
+ trap( "Assertion" );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_assumption( const char *exp,
+ const char *func,
+ const char *file,
+ int line )
+{
+ long long millis = direct_clock_get_millis();
+ const char *name = direct_thread_self_name();
+
+ direct_log_printf( NULL,
+ "(!) [%-15s %3lld.%03lld] (%5d) *** Assumption [%s] failed *** [%s:%d in %s()]\n",
+ name ? name : " NO NAME ", millis / 1000LL, millis % 1000LL,
+ direct_gettid(), exp, file, line, func );
+
+ direct_trace_print_stack( NULL );
+
+ if (direct_config->fatal >= DCFL_ASSUME)
+ trap( "Assumption" );
+}
+
+#endif /* DIRECT_BUILD_DEBUGS */
+
+#else
+
+void
+direct_debug_config_domain( const char *name, bool enable )
+{
+}
+
+#endif /* DIRECT_BUILD_TEXT */
+
diff --git a/Source/DirectFB/lib/direct/debug.h b/Source/DirectFB/lib/direct/debug.h
new file mode 100755
index 0000000..1232716
--- /dev/null
+++ b/Source/DirectFB/lib/direct/debug.h
@@ -0,0 +1,287 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__DEBUG_H__
+#define __DIRECT__DEBUG_H__
+
+#include <direct/build.h>
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <direct/clock.h>
+#include <direct/conf.h>
+#include <direct/log.h>
+#include <direct/messages.h>
+#include <direct/system.h>
+#include <direct/thread.h>
+#include <direct/trace.h>
+#include <direct/types.h>
+
+
+typedef struct {
+ unsigned int age;
+ bool enabled;
+ bool registered;
+
+ const char *name;
+ const char *description;
+
+ int name_len;
+} DirectDebugDomain;
+
+void direct_debug_config_domain( const char *name, bool enable );
+
+
+#if DIRECT_BUILD_TEXT
+
+#define D_DEBUG_DOMAIN(identifier,name,description) \
+ static DirectDebugDomain identifier __attribute__((unused)) \
+ = { 0, false, false, name, description, sizeof(name) - 1 }
+
+void direct_debug_at_always( DirectDebugDomain *domain,
+ const char *format, ... ) D_FORMAT_PRINTF(2);
+
+#define d_debug_at( domain, x... ) direct_debug_at_always( &domain, x )
+
+
+#if DIRECT_BUILD_DEBUGS
+
+void direct_debug( const char *format, ... ) D_FORMAT_PRINTF(1);
+
+void direct_debug_at( DirectDebugDomain *domain,
+ const char *format, ... ) D_FORMAT_PRINTF(2);
+
+void direct_debug_enter( DirectDebugDomain *domain,
+ const char *func,
+ const char *file,
+ int line,
+ const char *format, ... ) D_FORMAT_PRINTF(5);
+
+void direct_debug_exit( DirectDebugDomain *domain,
+ const char *func,
+ const char *file,
+ int line,
+ const char *format, ... ) D_FORMAT_PRINTF(5);
+
+void direct_break( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... ) D_FORMAT_PRINTF(4);
+
+void direct_assertion( const char *exp,
+ const char *func,
+ const char *file,
+ int line );
+
+void direct_assumption( const char *exp,
+ const char *func,
+ const char *file,
+ int line );
+#endif
+
+#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) || defined(DIRECT_FORCE_DEBUG)
+
+#define D_DEBUG_ENABLED (1)
+
+#define D_DEBUG(x...) \
+ do { \
+ if (!direct_config || direct_config->debug) \
+ direct_debug( x ); \
+ } while (0)
+
+
+#define D_DEBUG_AT(d,x...) \
+ do { \
+ direct_debug_at( &d, x ); \
+ } while (0)
+
+#define D_DEBUG_ENTER(d,x...) \
+ do { \
+ direct_debug_enter( &d, __FUNCTION__, __FILE__, __LINE__, x ); \
+ } while (0)
+
+#define D_DEBUG_EXIT(d,x...) \
+ do { \
+ direct_debug_exit( &d, __FUNCTION__, __FILE__, __LINE__, x ); \
+ } while (0)
+
+#define D_ASSERT(exp) \
+ do { \
+ if (!(exp)) \
+ direct_assertion( #exp, __FUNCTION__, __FILE__, __LINE__ ); \
+ } while (0)
+
+
+#define D_ASSUME(exp) \
+ do { \
+ if (!(exp)) \
+ direct_assumption( #exp, __FUNCTION__, __FILE__, __LINE__ ); \
+ } while (0)
+
+
+#define D_BREAK(x...) \
+ do { \
+ direct_break( __FUNCTION__, __FILE__, __LINE__, x ); \
+ } while (0)
+
+#elif defined(DIRECT_MINI_DEBUG)
+
+/*
+ * Mini debug mode, only D_DEBUG_AT, no domain filters, simple assertion
+ */
+
+#define D_DEBUG_ENABLED (2)
+
+#define D_DEBUG_AT(d,x...) \
+ do { \
+ if (direct_config->debug) direct_debug_at_always( &d, x ); \
+ } while (0)
+
+#define D_CHECK(exp, aa) \
+ do { \
+ if (!(exp)) { \
+ long long millis = direct_clock_get_millis(); \
+ const char *name = direct_thread_self_name(); \
+ \
+ direct_log_printf( NULL, \
+ "(!) [%-15s %3lld.%03lld] (%5d) *** " #aa " [%s] failed *** [%s:%d in %s()]\n", \
+ name ? name : " NO NAME ", millis / 1000LL, millis % 1000LL, \
+ direct_gettid(), #exp, __FILE__, __LINE__, __FUNCTION__ ); \
+ \
+ direct_trace_print_stack( NULL ); \
+ } \
+ } while (0)
+
+#define D_ASSERT(exp) D_CHECK(exp, Assertion)
+#define D_ASSUME(exp) D_CHECK(exp, Assumption)
+
+#endif /* MINI_DEBUG / DIRECT_BUILD_DEBUG || DIRECT_ENABLE_DEBUG || DIRECT_FORCE_DEBUG */
+
+#endif /* DIRECT_BUILD_TEXT */
+
+
+/*
+ * Fallback definitions, e.g. without DIRECT_BUILD_TEXT or DIRECT_ENABLE_DEBUG
+ */
+
+#ifndef D_DEBUG_ENABLED
+#define D_DEBUG_ENABLED (0)
+#endif
+
+#ifndef D_DEBUG
+#define D_DEBUG(x...) do {} while (0)
+#endif
+
+#ifndef D_DEBUG_AT
+#define D_DEBUG_AT(d,x...) do {} while (0)
+#endif
+
+#ifndef D_DEBUG_ENTER
+#define D_DEBUG_ENTER(d,x...) do {} while (0)
+#endif
+
+#ifndef D_DEBUG_EXIT
+#define D_DEBUG_EXIT(d,x...) do {} while (0)
+#endif
+
+#ifndef D_ASSERT
+#define D_ASSERT(exp) do {} while (0)
+#endif
+
+#ifndef D_ASSUME
+#define D_ASSUME(exp) do {} while (0)
+#endif
+
+#ifndef D_BREAK
+#define D_BREAK(x...) do {} while (0)
+#endif
+
+#ifndef d_debug_at
+#define d_debug_at( domain, x... ) do {} while (0)
+#endif
+
+#ifndef D_DEBUG_DOMAIN
+#define D_DEBUG_DOMAIN(i,n,d)
+#endif
+
+
+
+/*
+ * Magic Assertions & Utilities
+ */
+
+#define D_MAGIC(spell) ( (((spell)[sizeof(spell)*8/9] << 24) | \
+ ((spell)[sizeof(spell)*7/9] << 16) | \
+ ((spell)[sizeof(spell)*6/9] << 8) | \
+ ((spell)[sizeof(spell)*5/9] )) ^ \
+ (((spell)[sizeof(spell)*4/9] << 24) | \
+ ((spell)[sizeof(spell)*3/9] << 16) | \
+ ((spell)[sizeof(spell)*2/9] << 8) | \
+ ((spell)[sizeof(spell)*1/9] )) )
+
+
+#define D_MAGIC_SET(o,m) do { \
+ D_ASSERT( (o) != NULL ); \
+ D_ASSUME( (o)->magic != D_MAGIC(#m) ); \
+ \
+ (o)->magic = D_MAGIC(#m); \
+ } while (0)
+
+#define D_MAGIC_SET_ONLY(o,m) do { \
+ D_ASSERT( (o) != NULL ); \
+ \
+ (o)->magic = D_MAGIC(#m); \
+ } while (0)
+
+#define D_MAGIC_ASSERT(o,m) do { \
+ D_ASSERT( (o) != NULL ); \
+ D_ASSERT( (o)->magic == D_MAGIC(#m) ); \
+ } while (0)
+
+#define D_MAGIC_ASSUME(o,m) do { \
+ D_ASSUME( (o) != NULL ); \
+ if (o) \
+ D_ASSUME( (o)->magic == D_MAGIC(#m) ); \
+ } while (0)
+
+#define D_MAGIC_ASSERT_IF(o,m) do { \
+ if (o) \
+ D_ASSERT( (o)->magic == D_MAGIC(#m) ); \
+ } while (0)
+
+#define D_MAGIC_CLEAR(o) do { \
+ D_ASSERT( (o) != NULL ); \
+ D_ASSUME( (o)->magic != 0 ); \
+ \
+ (o)->magic = 0; \
+ } while (0)
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/direct.c b/Source/DirectFB/lib/direct/direct.c
new file mode 100755
index 0000000..38b930f
--- /dev/null
+++ b/Source/DirectFB/lib/direct/direct.c
@@ -0,0 +1,197 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#include <direct/debug.h>
+#include <direct/direct.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/log.h>
+#include <direct/mem.h>
+#include <direct/signals.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+D_DEBUG_DOMAIN( Direct_Main, "Direct/Main", "Initialization and shutdown of libdirect" );
+
+/**************************************************************************************************/
+
+struct __D_DirectCleanupHandler {
+ DirectLink link;
+
+ int magic;
+
+ DirectCleanupHandlerFunc func;
+ void *ctx;
+};
+
+/**************************************************************************************************/
+
+static int refs = 0;
+static DirectLink *handlers = NULL;
+static pthread_mutex_t main_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/**************************************************************************************************/
+
+static void
+direct_cleanup( void )
+{
+ DirectCleanupHandler *handler, *temp;
+
+ if (!refs)
+ return;
+
+ direct_list_foreach_safe (handler, temp, handlers) {
+ D_DEBUG_AT( Direct_Main, "Calling cleanup func %p...\n", handler->func );
+
+ handler->func( handler->ctx );
+
+ /*direct_list_remove( &handlers, &handler->link );
+
+ D_MAGIC_CLEAR( handler );
+
+ D_FREE( handler );*/
+ }
+
+ direct_print_memleaks();
+
+ direct_print_interface_leaks();
+}
+
+/**************************************************************************************************/
+
+DirectResult
+direct_cleanup_handler_add( DirectCleanupHandlerFunc func,
+ void *ctx,
+ DirectCleanupHandler **ret_handler )
+{
+ DirectCleanupHandler *handler;
+
+ D_ASSERT( func != NULL );
+ D_ASSERT( ret_handler != NULL );
+
+ D_DEBUG_AT( Direct_Main,
+ "Adding cleanup handler %p with context %p...\n", func, ctx );
+
+ handler = D_CALLOC( 1, sizeof(DirectCleanupHandler) );
+ if (!handler) {
+ D_WARN( "out of memory" );
+ return DR_NOLOCALMEMORY;
+ }
+
+ handler->func = func;
+ handler->ctx = ctx;
+
+ D_MAGIC_SET( handler, DirectCleanupHandler );
+
+ pthread_mutex_lock( &main_lock );
+
+ if (handlers == NULL)
+ atexit( direct_cleanup );
+
+ direct_list_append( &handlers, &handler->link );
+
+ pthread_mutex_unlock( &main_lock );
+
+ *ret_handler = handler;
+
+ return DR_OK;
+}
+
+DirectResult
+direct_cleanup_handler_remove( DirectCleanupHandler *handler )
+{
+ D_ASSERT( handler != NULL );
+
+ D_MAGIC_ASSERT( handler, DirectCleanupHandler );
+
+ D_DEBUG_AT( Direct_Main, "Removing cleanup handler %p with context %p...\n",
+ handler->func, handler->ctx );
+
+ pthread_mutex_lock( &main_lock );
+ direct_list_remove( &handlers, &handler->link );
+ pthread_mutex_unlock( &main_lock );
+
+ D_MAGIC_CLEAR( handler );
+
+ D_FREE( handler );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_initialize( void )
+{
+ pthread_mutex_lock( &main_lock );
+
+ D_DEBUG_AT( Direct_Main, "direct_initialize() called...\n" );
+
+ if (refs++) {
+ D_DEBUG_AT( Direct_Main, "...%d references now.\n", refs );
+ pthread_mutex_unlock( &main_lock );
+ return DR_OK;
+ }
+ else if (!direct_thread_self_name())
+ direct_thread_set_name( "Main Thread" );
+
+ D_DEBUG_AT( Direct_Main, "...initializing now.\n" );
+
+ direct_signals_initialize();
+
+ pthread_mutex_unlock( &main_lock );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_shutdown( void )
+{
+ pthread_mutex_lock( &main_lock );
+
+ D_DEBUG_AT( Direct_Main, "direct_shutdown() called...\n" );
+
+ if (--refs) {
+ D_DEBUG_AT( Direct_Main, "...%d references left.\n", refs );
+ pthread_mutex_unlock( &main_lock );
+ return DR_OK;
+ }
+
+ D_DEBUG_AT( Direct_Main, "...shutting down now.\n" );
+
+ direct_signals_shutdown();
+
+ pthread_mutex_unlock( &main_lock );
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/direct/direct.h b/Source/DirectFB/lib/direct/direct.h
new file mode 100755
index 0000000..b94e999
--- /dev/null
+++ b/Source/DirectFB/lib/direct/direct.h
@@ -0,0 +1,49 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__DIRECT_H__
+#define __DIRECT__DIRECT_H__
+
+#include <direct/types.h>
+
+DirectResult direct_initialize( void );
+DirectResult direct_shutdown( void );
+
+
+typedef void (*DirectCleanupHandlerFunc)( void *ctx );
+
+
+DirectResult direct_cleanup_handler_add( DirectCleanupHandlerFunc func,
+ void *ctx,
+ DirectCleanupHandler **ret_handler );
+
+DirectResult direct_cleanup_handler_remove( DirectCleanupHandler *handler );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/direct.pc.in b/Source/DirectFB/lib/direct/direct.pc.in
new file mode 100755
index 0000000..fa6e663
--- /dev/null
+++ b/Source/DirectFB/lib/direct/direct.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+moduledir=@MODULEDIR@
+moduledirname=@MODULEDIRNAME@
+includedir=@includedir@
+
+Name: Direct
+Description: DirectFB base development library
+Version: @VERSION@
+Libs: -L${libdir} -ldirect @THREADLIB@
+Libs.private: -L${libdir} @DYNLIB@
+Cflags: @THREADFLAGS@ -I@INCLUDEDIR@
diff --git a/Source/DirectFB/lib/direct/fastlz.c b/Source/DirectFB/lib/direct/fastlz.c
new file mode 100755
index 0000000..60bf3ca
--- /dev/null
+++ b/Source/DirectFB/lib/direct/fastlz.c
@@ -0,0 +1,97 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <direct/fastlz.h>
+#include <direct/messages.h>
+
+#include "flz.h"
+
+
+int
+direct_fastlz_compress( const void *input,
+ int length,
+ void *output )
+{
+ return fastlz_compress_level( 2, input, length, output );
+}
+
+int
+direct_fastlz_decompress( const void *input,
+ int length,
+ void *output,
+ int maxout )
+{
+ return fastlz_decompress( input, length, output, maxout );
+}
+
+int
+direct_fastlz_compress_multi( const void **inputs,
+ int *lengths,
+ unsigned int num,
+ void *output )
+{
+ // FIXME: Optimize by modifying fastlz compressor to take an array of buffers directly
+
+ unsigned int i;
+ int total = 0;
+ int offset = 0;
+ void *buffer;
+ int result;
+
+ if (num == 0)
+ return 0;
+
+ if (num == 1)
+ return direct_fastlz_compress( inputs[0], lengths[0], output );
+
+ for (i=0; i<num; i++)
+ total += lengths[i];
+
+ buffer = malloc( total );
+ if (!buffer) {
+ D_OOM();
+ return 0;
+ }
+
+ for (i=0; i<num; i++) {
+ memcpy( (char*) buffer + offset, inputs[i], lengths[i] );
+
+ offset += lengths[i];
+ }
+
+ result = direct_fastlz_compress( buffer, total, output );
+
+ free( buffer );
+
+ return result;
+}
diff --git a/Source/DirectFB/lib/direct/fastlz.h b/Source/DirectFB/lib/direct/fastlz.h
new file mode 100755
index 0000000..3a8750d
--- /dev/null
+++ b/Source/DirectFB/lib/direct/fastlz.h
@@ -0,0 +1,52 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__FASTLZ_H__
+#define __DIRECT__FASTLZ_H__
+
+#include <direct/types.h>
+
+/**********************************************************************************************************************/
+
+int direct_fastlz_compress ( const void *input,
+ int length,
+ void *output );
+
+int direct_fastlz_decompress ( const void *input,
+ int length,
+ void *output,
+ int maxout );
+
+
+int direct_fastlz_compress_multi( const void **inputs,
+ int *lengths,
+ unsigned int num,
+ void *output );
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/flz.c b/Source/DirectFB/lib/direct/flz.c
new file mode 100755
index 0000000..070bbe2
--- /dev/null
+++ b/Source/DirectFB/lib/direct/flz.c
@@ -0,0 +1,555 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+
+/*
+ * Always check for bound when decompressing.
+ * Generally it is best to leave it defined.
+ */
+#define FASTLZ_SAFE
+
+/*
+ * Give hints to the compiler for branch prediction optimization.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#else
+#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#endif
+
+/*
+ * Use inlined functions for supported systems.
+ */
+#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
+#define FASTLZ_INLINE inline
+#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
+#define FASTLZ_INLINE __inline
+#else
+#define FASTLZ_INLINE
+#endif
+
+/*
+ * Prevent accessing more than 8-bit at once, except on x86 architectures.
+ */
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_STRICT_ALIGN
+
+#if 0
+#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_M_IX86) /* Intel, MSVC */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__386)
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_X86_) /* MinGW */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__I86__) /* Digital Mars */
+#undef FASTLZ_STRICT_ALIGN
+#endif
+#endif
+
+#endif
+
+/*
+ * FIXME: use preprocessor magic to set this on different platforms!
+ */
+typedef unsigned char flzuint8;
+typedef unsigned short flzuint16;
+typedef unsigned int flzuint32;
+
+/* prototypes */
+int fastlz_compress(const void* input, int length, void* output);
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_DISTANCE 8192
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_READU16(p) *((const flzuint16*)(p))
+#else
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
+#endif
+
+#define HASH_LOG 13
+#define HASH_SIZE (1<< HASH_LOG)
+#define HASH_MASK (HASH_SIZE-1)
+#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 1
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz1_compress
+#define FASTLZ_DECOMPRESSOR fastlz1_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
+#include "flz.c"
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 2
+
+#undef MAX_DISTANCE
+#define MAX_DISTANCE 8191
+#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz2_compress
+#define FASTLZ_DECOMPRESSOR fastlz2_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
+#include "flz.c"
+
+int fastlz_compress(const void* input, int length, void* output)
+{
+ /* for short block, choose fastlz1 */
+ if(length < 65536)
+ return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout)
+{
+ /* magic identifier for compression level */
+ int level = ((*(const flzuint8*)input) >> 5) + 1;
+
+ if(level == 1)
+ return fastlz1_decompress(input, length, output, maxout);
+ if(level == 2)
+ return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void* input, int length, void* output)
+{
+ if(level == 1)
+ return fastlz1_compress(input, length, output);
+ if(level == 2)
+ return fastlz2_compress(input, length, output);
+
+ return 0;
+}
+
+#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
+{
+ const flzuint8* ip = (const flzuint8*) input;
+ const flzuint8* ip_bound = ip + length - 2;
+ const flzuint8* ip_limit = ip + length - 12;
+ flzuint8* op = (flzuint8*) output;
+
+ const flzuint8* htab[HASH_SIZE];
+ const flzuint8** hslot;
+ flzuint32 hval;
+
+ flzuint32 copy;
+
+ /* sanity check */
+ if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
+ {
+ if(length)
+ {
+ /* create literal copy only */
+ *op++ = length-1;
+ ip_bound++;
+ while(ip <= ip_bound)
+ *op++ = *ip++;
+ return length+1;
+ }
+ else
+ return 0;
+ }
+
+ /* initializes hash table */
+ for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
+ *hslot = ip;
+
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY-1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ {
+ const flzuint8* ref;
+ flzuint32 distance;
+
+ /* minimum match length */
+ flzuint32 len = 3;
+
+ /* comparison starting-point */
+ const flzuint8* anchor = ip;
+
+ /* check for a run */
+#if FASTLZ_LEVEL==2
+ if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
+ {
+ distance = 1;
+ ip += 3;
+ ref = anchor - 1 + 3;
+ goto match;
+ }
+#endif
+
+ /* find potential match */
+ HASH_FUNCTION(hval,ip);
+ hslot = htab + hval;
+ ref = htab[hval];
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* update hash table */
+ *hslot = anchor;
+
+ /* is this a match? check the first 3 bytes */
+ if(distance==0 ||
+#if FASTLZ_LEVEL==1
+ (distance >= MAX_DISTANCE) ||
+#else
+ (distance >= MAX_FARDISTANCE) ||
+#endif
+ *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
+ goto literal;
+
+#if FASTLZ_LEVEL==2
+ /* far, needs at least 5-byte match */
+ if(distance >= MAX_DISTANCE)
+ {
+ if(*ip++ != *ref++ || *ip++!= *ref++)
+ goto literal;
+ len += 2;
+ }
+
+ match:
+#endif
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if(!distance)
+ {
+ /* zero distance means a run */
+ flzuint8 x = ip[-1];
+ while(ip < ip_bound)
+ if(*ref++ != x) break; else ip++;
+ }
+ else
+ for(;;)
+ {
+ /* safe because the outer check against ip limit */
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ while(ip < ip_bound)
+ if(*ref++ != *ip++) break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if(copy)
+ /* copy is biased, '0' means 1 byte copy */
+ *(op-copy-1) = copy-1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+#if FASTLZ_LEVEL==2
+ if(distance < MAX_DISTANCE)
+ {
+ if(len < 7)
+ {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ }
+ else
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ for(len-=7; len >= 255; len-= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = (distance & 255);
+ }
+ }
+ else
+ {
+ /* far away, but not yet in the another galaxy... */
+ if(len < 7)
+ {
+ distance -= MAX_DISTANCE;
+ *op++ = (len << 5) + 31;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ else
+ {
+ distance -= MAX_DISTANCE;
+ *op++ = (7 << 5) + 31;
+ for(len-=7; len >= 255; len-= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ }
+#else
+
+ if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
+ while(len > MAX_LEN-2)
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 -2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN-2;
+ }
+
+ if(len < 7)
+ {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ }
+ else
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+#endif
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval,ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval,ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY-1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
+ {
+ copy = 0;
+ *op++ = MAX_COPY-1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while(ip <= ip_bound)
+ {
+ *op++ = *ip++;
+ copy++;
+ if(copy == MAX_COPY)
+ {
+ copy = 0;
+ *op++ = MAX_COPY-1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if(copy)
+ *(op-copy-1) = copy-1;
+ else
+ op--;
+
+#if FASTLZ_LEVEL==2
+ /* marker for fastlz2 */
+ *(flzuint8*)output |= (1 << 5);
+#endif
+
+ return op - (flzuint8*)output;
+}
+
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
+{
+ const flzuint8* ip = (const flzuint8*) input;
+ const flzuint8* ip_limit = ip + length;
+ flzuint8* op = (flzuint8*) output;
+ flzuint8* op_limit = op + maxout;
+ flzuint32 ctrl = (*ip++) & 31;
+ int loop = 1;
+
+ do
+ {
+ const flzuint8* ref = op;
+ flzuint32 len = ctrl >> 5;
+ flzuint32 ofs = (ctrl & 31) << 8;
+
+ if(ctrl >= 32)
+ {
+#if FASTLZ_LEVEL==2
+ flzuint8 code;
+#endif
+ len--;
+ ref -= ofs;
+ if (len == 7-1)
+#if FASTLZ_LEVEL==1
+ len += *ip++;
+ ref -= *ip++;
+#else
+ do
+ {
+ code = *ip++;
+ len += code;
+ } while (code==255);
+ code = *ip++;
+ ref -= code;
+
+ /* match from 16-bit distance */
+ if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
+ if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
+ {
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_DISTANCE;
+ }
+#endif
+
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
+ return 0;
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
+ return 0;
+#endif
+
+ if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ ctrl = *ip++;
+ else
+ loop = 0;
+
+ if(ref == op)
+ {
+ /* optimize copy for a run */
+ flzuint8 b = ref[-1];
+ *op++ = b;
+ *op++ = b;
+ *op++ = b;
+ for(; len; --len)
+ *op++ = b;
+ }
+ else
+ {
+#if !defined(FASTLZ_STRICT_ALIGN)
+ const flzuint16* p;
+ flzuint16* q;
+#endif
+ /* copy from reference */
+ ref--;
+ *op++ = *ref++;
+ *op++ = *ref++;
+ *op++ = *ref++;
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+ /* copy a byte, so that now it's word aligned */
+ if(len & 1)
+ {
+ *op++ = *ref++;
+ len--;
+ }
+
+ /* copy 16-bit at once */
+ q = (flzuint16*) op;
+ op += len;
+ p = (const flzuint16*) ref;
+ for(len>>=1; len > 4; len-=4)
+ {
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ }
+ for(; len; --len)
+ *q++ = *p++;
+#else
+ for(; len; --len)
+ *op++ = *ref++;
+#endif
+ }
+ }
+ else
+ {
+ ctrl++;
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
+ return 0;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
+ return 0;
+#endif
+
+ *op++ = *ip++;
+ for(--ctrl; ctrl; ctrl--)
+ *op++ = *ip++;
+
+ loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
+ if(loop)
+ ctrl = *ip++;
+ }
+ }
+ while(FASTLZ_EXPECT_CONDITIONAL(loop));
+
+ return op - (flzuint8*)output;
+}
+
+#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
diff --git a/Source/DirectFB/lib/direct/flz.h b/Source/DirectFB/lib/direct/flz.h
new file mode 100755
index 0000000..f87bc7b
--- /dev/null
+++ b/Source/DirectFB/lib/direct/flz.h
@@ -0,0 +1,100 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef FASTLZ_H
+#define FASTLZ_H
+
+#define FASTLZ_VERSION 0x000100
+
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 0
+#define FASTLZ_VERSION_REVISION 0
+
+#define FASTLZ_VERSION_STRING "0.1.0"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+*/
+
+int fastlz_compress(const void* input, int length, void* output);
+
+/**
+ Decompress a block of compressed data and returns the size of the
+ decompressed block. If error occurs, e.g. the compressed data is
+ corrupted or the output buffer is not large enough, then 0 (zero)
+ will be returned instead.
+
+ The input buffer and the output buffer can not overlap.
+
+ Decompression is memory safe and guaranteed not to write the output buffer
+ more than what is specified in maxout.
+ */
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress above.
+*/
+
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* FASTLZ_H */
diff --git a/Source/DirectFB/lib/direct/hash.c b/Source/DirectFB/lib/direct/hash.c
new file mode 100755
index 0000000..729e866
--- /dev/null
+++ b/Source/DirectFB/lib/direct/hash.c
@@ -0,0 +1,268 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <direct/debug.h>
+#include <direct/hash.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+
+D_DEBUG_DOMAIN( Direct_Hash, "Direct/Hash", "Hash table implementation" );
+
+
+#define REMOVED ((void *) -1)
+
+typedef struct {
+ unsigned long key;
+ void *value;
+} Element;
+
+struct __D_DirectHash {
+ int magic;
+
+ int size;
+
+ int count;
+ int removed;
+
+ Element *elements;
+};
+
+/**************************************************************************************************/
+
+static inline int
+locate_key( const DirectHash *hash, unsigned long key )
+{
+ int pos;
+ const Element *element;
+
+ pos = key % hash->size;
+
+ element = &hash->elements[pos];
+
+ while (element->value) {
+ if (element->value != REMOVED && element->key == key)
+ return pos;
+
+ if (++pos == hash->size)
+ pos = 0;
+
+ element = &hash->elements[pos];
+ }
+
+ return -1;
+}
+
+/**************************************************************************************************/
+
+DirectResult
+direct_hash_create( int size,
+ DirectHash **ret_hash )
+{
+ DirectHash *hash;
+
+ if (size < 17)
+ size = 17;
+
+ D_DEBUG_AT( Direct_Hash, "Creating hash table with initial capacity of %d...\n", size );
+
+ hash = D_CALLOC( 1, sizeof (DirectHash) );
+ if (!hash) {
+ D_WARN( "out of memory" );
+ return DR_NOLOCALMEMORY;
+ }
+
+ hash->size = size;
+ hash->elements = D_CALLOC( size, sizeof(Element) );
+
+ if (!hash->elements) {
+ D_WARN( "out of memory" );
+ D_FREE( hash );
+ return DR_NOLOCALMEMORY;
+ }
+
+ D_MAGIC_SET( hash, DirectHash );
+
+ *ret_hash = hash;
+
+ return DR_OK;
+}
+
+void
+direct_hash_destroy( DirectHash *hash )
+{
+ D_MAGIC_ASSERT( hash, DirectHash );
+
+ D_MAGIC_CLEAR( hash );
+
+ D_FREE( hash->elements );
+ D_FREE( hash );
+}
+
+DirectResult
+direct_hash_insert( DirectHash *hash,
+ unsigned long key,
+ void *value )
+{
+ int pos;
+ Element *element;
+
+ D_MAGIC_ASSERT( hash, DirectHash );
+ D_ASSERT( value != NULL );
+
+ /* Need to resize the hash table? */
+ if ((hash->count + hash->removed) > hash->size / 4) {
+ int i, size = hash->size * 3;
+ Element *elements;
+
+ D_DEBUG_AT( Direct_Hash, "Resizing from %d to %d... (count %d, removed %d)\n",
+ hash->size, size, hash->count, hash->removed );
+
+ elements = D_CALLOC( size, sizeof(Element) );
+ if (!elements) {
+ D_WARN( "out of memory" );
+ return DR_NOLOCALMEMORY;
+ }
+
+ for (i=0; i<hash->size; i++) {
+ Element *element = &hash->elements[i];
+ Element *insertElement;
+
+ if (element->value && element->value != REMOVED) {
+ pos = element->key % size;
+
+ insertElement = &elements[pos];
+ while (insertElement->value && insertElement->value != REMOVED) {
+ if (++pos == size)
+ pos = 0;
+ insertElement = &elements[pos];
+ }
+
+ elements[pos] = *element;
+ }
+ }
+
+ D_FREE( hash->elements );
+
+ hash->size = size;
+ hash->elements = elements;
+ hash->removed = 0;
+ }
+
+ pos = key % hash->size;
+
+ D_DEBUG_AT( Direct_Hash, "Attempting to insert key 0x%08lx at position %d...\n", key, pos );
+
+ element = &hash->elements[pos];
+
+ while (element->value && element->value != REMOVED) {
+ if (element->key == key) {
+ D_BUG( "key already exists" );
+ return DR_BUG;
+ }
+
+ if (++pos == hash->size)
+ pos = 0;
+
+ element = &hash->elements[pos];
+ }
+
+ if (element->value == REMOVED)
+ hash->removed--;
+
+ element->key = key;
+ element->value = value;
+
+ hash->count++;
+
+ D_DEBUG_AT( Direct_Hash, "...inserted at %d, new count = %d, removed = %d, size = %d, key = 0x%08lx.\n",
+ pos, hash->count, hash->removed, hash->size, key );
+
+ return DR_OK;
+}
+
+void
+direct_hash_remove( DirectHash *hash,
+ unsigned long key )
+{
+ int pos;
+
+ D_MAGIC_ASSERT( hash, DirectHash );
+
+ pos = locate_key( hash, key );
+ if (pos == -1) {
+ D_WARN( "key not found" );
+ return;
+ }
+
+ hash->elements[pos].value = REMOVED;
+
+ hash->count--;
+ hash->removed++;
+
+ D_DEBUG_AT( Direct_Hash, "Removed key 0x%08lx at %d, new count = %d, removed = %d, size = %d.\n",
+ key, pos, hash->count, hash->removed, hash->size );
+}
+
+void *
+direct_hash_lookup( DirectHash *hash,
+ unsigned long key )
+{
+ int pos;
+
+ D_MAGIC_ASSERT( hash, DirectHash );
+
+ pos = locate_key( hash, key );
+
+ return (pos != -1) ? hash->elements[pos].value : NULL;
+}
+
+void
+direct_hash_iterate( DirectHash *hash,
+ DirectHashIteratorFunc func,
+ void *ctx )
+{
+ int i;
+
+ D_MAGIC_ASSERT( hash, DirectHash );
+
+ for (i=0; i<hash->size; i++) {
+ Element *element = &hash->elements[i];
+
+ if (!element->value || element->value == REMOVED)
+ continue;
+
+ if (!func( hash, element->key, element->value, ctx ) )
+ return;
+ }
+}
+
diff --git a/Source/DirectFB/lib/direct/hash.h b/Source/DirectFB/lib/direct/hash.h
new file mode 100755
index 0000000..6b487d9
--- /dev/null
+++ b/Source/DirectFB/lib/direct/hash.h
@@ -0,0 +1,61 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__HASH_H__
+#define __DIRECT__HASH_H__
+
+#include <direct/types.h>
+
+
+typedef bool (*DirectHashIteratorFunc)( DirectHash *hash,
+ unsigned long key,
+ void *value,
+ void *ctx );
+
+
+DirectResult direct_hash_create ( int size,
+ DirectHash **ret_hash );
+
+void direct_hash_destroy( DirectHash *hash );
+
+DirectResult direct_hash_insert ( DirectHash *hash,
+ unsigned long key,
+ void *value );
+
+void direct_hash_remove ( DirectHash *hash,
+ unsigned long key );
+
+void *direct_hash_lookup ( DirectHash *hash,
+ unsigned long key );
+
+void direct_hash_iterate( DirectHash *hash,
+ DirectHashIteratorFunc func,
+ void *ctx );
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/interface.c b/Source/DirectFB/lib/direct/interface.c
new file mode 100755
index 0000000..1247412
--- /dev/null
+++ b/Source/DirectFB/lib/direct/interface.c
@@ -0,0 +1,474 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <pthread.h>
+#include <dirent.h>
+#ifndef USE_KOS
+#include <dlfcn.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <alloca.h>
+
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/interface.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+#ifdef PIC
+#define DYNAMIC_LINKING
+#endif
+
+
+D_DEBUG_DOMAIN( Direct_Interface, "Direct/Interface", "Direct Interface" );
+
+
+typedef struct {
+ DirectLink link;
+
+ int magic;
+
+ char *filename;
+ void *module_handle;
+
+ DirectInterfaceFuncs *funcs;
+
+ const char *type;
+ const char *implementation;
+
+ int references;
+} DirectInterfaceImplementation;
+
+
+#ifdef PTHREADMINIT
+static pthread_mutex_t implementations_mutex = PTHREAD_MUTEX_INITIALIZER;
+#else
+static pthread_mutex_t implementations_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#endif
+static DirectLink *implementations = NULL;
+
+/**************************************************************************************************/
+
+void
+DirectRegisterInterface( DirectInterfaceFuncs *funcs )
+{
+ DirectInterfaceImplementation *impl;
+
+ D_DEBUG_AT( Direct_Interface, "%s( %p )\n", __FUNCTION__, funcs );
+
+ impl = D_CALLOC( 1, sizeof(DirectInterfaceImplementation) );
+
+ impl->funcs = funcs;
+ impl->type = funcs->GetType();
+ impl->implementation = funcs->GetImplementation();
+
+ D_MAGIC_SET( impl, DirectInterfaceImplementation );
+
+ D_DEBUG_AT( Direct_Interface, " -> %s | %s\n", impl->type, impl->implementation );
+
+ pthread_mutex_lock( &implementations_mutex );
+ direct_list_prepend( &implementations, &impl->link );
+ pthread_mutex_unlock( &implementations_mutex );
+}
+
+void
+DirectUnregisterInterface( DirectInterfaceFuncs *funcs )
+{
+ DirectInterfaceImplementation *impl;
+
+ pthread_mutex_lock( &implementations_mutex );
+
+ direct_list_foreach (impl, implementations) {
+ D_MAGIC_ASSERT( impl, DirectInterfaceImplementation );
+
+ if (impl->funcs == funcs) {
+ direct_list_remove( &implementations, &impl->link );
+
+ break;
+ }
+ }
+
+ pthread_mutex_unlock( &implementations_mutex );
+
+ if (!impl) {
+ D_BUG( "implementation not found" );
+ return;
+ }
+
+ D_MAGIC_CLEAR( impl );
+
+ D_FREE( impl );
+}
+
+DirectResult
+DirectProbeInterface( DirectInterfaceFuncs *funcs, void *ctx )
+{
+ return (funcs->Probe( ctx ) == DR_OK);
+}
+
+DirectResult
+DirectGetInterface( DirectInterfaceFuncs **funcs,
+ const char *type,
+ const char *implementation,
+ DirectInterfaceProbeFunc probe,
+ void *probe_ctx )
+{
+#ifdef DYNAMIC_LINKING
+ int len;
+ DIR *dir;
+ char *interface_dir;
+ struct dirent *entry = NULL;
+ struct dirent tmp;
+ const char *path;
+#endif
+
+ DirectLink *link;
+
+ D_DEBUG_AT( Direct_Interface, "%s( %p, '%s', '%s', %p, %p )\n", __FUNCTION__,
+ funcs, type, implementation, probe, probe_ctx );
+
+ pthread_mutex_lock( &implementations_mutex );
+
+ /*
+ * Check existing implementations first.
+ */
+ direct_list_foreach( link, implementations ) {
+ DirectInterfaceImplementation *impl = (DirectInterfaceImplementation*) link;
+
+ if (type && strcmp( type, impl->type ))
+ continue;
+
+ if (implementation && strcmp( implementation, impl->implementation ))
+ continue;
+
+ D_DEBUG_AT( Direct_Interface, " -> Probing '%s'...\n", impl->implementation );
+
+ if (probe && !probe( impl->funcs, probe_ctx ))
+ continue;
+ else {
+ if (!impl->references) {
+ D_INFO( "Direct/Interface: Using '%s' implementation of '%s'.\n",
+ impl->implementation, impl->type );
+ }
+
+ *funcs = impl->funcs;
+ impl->references++;
+
+ pthread_mutex_unlock( &implementations_mutex );
+
+ return DR_OK;
+ }
+ }
+
+#ifdef DYNAMIC_LINKING
+ /*
+ * Try to load it dynamically.
+ */
+
+ /* NULL type means we can't find plugin, so stop immediately */
+ if (type == NULL) {
+ pthread_mutex_unlock( &implementations_mutex );
+ return DR_NOIMPL;
+ }
+
+ path = direct_config->module_dir;
+ if(!path)
+ path = MODULEDIR;
+
+ len = strlen(path) + strlen("/interfaces/") + strlen(type) + 1;
+ interface_dir = alloca( len );
+ snprintf( interface_dir, len, "%s%sinterfaces/%s", path, (path[strlen(path)-1]=='/') ? "" : "/", type );
+
+ dir = opendir( interface_dir );
+ if (!dir) {
+ D_DEBUG( "Could not open interface directory `%s'!\n", interface_dir );
+ pthread_mutex_unlock( &implementations_mutex );
+ return errno2result( errno );
+ }
+
+ /*
+ * Iterate directory.
+ */
+ while (readdir_r( dir, &tmp, &entry ) == 0 && entry) {
+ void *handle = NULL;
+ char buf[4096];
+
+ DirectInterfaceImplementation *old_impl = (DirectInterfaceImplementation*) implementations;
+
+ if (strlen(entry->d_name) < 4 ||
+ entry->d_name[strlen(entry->d_name)-1] != 'o' ||
+ entry->d_name[strlen(entry->d_name)-2] != 's')
+ continue;
+
+ snprintf( buf, 4096, "%s/%s", interface_dir, entry->d_name );
+
+ /*
+ * Check if it got already loaded.
+ */
+ direct_list_foreach( link, implementations ) {
+ DirectInterfaceImplementation *impl = (DirectInterfaceImplementation*) link;
+
+ if (impl->filename && !strcmp( impl->filename, buf )) {
+ handle = impl->module_handle;
+ break;
+ }
+ }
+
+ /*
+ * If already loaded take the next one.
+ */
+ if (handle)
+ continue;
+
+ /*
+ * Open it and check.
+ */
+ handle = dlopen( buf, RTLD_NOW );
+ if (handle) {
+ DirectInterfaceImplementation *impl = (DirectInterfaceImplementation*) implementations;
+
+ /*
+ * Check if it registered itself.
+ */
+ if (impl == old_impl) {
+ dlclose( handle );
+ continue;
+ }
+
+ /*
+ * Keep filename and module handle.
+ */
+ impl->filename = D_STRDUP( buf );
+ impl->module_handle = handle;
+
+ /*
+ * Almost the same stuff like above, TODO: make function.
+ */
+ if (strcmp( type, impl->type ))
+ continue;
+
+ if (implementation && strcmp( implementation,
+ impl->implementation ))
+ continue;
+
+ if (probe && !probe( impl->funcs, probe_ctx )) {
+ continue;
+ }
+ else {
+ D_INFO( "Direct/Interface: Loaded '%s' implementation of '%s'.\n",
+ impl->implementation, impl->type );
+
+ *funcs = impl->funcs;
+ impl->references++;
+
+ closedir( dir );
+
+ pthread_mutex_unlock( &implementations_mutex );
+
+ return DR_OK;
+ }
+ }
+ else
+ D_DLERROR( "Direct/Interface: Unable to dlopen `%s'!\n", buf );
+ }
+
+ closedir( dir );
+
+ pthread_mutex_unlock( &implementations_mutex );
+#endif
+
+ return DR_NOIMPL;
+}
+
+/**************************************************************************************************/
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+typedef struct {
+ const void *interface;
+ char *name;
+ char *what;
+
+ const char *func;
+ const char *file;
+ int line;
+
+ DirectTraceBuffer *trace;
+} InterfaceDesc;
+
+static int alloc_count = 0;
+static int alloc_capacity = 0;
+static InterfaceDesc *alloc_list = NULL;
+static pthread_mutex_t alloc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/**************************************************************************************************/
+
+void
+direct_print_interface_leaks( void )
+{
+ unsigned int i;
+
+ pthread_mutex_lock( &alloc_lock );
+
+ if (alloc_count /*&& (!direct_config || direct_config->debug)*/) {
+ direct_log_printf( NULL, "Interface instances remaining (%d): \n", alloc_count );
+
+ for (i=0; i<alloc_count; i++) {
+ InterfaceDesc *desc = &alloc_list[i];
+
+ direct_log_printf( NULL, " - '%s' at %p (%s) allocated in %s (%s: %u)\n", desc->name,
+ desc->interface, desc->what, desc->func, desc->file, desc->line );
+
+ if (desc->trace)
+ direct_trace_print_stack( desc->trace );
+ }
+ }
+
+ pthread_mutex_unlock( &alloc_lock );
+}
+
+/**************************************************************************************************/
+
+static InterfaceDesc *
+allocate_interface_desc( void )
+{
+ int cap = alloc_capacity;
+
+ if (!cap)
+ cap = 64;
+ else if (cap == alloc_count)
+ cap <<= 1;
+
+ if (cap != alloc_capacity) {
+ alloc_capacity = cap;
+ alloc_list = realloc( alloc_list, sizeof(InterfaceDesc) * cap );
+
+ D_ASSERT( alloc_list != NULL );
+ }
+
+ return &alloc_list[alloc_count++];
+}
+
+static inline void
+fill_interface_desc( InterfaceDesc *desc,
+ const void *interface,
+ const char *name,
+ const char *func,
+ const char *file,
+ int line,
+ const char *what,
+ DirectTraceBuffer *trace )
+{
+ desc->interface = interface;
+ desc->name = strdup( name );
+ desc->what = strdup( what );
+ desc->func = func;
+ desc->file = file;
+ desc->line = line;
+ desc->trace = trace;
+}
+
+/**************************************************************************************************/
+
+__attribute__((no_instrument_function))
+void
+direct_dbg_interface_add( const char *func,
+ const char *file,
+ int line,
+ const char *what,
+ const void *interface,
+ const char *name )
+{
+ InterfaceDesc *desc;
+
+ pthread_mutex_lock( &alloc_lock );
+
+ desc = allocate_interface_desc();
+
+ fill_interface_desc( desc, interface, name,
+ func, file, line, what, direct_trace_copy_buffer(NULL) );
+
+ pthread_mutex_unlock( &alloc_lock );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_dbg_interface_remove( const char *func,
+ const char *file,
+ int line,
+ const char *what,
+ const void *interface )
+{
+ unsigned int i;
+
+ pthread_mutex_lock( &alloc_lock );
+
+ for (i=0; i<alloc_count; i++) {
+ InterfaceDesc *desc = &alloc_list[i];
+
+ if (desc->interface == interface) {
+ if (desc->trace)
+ direct_trace_free_buffer( desc->trace );
+
+ free( desc->what );
+ free( desc->name );
+
+ if (i < --alloc_count)
+ direct_memmove( desc, desc + 1, (alloc_count - i) * sizeof(InterfaceDesc) );
+
+ pthread_mutex_unlock( &alloc_lock );
+
+ return;
+ }
+ }
+
+ pthread_mutex_unlock( &alloc_lock );
+
+ D_ERROR( "Direct/Interface: unknown instance %p (%s) from [%s:%d in %s()]\n",
+ interface, what, file, line, func );
+ D_BREAK( "unknown instance" );
+}
+
+#else /* DIRECT_BUILD_DEBUG */
+
+void
+direct_print_interface_leaks( void )
+{
+}
+
+#endif /* DIRECT_BUILD_DEBUG */
+
diff --git a/Source/DirectFB/lib/direct/interface.h b/Source/DirectFB/lib/direct/interface.h
new file mode 100755
index 0000000..5e6200d
--- /dev/null
+++ b/Source/DirectFB/lib/direct/interface.h
@@ -0,0 +1,215 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__INTERFACE_H__
+#define __DIRECT__INTERFACE_H__
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+
+/*
+ * Forward declaration macro for interfaces.
+ */
+#define DECLARE_INTERFACE( IFACE ) \
+ typedef struct _##IFACE IFACE;
+
+/*
+ * Macro for an interface definition.
+ */
+#define DEFINE_INTERFACE( IFACE, IDATA... ) \
+ struct _##IFACE { \
+ void *priv; \
+ int magic; \
+ \
+ DirectResult (*AddRef)( IFACE *thiz ); \
+ DirectResult (*Release)( IFACE *thiz ); \
+ \
+ IDATA \
+ };
+
+/*
+ * Declare base interface
+ */
+DECLARE_INTERFACE( IAny )
+
+/*
+ * Define base interface
+ */
+DEFINE_INTERFACE( IAny, )
+
+/*
+ * Function type for probing of interface implementations
+ */
+typedef DirectResult (*DirectInterfaceGenericProbeFunc)( void *ctx, ... );
+
+/*
+ * Function type for initialization of interface instances
+ */
+typedef DirectResult (*DirectInterfaceGenericConstructFunc)( void *interface, ... );
+
+/*
+ * Function table for interface implementations
+ */
+typedef struct {
+ const char * (*GetType)(void);
+ const char * (*GetImplementation)(void);
+ DirectResult (*Allocate)( void **interface );
+
+ DirectInterfaceGenericProbeFunc Probe;
+ DirectInterfaceGenericConstructFunc Construct;
+} DirectInterfaceFuncs;
+
+/*
+ * Callback type for user probing interface implementations
+ */
+typedef DirectResult (*DirectInterfaceProbeFunc)( DirectInterfaceFuncs *impl, void *ctx );
+
+/*
+ * Loads an interface of a specific 'type'.
+ * Optionally an 'implementation' can be chosen.
+ * A 'probe' function can be used to check available implementations.
+ *
+ * After success 'funcs' is set.
+ */
+DirectResult DirectGetInterface( DirectInterfaceFuncs **funcs,
+ const char *type,
+ const char *implementation,
+ DirectInterfaceProbeFunc probe,
+ void *probe_ctx );
+
+/*
+ * Default probe function. Calls "funcs->Probe(ctx)".
+ * Can be used as the 'probe' argument to DirectGetInterface.
+ * 'probe_ctx' should then be set to the interface specific probe context.
+ */
+DirectResult DirectProbeInterface( DirectInterfaceFuncs *funcs, void *ctx );
+
+/*
+ * Called by implementation modules during 'dlopen'ing or at startup if linked
+ * into the executable.
+ */
+void DirectRegisterInterface( DirectInterfaceFuncs *funcs );
+
+void DirectUnregisterInterface( DirectInterfaceFuncs *funcs );
+
+void direct_print_interface_leaks(void);
+
+#if DIRECT_BUILD_DEBUGS
+void direct_dbg_interface_add ( const char *func,
+ const char *file,
+ int line,
+ const char *what,
+ const void *interface,
+ const char *name );
+
+void direct_dbg_interface_remove( const char *func,
+ const char *file,
+ int line,
+ const char *what,
+ const void *interface );
+#endif
+
+#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) || defined(DIRECT_FORCE_DEBUG)
+
+#if !DIRECT_BUILD_DEBUGS
+#error Building with debug, but library headers suggest that debug is not supported.
+#endif
+
+#define DIRECT_DBG_INTERFACE_ADD direct_dbg_interface_add
+#define DIRECT_DBG_INTERFACE_REMOVE direct_dbg_interface_remove
+
+#else
+
+#define DIRECT_DBG_INTERFACE_ADD(func,file,line,what,interface,name) do {} while (0)
+#define DIRECT_DBG_INTERFACE_REMOVE(func,file,line,what,interface) do {} while (0)
+
+#endif
+
+
+
+#define DIRECT_ALLOCATE_INTERFACE(p,i) \
+ do { \
+ (p) = (__typeof__(p))D_CALLOC( 1, sizeof(i) ); \
+ \
+ D_MAGIC_SET( (IAny*)(p), DirectInterface ); \
+ \
+ DIRECT_DBG_INTERFACE_ADD( __FUNCTION__, __FILE__, __LINE__, #p, p, #i ); \
+ } while (0)
+
+
+#define DIRECT_ALLOCATE_INTERFACE_DATA(p,i) \
+ i##_data *data; \
+ \
+ D_MAGIC_ASSERT( (IAny*)(p), DirectInterface ); \
+ \
+ if (!(p)->priv) \
+ (p)->priv = D_CALLOC( 1, sizeof(i##_data) ); \
+ \
+ data = (i##_data*)((p)->priv);
+
+
+#define DIRECT_DEALLOCATE_INTERFACE(p) \
+ DIRECT_DBG_INTERFACE_REMOVE( __FUNCTION__, __FILE__, __LINE__, #p, p ); \
+ \
+ if ((p)->priv) { \
+ D_FREE( (p)->priv ); \
+ (p)->priv = NULL; \
+ } \
+ \
+ D_MAGIC_CLEAR( (IAny*)(p) ); \
+ \
+ D_FREE( (p) );
+
+
+#define DIRECT_INTERFACE_GET_DATA(i) \
+ i##_data *data; \
+ \
+ if (!thiz) \
+ return DR_THIZNULL; \
+ \
+ D_MAGIC_ASSERT( (IAny*)thiz, DirectInterface ); \
+ \
+ data = (i##_data*) thiz->priv; \
+ \
+ if (!data) \
+ return DR_DEAD;
+
+
+#define DIRECT_INTERFACE_GET_DATA_FROM(interface,data,prefix) \
+ do { \
+ D_MAGIC_ASSERT( (IAny*)(interface), DirectInterface ); \
+ \
+ (data) = (prefix##_data*) (interface)->priv; \
+ \
+ if (!(data)) \
+ return DR_DEAD; \
+ } while (0)
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/interface_implementation.h b/Source/DirectFB/lib/direct/interface_implementation.h
new file mode 100755
index 0000000..7951b59
--- /dev/null
+++ b/Source/DirectFB/lib/direct/interface_implementation.h
@@ -0,0 +1,91 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__INTERFACE_IMPLEMENTATION_H__
+#define __DIRECT__INTERFACE_IMPLEMENTATION_H__
+
+#include <direct/interface.h>
+
+
+static const char *GetType( void );
+static const char *GetImplementation( void );
+static DirectResult Allocate( void **interface );
+
+static DirectInterfaceFuncs interface_funcs = {
+ .GetType = GetType,
+ .GetImplementation = GetImplementation,
+ .Allocate = Allocate,
+ .Probe = (DirectInterfaceGenericProbeFunc) Probe,
+ .Construct = (DirectInterfaceGenericConstructFunc) Construct
+};
+
+#define DIRECT_INTERFACE_IMPLEMENTATION(type, impl) \
+ \
+static const char * \
+GetType( void ) \
+{ \
+ return #type; \
+} \
+ \
+static const char * \
+GetImplementation( void ) \
+{ \
+ return #impl; \
+} \
+ \
+static DirectResult \
+Allocate( void **interface ) \
+{ \
+ DIRECT_ALLOCATE_INTERFACE( *interface, type ); \
+ return DR_OK; \
+} \
+ \
+__attribute__((constructor)) \
+void \
+type##_##impl##_ctor(void); \
+ \
+__attribute__((constructor)) \
+void \
+type##_##impl##_ctor(void) \
+{ \
+ DirectRegisterInterface( &interface_funcs ); \
+} \
+ \
+__attribute__((destructor)) \
+void \
+type##_##impl##_dtor(void); \
+ \
+__attribute__((destructor)) \
+void \
+type##_##impl##_dtor(void) \
+{ \
+ DirectUnregisterInterface( &interface_funcs ); \
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/list.c b/Source/DirectFB/lib/direct/list.c
new file mode 100755
index 0000000..8a82bfa
--- /dev/null
+++ b/Source/DirectFB/lib/direct/list.c
@@ -0,0 +1,35 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <direct/list.h>
+
+
diff --git a/Source/DirectFB/lib/direct/list.h b/Source/DirectFB/lib/direct/list.h
new file mode 100755
index 0000000..25ecdf8
--- /dev/null
+++ b/Source/DirectFB/lib/direct/list.h
@@ -0,0 +1,224 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__LIST_H__
+#define __DIRECT__LIST_H__
+
+#include <direct/types.h>
+#include <direct/debug.h>
+
+
+struct __D_DirectLink {
+ int magic;
+
+ DirectLink *next;
+ DirectLink *prev; /* The 'prev' pointer of the first element always points
+ to the last element of the list, for fast appending ;-) */
+};
+
+static __inline__ void
+direct_list_prepend( DirectLink **list, DirectLink *link )
+{
+ DirectLink *first = *list;
+
+ link->next = first;
+
+ if (first) {
+ D_MAGIC_ASSERT( first, DirectLink );
+
+ link->prev = first->prev;
+
+ first->prev = link;
+ }
+ else
+ link->prev = link;
+
+ *list = link;
+
+ D_MAGIC_SET( link, DirectLink );
+}
+
+static __inline__ void
+direct_list_append( DirectLink **list, DirectLink *link )
+{
+ DirectLink *first = *list;
+
+ link->next = NULL;
+
+ if (first) {
+ DirectLink *last = first->prev;
+
+ D_MAGIC_ASSERT( first, DirectLink );
+ D_MAGIC_ASSERT( last, DirectLink );
+
+ link->prev = last;
+
+ last->next = first->prev = link;
+ }
+ else
+ *list = link->prev = link;
+
+ D_MAGIC_SET( link, DirectLink );
+}
+
+static __inline__ bool
+direct_list_contains_element_EXPENSIVE( DirectLink *list, DirectLink *link )
+{
+ D_MAGIC_ASSERT_IF( list, DirectLink );
+
+ while (list) {
+ if (list == link)
+ return true;
+
+ list = list->next;
+ }
+
+ return false;
+}
+
+static __inline__ int
+direct_list_count_elements_EXPENSIVE( DirectLink *list )
+{
+ int count = 0;
+
+ while (list) {
+ D_MAGIC_ASSERT( list, DirectLink );
+
+ count++;
+
+ list = list->next;
+ }
+
+ return count;
+}
+
+static __inline__ void
+direct_list_remove( DirectLink **list, DirectLink *link )
+{
+ DirectLink *next;
+ DirectLink *prev;
+
+ D_ASSERT( list != NULL );
+
+ D_ASSERT( direct_list_contains_element_EXPENSIVE( *list, link ) );
+
+ D_MAGIC_ASSERT( *list, DirectLink );
+ D_MAGIC_ASSERT( link, DirectLink );
+
+ next = link->next;
+ prev = link->prev;
+
+ if (next) {
+ D_MAGIC_ASSERT( next, DirectLink );
+
+ next->prev = prev;
+ }
+ else
+ (*list)->prev = prev;
+
+ if (link == *list)
+ *list = next;
+ else {
+ D_MAGIC_ASSERT( prev, DirectLink );
+
+ prev->next = next;
+ }
+
+ link->next = link->prev = NULL;
+
+ D_MAGIC_CLEAR( link );
+}
+
+static __inline__ void
+direct_list_move_to_front( DirectLink **list, DirectLink *link )
+{
+ DirectLink *next;
+ DirectLink *prev;
+ DirectLink *first;
+
+ D_ASSERT( list != NULL );
+
+ first = *list;
+
+ D_ASSERT( direct_list_contains_element_EXPENSIVE( first, link ) );
+
+ D_MAGIC_ASSERT( first, DirectLink );
+ D_MAGIC_ASSERT( link, DirectLink );
+
+ if (first == link)
+ return;
+
+ next = link->next;
+ prev = link->prev;
+
+ D_MAGIC_ASSERT_IF( next, DirectLink );
+ D_MAGIC_ASSERT( prev, DirectLink );
+
+ if (next) {
+ next->prev = prev;
+
+ link->prev = first->prev;
+ }
+ else
+ link->prev = prev;
+
+ prev->next = next;
+
+ link->next = first;
+
+ first->prev = link;
+
+ *list = link;
+}
+
+static __inline__ bool
+direct_list_check_link( const DirectLink *link )
+{
+ D_MAGIC_ASSERT_IF( link, DirectLink );
+
+ return link != NULL;
+}
+
+
+#define direct_list_foreach(elem, list) \
+ for (elem = (__typeof__(elem))(list); \
+ direct_list_check_link( (DirectLink*)(elem) ); \
+ elem = (__typeof__(elem))(((DirectLink*)(elem))->next))
+
+#define direct_list_foreach_reverse(elem, list) \
+ for (elem = (__typeof__(elem))((list) ? (list)->prev : NULL); \
+ direct_list_check_link( (DirectLink*)(elem) ); \
+ elem = (__typeof__(elem))((((DirectLink*)(elem))->prev->next) ? ((DirectLink*)(elem))->prev : NULL))
+
+#define direct_list_foreach_safe(elem, temp, list) \
+ for (elem = (__typeof__(elem))(list), temp = ((__typeof__(temp))(elem) ? (__typeof__(temp))(((DirectLink*)(elem))->next) : NULL); \
+ direct_list_check_link( (DirectLink*)(elem) ); \
+ elem = (__typeof__(elem))(temp), temp = ((__typeof__(temp))(elem) ? (__typeof__(temp))(((DirectLink*)(elem))->next) : NULL))
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/log.c b/Source/DirectFB/lib/direct/log.c
new file mode 100755
index 0000000..774b7a5
--- /dev/null
+++ b/Source/DirectFB/lib/direct/log.c
@@ -0,0 +1,414 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/log.h>
+#include <direct/util.h>
+
+
+struct __D_DirectLog {
+ int magic;
+
+ DirectLogType type;
+
+ int fd;
+
+ pthread_mutex_t lock;
+};
+
+/**********************************************************************************************************************/
+
+/* Statically allocated to avoid endless loops between D_CALLOC() and D_DEBUG(), while the latter would only
+ * call the allocation once, if there wouldn't be the loopback...
+ */
+static DirectLog fallback_log;
+
+static DirectLog *default_log = NULL;
+static pthread_once_t init_fallback = PTHREAD_ONCE_INIT;
+
+/**********************************************************************************************************************/
+
+static DirectResult init_stderr( DirectLog *log );
+
+static DirectResult init_file ( DirectLog *log,
+ const char *filename );
+
+static DirectResult init_udp ( DirectLog *log,
+ const char *hostport );
+
+/**********************************************************************************************************************/
+
+DirectResult
+direct_log_create( DirectLogType type,
+ const char *param,
+ DirectLog **ret_log )
+{
+ DirectResult ret = DR_INVARG;
+ DirectLog *log;
+
+ log = D_CALLOC( 1, sizeof(DirectLog) );
+ if (!log)
+ return D_OOM();
+
+ log->type = type;
+
+ switch (type) {
+ case DLT_STDERR:
+ ret = init_stderr( log );
+ break;
+
+ case DLT_FILE:
+ ret = init_file( log, param );
+ break;
+
+ case DLT_UDP:
+ ret = init_udp( log, param );
+ break;
+ }
+
+ if (ret)
+ D_FREE( log );
+ else {
+ direct_util_recursive_pthread_mutex_init( &log->lock );
+
+ D_MAGIC_SET( log, DirectLog );
+
+ *ret_log = log;
+ }
+
+ return ret;
+}
+
+DirectResult
+direct_log_destroy( DirectLog *log )
+{
+ D_MAGIC_ASSERT( log, DirectLog );
+
+ D_ASSERT( &fallback_log != log );
+
+ if (log == default_log)
+ default_log = NULL;
+
+ close( log->fd );
+
+ D_MAGIC_CLEAR( log );
+
+ D_FREE( log );
+
+ return DR_OK;
+}
+
+__attribute__((no_instrument_function))
+DirectResult
+direct_log_printf( DirectLog *log,
+ const char *format, ... )
+{
+ va_list args;
+
+ /*
+ * Don't use D_MAGIC_ASSERT or any other
+ * macros/functions that might cause an endless loop.
+ */
+
+ va_start( args, format );
+
+ /* Use the default log if passed log is invalid. */
+ if (!log || log->magic != D_MAGIC("DirectLog"))
+ log = direct_log_default();
+
+ /* Write to stderr as a fallback if default is invalid, too. */
+ if (!log || log->magic != D_MAGIC("DirectLog")) {
+
+ printf(format,args);
+
+
+
+ //vfprintf( stderr, format, args );
+
+
+
+
+ fflush( stderr );
+ }
+ else {
+ int len;
+ char buf[512];
+
+ len = vsnprintf( buf, sizeof(buf), format, args );
+
+ pthread_mutex_lock( &log->lock );
+
+
+
+
+ // write( log->fd, buf, len );
+ printf("%s\n",buf);
+
+
+
+
+ pthread_mutex_unlock( &log->lock );
+ }
+
+ va_end( args );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_log_set_default( DirectLog *log )
+{
+ D_MAGIC_ASSERT( log, DirectLog );
+
+ default_log = log;
+
+ return DR_OK;
+}
+
+__attribute__((no_instrument_function))
+void
+direct_log_lock( DirectLog *log )
+{
+ D_MAGIC_ASSERT_IF( log, DirectLog );
+
+ if (!log)
+ log = direct_log_default();
+
+ D_MAGIC_ASSERT( log, DirectLog );
+
+ pthread_mutex_lock( &log->lock );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_log_unlock( DirectLog *log )
+{
+ D_MAGIC_ASSERT_IF( log, DirectLog );
+
+ if (!log)
+ log = direct_log_default();
+
+ D_MAGIC_ASSERT( log, DirectLog );
+
+ pthread_mutex_unlock( &log->lock );
+}
+
+__attribute__((no_instrument_function))
+static void
+init_fallback_log( void )
+{
+ fallback_log.type = DLT_STDERR;
+ fallback_log.fd = fileno( stderr );
+
+ direct_util_recursive_pthread_mutex_init( &fallback_log.lock );
+
+ D_MAGIC_SET( &fallback_log, DirectLog );
+}
+
+__attribute__((no_instrument_function))
+DirectLog *
+direct_log_default( void )
+{
+ pthread_once( &init_fallback, init_fallback_log );
+
+ if (!default_log)
+ default_log = &fallback_log;
+
+ D_MAGIC_ASSERT( default_log, DirectLog );
+
+ return default_log;
+}
+
+/**********************************************************************************************************************/
+
+static DirectResult
+init_stderr( DirectLog *log )
+{
+ log->fd = dup( fileno( stderr ) );
+
+ return DR_OK;
+}
+
+static DirectResult
+init_file( DirectLog *log,
+ const char *filename )
+{
+ DirectResult ret;
+ int fd;
+
+ fd = open( filename, O_WRONLY | O_CREAT | O_APPEND, 0664 );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Direct/Log: Could not open '%s' for writing!\n", filename );
+ return ret;
+ }
+
+ log->fd = fd;
+
+ return DR_OK;
+}
+
+static DirectResult
+parse_host_addr( const char *hostport,
+ struct addrinfo **ret_addr )
+{
+ int i, ret;
+
+ int size = strlen( hostport ) + 1;
+ char buf[size];
+
+ char *hoststr = buf;
+ char *portstr = NULL;
+ char *end;
+
+ struct addrinfo hints;
+
+ memcpy( buf, hostport, size );
+
+ for (i=0; i<size; i++) {
+ if (buf[i] == ':') {
+ buf[i] = 0;
+ portstr = &buf[i+1];
+
+ break;
+ }
+ }
+
+ if (!portstr) {
+ D_ERROR( "Direct/Log: Parse error in '%s' that should be '<host>:<port>'!\n", hostport );
+ return DR_INVARG;
+ }
+
+ strtoul( portstr, &end, 10 );
+ if (end && *end) {
+ D_ERROR( "Direct/Log: Parse error in port number '%s'!\n", portstr );
+ return DR_INVARG;
+ }
+
+ memset( &hints, 0, sizeof(hints) );
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_family = PF_UNSPEC;
+
+ ret = getaddrinfo( hoststr, portstr, &hints, ret_addr );
+ if (ret) {
+ switch (ret) {
+ case EAI_FAMILY:
+ D_ERROR( "Direct/Log: Unsupported address family!\n" );
+ return DR_UNSUPPORTED;
+
+ case EAI_SOCKTYPE:
+ D_ERROR( "Direct/Log: Unsupported socket type!\n" );
+ return DR_UNSUPPORTED;
+
+ case EAI_NONAME:
+ D_ERROR( "Direct/Log: Host not found!\n" );
+ return DR_FAILURE;
+
+ case EAI_SERVICE:
+ D_ERROR( "Direct/Log: Port %s is unreachable!\n", portstr );
+ return DR_FAILURE;
+
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY:
+#endif
+ case EAI_NODATA:
+ D_ERROR( "Direct/Log: Host found, but has no address!\n" );
+ return DR_FAILURE;
+
+ case EAI_MEMORY:
+ return D_OOM();
+
+ case EAI_FAIL:
+ D_ERROR( "Direct/Log: A non-recoverable name server error occurred!\n" );
+ return DR_FAILURE;
+
+ case EAI_AGAIN:
+ D_ERROR( "Direct/Log: Temporary error, try again!\n" );
+ return DR_TEMPUNAVAIL;
+
+ default:
+ D_ERROR( "Direct/Log: Unknown error occured!?\n" );
+ return DR_FAILURE;
+ }
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+init_udp( DirectLog *log,
+ const char *hostport )
+{
+ DirectResult ret;
+ int fd;
+ struct addrinfo *addr;
+
+ ret = parse_host_addr( hostport, &addr );
+ if (ret)
+ return ret;
+
+ fd = socket( addr->ai_family, SOCK_DGRAM, 0 );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Direct/Log: Could not create a UDP socket!\n" );
+ freeaddrinfo( addr );
+ return ret;
+ }
+
+ ret = connect( fd, addr->ai_addr, addr->ai_addrlen );
+ freeaddrinfo( addr );
+
+ if (ret) {
+ ret = errno2result( errno );
+ D_PERROR( "Direct/Log: Could not connect UDP socket to '%s'!\n", hostport );
+ close( fd );
+ return ret;
+ }
+
+ log->fd = fd;
+
+ return DR_OK;
+}
diff --git a/Source/DirectFB/lib/direct/log.h b/Source/DirectFB/lib/direct/log.h
new file mode 100755
index 0000000..68eeccb
--- /dev/null
+++ b/Source/DirectFB/lib/direct/log.h
@@ -0,0 +1,89 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__LOG_H__
+#define __DIRECT__LOG_H__
+
+#include <direct/types.h>
+#include <direct/messages.h>
+
+
+typedef enum {
+ DLT_STDERR, /* Simply print out log on stderr. */
+ DLT_FILE, /* Write log into a file. */
+ DLT_UDP /* Send out log via UDP. */
+} DirectLogType;
+
+
+/*
+ * Creates a logging facility.
+ *
+ * For each 'type' the 'param' has a different meaning:
+ * DLT_STDERR ignored (leave NULL)
+ * DLT_FILE file name
+ * DLT_UDP <ip>:<port>
+ */
+DirectResult direct_log_create ( DirectLogType type,
+ const char *param,
+ DirectLog **ret_log );
+
+/*
+ * Destroys a logging facility.
+ */
+DirectResult direct_log_destroy ( DirectLog *log );
+
+/*
+ * Write to the log in a printf fashion.
+ *
+ * If log is NULL, the default log is used if it's valid,
+ * otherwise stderr is used a fallback until now.
+ */
+DirectResult direct_log_printf ( DirectLog *log,
+ const char *format, ... ) D_FORMAT_PRINTF(2);
+
+/*
+ * Set the default log that's used when no valid log is passed.
+ */
+DirectResult direct_log_set_default( DirectLog *log );
+
+/*
+ * Locks a logging facility for non-intermixed output of multiple calls in multiple threads. Not mandatory.
+ */
+void direct_log_lock ( DirectLog *log );
+
+/*
+ * Unlocks a logging facility.
+ */
+void direct_log_unlock ( DirectLog *log );
+
+/*
+ * Returns the default log.
+ */
+DirectLog *direct_log_default( void );
+
+#endif
diff --git a/Source/DirectFB/lib/direct/mem.c b/Source/DirectFB/lib/direct/mem.c
new file mode 100755
index 0000000..7b65a32
--- /dev/null
+++ b/Source/DirectFB/lib/direct/mem.c
@@ -0,0 +1,350 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/build.h>
+
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+
+D_DEBUG_DOMAIN( Direct_Mem, "Direct/Mem", "libdirect memory allocation (debugging)" );
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ const void *mem;
+ size_t bytes;
+ const char *func;
+ const char *file;
+ int line;
+ DirectTraceBuffer *trace;
+} MemDesc;
+
+/**********************************************************************************************************************/
+
+static int alloc_count = 0;
+static int alloc_capacity = 0;
+static MemDesc *alloc_list = NULL;
+static pthread_mutex_t alloc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/**********************************************************************************************************************/
+
+void
+direct_print_memleaks( void )
+{
+ unsigned int i;
+
+ /* Debug only. */
+ pthread_mutex_lock( &alloc_lock );
+
+ if (alloc_count && (!direct_config || direct_config->debugmem)) {
+ direct_log_printf( NULL, "Local memory allocations remaining (%d): \n", alloc_count );
+
+ for (i=0; i<alloc_count; i++) {
+ MemDesc *desc = &alloc_list[i];
+
+ direct_log_printf( NULL, "%7zu bytes at %p allocated in %s (%s: %u)\n",
+ desc->bytes, desc->mem, desc->func, desc->file, desc->line );
+
+ if (desc->trace)
+ direct_trace_print_stack( desc->trace );
+ }
+ }
+
+ pthread_mutex_unlock( &alloc_lock );
+}
+
+/**********************************************************************************************************************/
+
+/* FIXME: Replace array by linked list, or at least avoid the memmove on free of an item. */
+
+static MemDesc *
+allocate_mem_desc( void )
+{
+ int cap = alloc_capacity;
+
+ if (!cap)
+ cap = 64;
+ else if (cap == alloc_count)
+ cap <<= 1;
+
+ if (cap != alloc_capacity) {
+ void *new_list = malloc( sizeof(MemDesc) * cap );
+
+ if (!new_list) {
+ D_WARN( "could not allocate more descriptors (%d->%d)", alloc_capacity, cap );
+ return NULL;
+ }
+
+ direct_memcpy( new_list, alloc_list, sizeof(MemDesc) * alloc_count );
+
+ free( alloc_list );
+
+ alloc_capacity = cap;
+ alloc_list = new_list;
+ }
+
+ return &alloc_list[alloc_count++];
+}
+
+static inline void
+fill_mem_desc( MemDesc *desc, const void *mem, int bytes,
+ const char *func, const char *file, int line, DirectTraceBuffer *trace )
+{
+ desc->mem = mem;
+ desc->bytes = bytes;
+ desc->func = func;
+ desc->file = file;
+ desc->line = line;
+ desc->trace = trace;
+}
+
+/**********************************************************************************************************************/
+
+void *
+direct_malloc( const char* file, int line, const char *func, size_t bytes )
+{
+ void *mem;
+ MemDesc *desc;
+
+ D_DEBUG_AT( Direct_Mem, " +%6zu bytes [%s:%d in %s()]\n", bytes, file, line, func );
+
+ mem = malloc( bytes );
+ if (!mem)
+ return NULL;
+
+ if (!direct_config->debugmem)
+ return mem;
+
+
+ /* Debug only. */
+ pthread_mutex_lock( &alloc_lock );
+ desc = allocate_mem_desc();
+ pthread_mutex_unlock( &alloc_lock );
+
+ if (desc)
+ fill_mem_desc( desc, mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) );
+
+ return mem;
+}
+
+void *
+direct_calloc( const char* file, int line, const char *func, size_t count, size_t bytes )
+{
+ void *mem;
+ MemDesc *desc;
+
+ D_DEBUG_AT( Direct_Mem, " +%6zu bytes [%s:%d in %s()]\n", count * bytes, file, line, func );
+
+ mem = calloc( count, bytes );
+ if (!mem)
+ return NULL;
+
+ if (!direct_config->debugmem)
+ return mem;
+
+
+ /* Debug only. */
+ pthread_mutex_lock( &alloc_lock );
+ desc = allocate_mem_desc();
+ pthread_mutex_unlock( &alloc_lock );
+
+ if (desc)
+ fill_mem_desc( desc, mem, count * bytes, func, file, line, direct_trace_copy_buffer(NULL) );
+
+ return mem;
+}
+
+void *
+direct_realloc( const char *file, int line, const char *func, const char *what, void *mem, size_t bytes )
+{
+ int i;
+
+ if (!mem)
+ return direct_malloc( file, line, func, bytes );
+
+ if (!bytes) {
+ direct_free( file, line, func, what, mem );
+ return NULL;
+ }
+
+ if (!direct_config->debugmem) {
+ D_DEBUG_AT( Direct_Mem, " *%6zu bytes [%s:%d in %s()] '%s'\n", bytes, file, line, func, what );
+ return realloc( mem, bytes );
+ }
+
+
+ /* Debug only. */
+ pthread_mutex_lock( &alloc_lock );
+
+ for (i=0; i<alloc_count; i++) {
+ MemDesc *desc = &alloc_list[i];
+
+ if (desc->mem == mem) {
+ void *new_mem = realloc( mem, bytes );
+
+ D_DEBUG_AT( Direct_Mem, " %c%6zu bytes [%s:%d in %s()] (%s%zu) <- %p -> %p '%s'\n",
+ (bytes > desc->bytes) ? '>' : '<', bytes, file, line, func,
+ (bytes > desc->bytes) ? "+" : "", bytes - desc->bytes, mem, new_mem, what);
+
+ if (desc->trace) {
+ direct_trace_free_buffer( desc->trace );
+ desc->trace = NULL;
+ }
+
+ if (!new_mem) {
+ D_WARN( "could not reallocate memory (%p: %zu->%zu)", mem, desc->bytes, bytes );
+
+ alloc_count--;
+
+ /* FIXME: This can be very slow. */
+ if (i < alloc_count)
+ direct_memmove( desc, desc + 1, (alloc_count - i) * sizeof(MemDesc) );
+ }
+ else
+ fill_mem_desc( desc, new_mem, bytes, func, file, line, direct_trace_copy_buffer(NULL) );
+
+ pthread_mutex_unlock( &alloc_lock );
+
+ return new_mem;
+ }
+ }
+
+ pthread_mutex_unlock( &alloc_lock );
+
+ D_ERROR( "Direct/Mem: Not reallocating unknown %p (%s) from [%s:%d in %s()] - corrupt/incomplete list?\n",
+ mem, what, file, line, func );
+
+ return direct_malloc( file, line, func, bytes );
+}
+
+void
+direct_free( const char *file, int line, const char *func, const char *what, void *mem )
+{
+ unsigned int i;
+
+ if (!mem) {
+ D_WARN( "%s (NULL) called", __FUNCTION__ );
+ return;
+ }
+
+ if (!direct_config->debugmem) {
+ D_DEBUG_AT( Direct_Mem, " - number of bytes of %s [%s:%d in %s()] -> %p\n", what, file, line, func, mem );
+ free( mem );
+ return;
+ }
+
+
+ /* Debug only. */
+ pthread_mutex_lock( &alloc_lock );
+
+ for (i=0; i<alloc_count; i++) {
+ MemDesc *desc = &alloc_list[i];
+
+ if (desc->mem == mem) {
+ free( mem );
+
+ D_DEBUG_AT( Direct_Mem, " -%6zu bytes [%s:%d in %s()] -> %p '%s'\n",
+ desc->bytes, file, line, func, mem, what );
+
+ if (desc->trace)
+ direct_trace_free_buffer( desc->trace );
+
+ alloc_count--;
+
+ /* FIXME: This can be very slow. */
+ if (i < alloc_count)
+ direct_memmove( desc, desc + 1, (alloc_count - i) * sizeof(MemDesc) );
+
+ pthread_mutex_unlock( &alloc_lock );
+
+ return;
+ }
+ }
+
+ pthread_mutex_unlock( &alloc_lock );
+
+ D_ERROR( "Direct/Mem: Not freeing unknown %p (%s) from [%s:%d in %s()] - corrupt/incomplete list?\n",
+ mem, what, file, line, func );
+}
+
+char *
+direct_strdup( const char* file, int line, const char *func, const char *string )
+{
+ void *mem;
+ MemDesc *desc;
+ size_t length = strlen( string ) + 1;
+
+ mem = malloc( length );
+ D_DEBUG_AT( Direct_Mem, " +%6zu bytes [%s:%d in %s()] -> %p \"%30s\"\n", length, file, line, func, mem, string );
+ if (!mem)
+ return NULL;
+
+ direct_memcpy( mem, string, length );
+
+ if (!direct_config->debugmem)
+ return mem;
+
+
+ /* Debug only. */
+ pthread_mutex_lock( &alloc_lock );
+ desc = allocate_mem_desc();
+ pthread_mutex_unlock( &alloc_lock );
+
+ if (desc)
+ fill_mem_desc( desc, mem, length, func, file, line, direct_trace_copy_buffer(NULL) );
+
+ return mem;
+}
+
+/**********************************************************************************************************************/
+
+#else
+
+void
+direct_print_memleaks( void )
+{
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/mem.h b/Source/DirectFB/lib/direct/mem.h
new file mode 100755
index 0000000..2366e26
--- /dev/null
+++ b/Source/DirectFB/lib/direct/mem.h
@@ -0,0 +1,84 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__MEM_H__
+#define __DIRECT__MEM_H__
+
+#include <stddef.h>
+
+#include <direct/build.h>
+
+void direct_print_memleaks( void );
+
+
+void direct_free ( const char *file, int line,
+ const char *func, const char *what, void *mem );
+
+void *direct_malloc ( const char *file, int line,
+ const char *func, size_t bytes );
+
+void *direct_calloc ( const char *file, int line,
+ const char *func, size_t count, size_t bytes);
+
+void *direct_realloc( const char *file, int line,
+ const char *func, const char *what, void *mem,
+ size_t bytes );
+
+char *direct_strdup ( const char *file, int line,
+ const char *func, const char *string );
+
+
+#if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) || defined(DIRECT_FORCE_DEBUG)
+
+#if !DIRECT_BUILD_DEBUGS
+#warning Building with debug, but library headers suggest that debug is not supported.
+#endif
+
+
+#define D_FREE(mem) direct_free( __FILE__, __LINE__, __FUNCTION__, #mem, mem )
+#define D_MALLOC(bytes) direct_malloc( __FILE__, __LINE__, __FUNCTION__, bytes )
+#define D_CALLOC(count,bytes) direct_calloc( __FILE__, __LINE__, __FUNCTION__, count, bytes )
+#define D_REALLOC(mem,bytes) direct_realloc( __FILE__, __LINE__, __FUNCTION__, #mem, mem, bytes )
+#define D_STRDUP(string) direct_strdup( __FILE__, __LINE__, __FUNCTION__, string )
+
+#else
+
+#include <stdlib.h>
+#include <string.h>
+
+#define D_FREE free
+#define D_MALLOC malloc
+#define D_CALLOC calloc
+#define D_REALLOC realloc
+#define D_STRDUP strdup
+
+#endif
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/memcpy.c b/Source/DirectFB/lib/direct/memcpy.c
new file mode 100755
index 0000000..918853f
--- /dev/null
+++ b/Source/DirectFB/lib/direct/memcpy.c
@@ -0,0 +1,265 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ Fast memcpy code was taken from xine (see below).
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <dfb_types.h>
+
+#include <direct/conf.h>
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#if defined (ARCH_PPC) || defined (ARCH_ARM) || (SIZEOF_LONG == 8)
+# define RUN_BENCHMARK 1
+#else
+# define RUN_BENCHMARK 0
+#endif
+
+#if RUN_BENCHMARK
+D_DEBUG_DOMAIN( Direct_Memcpy, "Direct/Memcpy", "Direct's Memcpy Routines" );
+#endif
+
+#ifdef USE_PPCASM
+#include "ppcasm_memcpy.h"
+#endif
+
+#if defined(USE_ARMASM) && !defined(WORDS_BIGENDIAN)
+#include "armasm_memcpy.h"
+#endif
+
+
+#if SIZEOF_LONG == 8
+
+static void * generic64_memcpy( void * to, const void * from, size_t len )
+{
+ register u8 *d = (u8*)to;
+ register const u8 *s = (const u8*)from;
+ size_t n;
+
+ if (len >= 128) {
+ unsigned long delta;
+
+ /* Align destination to 8-byte boundary */
+ delta = (unsigned long)d & 7;
+ if (delta) {
+ len -= 8 - delta;
+
+ if ((unsigned long)d & 1) {
+ *d++ = *s++;
+ }
+ if ((unsigned long)d & 2) {
+ *((u16*)d) = *((const u16*)s);
+ d += 2; s += 2;
+ }
+ if ((unsigned long)d & 4) {
+ *((u32*)d) = *((const u32*)s);
+ d += 4; s += 4;
+ }
+ }
+
+ n = len >> 6;
+ len &= 63;
+
+ for (; n; n--) {
+ ((u64*)d)[0] = ((const u64*)s)[0];
+ ((u64*)d)[1] = ((const u64*)s)[1];
+ ((u64*)d)[2] = ((const u64*)s)[2];
+ ((u64*)d)[3] = ((const u64*)s)[3];
+ ((u64*)d)[4] = ((const u64*)s)[4];
+ ((u64*)d)[5] = ((const u64*)s)[5];
+ ((u64*)d)[6] = ((const u64*)s)[6];
+ ((u64*)d)[7] = ((const u64*)s)[7];
+ d += 64; s += 64;
+ }
+ }
+ /*
+ * Now do the tail of the block
+ */
+ if (len) {
+ n = len >> 3;
+
+ for (; n; n--) {
+ *((u64*)d) = *((const u64*)s);
+ d += 8; s += 8;
+ }
+ if (len & 4) {
+ *((u32*)d) = *((const u32*)s);
+ d += 4; s += 4;
+ }
+ if (len & 2) {
+ *((u16*)d) = *((const u16*)s);
+ d += 2; s += 2;
+ }
+ if (len & 1)
+ *d = *s;
+ }
+
+ return to;
+}
+
+#endif /* SIZEOF_LONG == 8 */
+
+
+typedef void* (*memcpy_func)(void *to, const void *from, size_t len);
+
+static struct {
+ char *name;
+ char *desc;
+ memcpy_func function;
+ unsigned long long time;
+ u32 cpu_require;
+} memcpy_method[] =
+{
+ { NULL, NULL, NULL, 0, 0},
+ { "libc", "libc memcpy()", (memcpy_func) memcpy, 0, 0},
+#if SIZEOF_LONG == 8
+ { "generic64","Generic 64bit memcpy()", generic64_memcpy, 0, 0},
+#endif /* SIZEOF_LONG == 8 */
+#ifdef USE_PPCASM
+ { "ppc", "ppcasm_memcpy()", direct_ppcasm_memcpy, 0, 0},
+#ifdef __LINUX__
+ { "ppccache", "ppcasm_cacheable_memcpy()", direct_ppcasm_cacheable_memcpy, 0, 0},
+#endif /* __LINUX__ */
+#endif /* USE_PPCASM */
+#if defined(USE_ARMASM) && !defined(WORDS_BIGENDIAN)
+ { "arm", "armasm_memcpy()", direct_armasm_memcpy, 0, 0},
+#endif
+ { NULL, NULL, NULL, 0, 0}
+};
+
+
+static inline unsigned long long int rdtsc( void )
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ return (tv.tv_sec * 1000000 + tv.tv_usec);
+}
+
+
+memcpy_func direct_memcpy = (memcpy_func) memcpy;
+
+#define BUFSIZE 1024
+
+void
+direct_find_best_memcpy( void )
+{
+ /* Save library size and startup time
+ on platforms without a special memcpy() implementation. */
+#if RUN_BENCHMARK
+ unsigned long long t;
+ char *buf1, *buf2;
+ int i, j, best = 0;
+ u32 config_flags = 0;
+
+ if (direct_config->memcpy) {
+ for (i=1; memcpy_method[i].name; i++) {
+ if (!strcmp( direct_config->memcpy, memcpy_method[i].name )) {
+ if (memcpy_method[i].cpu_require & ~config_flags)
+ break;
+
+ direct_memcpy = memcpy_method[i].function;
+
+ D_INFO( "Direct/Memcpy: Forced to use %s\n", memcpy_method[i].desc );
+
+ return;
+ }
+ }
+ }
+
+ if (!(buf1 = D_MALLOC( BUFSIZE * 500 )))
+ return;
+
+ if (!(buf2 = D_MALLOC( BUFSIZE * 500 ))) {
+ D_FREE( buf1 );
+ return;
+ }
+
+ D_DEBUG_AT( Direct_Memcpy, "Benchmarking memcpy methods (smaller is better):\n");
+
+ /* make sure buffers are present on physical memory */
+ memcpy( buf1, buf2, BUFSIZE * 500 );
+ memcpy( buf2, buf1, BUFSIZE * 500 );
+
+ for (i=1; memcpy_method[i].name; i++) {
+ if (memcpy_method[i].cpu_require & ~config_flags)
+ continue;
+
+ t = rdtsc();
+
+ for (j=0; j<500; j++)
+ memcpy_method[i].function( buf1 + j*BUFSIZE, buf2 + j*BUFSIZE, BUFSIZE );
+
+ t = rdtsc() - t;
+ memcpy_method[i].time = t;
+
+ D_DEBUG_AT( Direct_Memcpy, "\t%-10s %20lld\n", memcpy_method[i].name, t );
+
+ if (best == 0 || t < memcpy_method[best].time)
+ best = i;
+ }
+
+ if (best) {
+ direct_memcpy = memcpy_method[best].function;
+
+ D_INFO( "Direct/Memcpy: Using %s\n", memcpy_method[best].desc );
+ }
+
+ D_FREE( buf1 );
+ D_FREE( buf2 );
+#endif
+}
+
+void
+direct_print_memcpy_routines( void )
+{
+ int i;
+ u32 config_flags = 0;
+
+ direct_log_printf( NULL, "\nPossible values for memcpy option are:\n\n" );
+
+ for (i=1; memcpy_method[i].name; i++) {
+ bool unsupported = (memcpy_method[i].cpu_require & ~config_flags);
+
+ direct_log_printf( NULL, " %-10s %-27s %s\n", memcpy_method[i].name,
+ memcpy_method[i].desc, unsupported ? "" : "supported" );
+ }
+
+ direct_log_printf( NULL, "\n" );
+}
+
diff --git a/Source/DirectFB/lib/direct/memcpy.h b/Source/DirectFB/lib/direct/memcpy.h
new file mode 100755
index 0000000..374bc54
--- /dev/null
+++ b/Source/DirectFB/lib/direct/memcpy.h
@@ -0,0 +1,51 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__MEMCPY_H__
+#define __DIRECT__MEMCPY_H__
+
+#include <stdlib.h>
+#include <string.h>
+
+
+void direct_find_best_memcpy( void );
+void direct_print_memcpy_routines( void );
+
+extern void *(*direct_memcpy)( void *to, const void *from, size_t len );
+
+static __inline__ void *direct_memmove( void *to, const void *from, size_t len )
+{
+ if ((from < to && ((const char*) from + len) < ((char*) to)) ||
+ (((char*) to + len) < ((const char*) from)))
+ return direct_memcpy( to, from, len );
+ else
+ return memmove( to, from, len );
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/messages.c b/Source/DirectFB/lib/direct/messages.c
new file mode 100755
index 0000000..21b5978
--- /dev/null
+++ b/Source/DirectFB/lib/direct/messages.c
@@ -0,0 +1,215 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <direct/build.h>
+#include <direct/log.h>
+#include <direct/messages.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+
+#if DIRECT_BUILD_TEXT
+
+__attribute__((no_instrument_function))
+void
+direct_messages_info( const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, "(*) %s", buf );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_error( const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, "(!) %s", buf );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_derror( DirectResult result, const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, "(!) %s --> %s\n", buf, DirectResultString( result ) );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_perror( int erno, const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, "(!) %s --> %s\n", buf, strerror( erno ) );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_dlerror( const char *dlerr, const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, "(!) %s --> %s\n", buf, dlerr );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_once( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, " (!!!) *** ONCE [%s] *** [%s:%d in %s()]\n", buf, file, line, func );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_unimplemented( const char *func,
+ const char *file,
+ int line )
+{
+ direct_log_printf( NULL, " (!!!) *** UNIMPLEMENTED [%s] *** [%s:%d]\n", func, file, line );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_bug( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, " (!?!) *** BUG [%s] *** [%s:%d in %s()]\n", buf, file, line, func );
+
+ direct_trace_print_stack( NULL );
+}
+
+__attribute__((no_instrument_function))
+void
+direct_messages_warn( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... )
+{
+ char buf[512];
+
+ va_list ap;
+
+ va_start( ap, format );
+
+ vsnprintf( buf, sizeof(buf), format, ap );
+
+ va_end( ap );
+
+ direct_log_printf( NULL, " (!!!) *** WARNING [%s] *** [%s:%d in %s()]\n", buf, file, line, func );
+
+ direct_trace_print_stack( NULL );
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/messages.h b/Source/DirectFB/lib/direct/messages.h
new file mode 100755
index 0000000..bafce88
--- /dev/null
+++ b/Source/DirectFB/lib/direct/messages.h
@@ -0,0 +1,173 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__MESSAGES_H__
+#define __DIRECT__MESSAGES_H__
+
+#include <direct/build.h>
+#include <direct/types.h>
+
+
+#if __GNUC__ >= 3
+#define D_FORMAT_PRINTF(n) __attribute__((__format__ (__printf__, n, n+1)))
+#else
+#define D_FORMAT_PRINTF(n)
+#endif
+
+typedef enum {
+ DMT_NONE = 0x00000000, /* No message type. */
+
+ DMT_BANNER = 0x00000001, /* Startup banner. */
+ DMT_INFO = 0x00000002, /* Info messages. */
+ DMT_WARNING = 0x00000004, /* Warnings. */
+ DMT_ERROR = 0x00000008, /* Error messages: regular, with DFBResult, bugs,
+ system call errors, dlopen errors */
+ DMT_UNIMPLEMENTED = 0x00000010, /* Messages notifying unimplemented functionality. */
+ DMT_ONCE = 0x00000020, /* One-shot messages .*/
+
+ DMT_ALL = 0x0000003f /* All types. */
+} DirectMessageType;
+
+#if DIRECT_BUILD_TEXT
+
+#include <errno.h>
+
+#include <direct/conf.h>
+
+
+void direct_messages_info ( const char *format, ... ) D_FORMAT_PRINTF(1);
+
+void direct_messages_error ( const char *format, ... ) D_FORMAT_PRINTF(1);
+
+void direct_messages_derror ( DirectResult result,
+ const char *format, ... ) D_FORMAT_PRINTF(2);
+
+void direct_messages_perror ( int erno,
+ const char *format, ... ) D_FORMAT_PRINTF(2);
+
+void direct_messages_dlerror ( const char *dlerr,
+ const char *format, ... ) D_FORMAT_PRINTF(2);
+
+void direct_messages_once ( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... ) D_FORMAT_PRINTF(4);
+
+void direct_messages_unimplemented( const char *func,
+ const char *file,
+ int line );
+
+void direct_messages_bug ( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... ) D_FORMAT_PRINTF(4);
+
+void direct_messages_warn ( const char *func,
+ const char *file,
+ int line,
+ const char *format, ... ) D_FORMAT_PRINTF(4);
+
+
+#define D_INFO(x...) do { \
+ if (!(direct_config->quiet & DMT_INFO)) \
+ direct_messages_info( x ); \
+ } while (0)
+
+#define D_ERROR(x...) do { \
+ if (!(direct_config->quiet & DMT_ERROR)) \
+ direct_messages_error( x ); \
+ } while (0)
+
+#define D_DERROR(r,x...) do { \
+ if (!(direct_config->quiet & DMT_ERROR)) \
+ direct_messages_derror( r, x ); \
+ } while (0)
+
+#define D_PERROR(x...) do { \
+ if (!(direct_config->quiet & DMT_ERROR)) \
+ direct_messages_perror( errno, x ); \
+ } while (0)
+
+#define D_DLERROR(x...) do { \
+ if (!(direct_config->quiet & DMT_ERROR)) \
+ direct_messages_dlerror( dlerror(), x ); \
+ } while (0)
+
+
+#define D_ONCE(x...) do { \
+ if (!(direct_config->quiet & DMT_ONCE)) { \
+ static bool first = true; \
+ if (first) { \
+ direct_messages_once( __FUNCTION__, \
+ __FILE__, __LINE__, x ); \
+ first = false; \
+ } \
+ } \
+ } while (0)
+
+#define D_UNIMPLEMENTED() do { \
+ if (!(direct_config->quiet & DMT_UNIMPLEMENTED)) { \
+ static bool first = true; \
+ if (first) { \
+ direct_messages_unimplemented( __FUNCTION__, \
+ __FILE__, __LINE__ ); \
+ first = false; \
+ } \
+ } \
+ } while (0)
+
+#define D_BUG(x...) do { \
+ if (!(direct_config->quiet & DMT_ERROR)) \
+ direct_messages_bug( __FUNCTION__, __FILE__, __LINE__, x ); \
+ } while (0)
+
+#define D_WARN(x...) do { \
+ if (!(direct_config->quiet & DMT_WARNING)) \
+ direct_messages_warn( __FUNCTION__, __FILE__, __LINE__, x );\
+ } while (0)
+
+#define D_OOM() (direct_messages_warn( __FUNCTION__, __FILE__, __LINE__, \
+ "out of memory" ), DR_NOLOCALMEMORY)
+
+
+#else
+ #define D_INFO(x...) do { } while (0)
+ #define D_ERROR(x...) do { } while (0)
+ #define D_DERROR(x...) do { } while (0)
+ #define D_PERROR(x...) do { } while (0)
+ #define D_DLERROR(x...) do { } while (0)
+ #define D_ONCE(x...) do { } while (0)
+ #define D_UNIMPLEMENTED() do { } while (0)
+ #define D_BUG(x...) do { } while (0)
+ #define D_WARN(x...) do { } while (0)
+ #define D_OOM() (printf("out of memory\n"), DR_NOLOCALMEMORY)
+#endif
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/modules.c b/Source/DirectFB/lib/direct/modules.c
new file mode 100755
index 0000000..ba3d59b
--- /dev/null
+++ b/Source/DirectFB/lib/direct/modules.c
@@ -0,0 +1,463 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <alloca.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <direct/conf.h>
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/modules.h>
+
+#ifdef PIC
+#define DYNAMIC_LINKING
+#endif
+
+#ifdef DYNAMIC_LINKING
+#include <dlfcn.h>
+#endif
+
+D_DEBUG_DOMAIN( Direct_Modules, "Direct/Modules", "Module loading and registration" );
+
+/******************************************************************************/
+
+#ifdef DYNAMIC_LINKING
+
+static DirectModuleEntry *lookup_by_name( const DirectModuleDir *directory,
+ const char *name );
+
+static DirectModuleEntry *lookup_by_file( const DirectModuleDir *directory,
+ const char *file );
+
+static void *open_module ( DirectModuleEntry *module );
+static bool load_module ( DirectModuleEntry *module );
+static void unload_module( DirectModuleEntry *module );
+
+#endif
+
+/******************************************************************************/
+
+static int
+suppress_module (const char *name)
+{
+ int i = 0;
+
+ if (!direct_config || !direct_config->disable_module)
+ return 0;
+
+ while (direct_config->disable_module[i]) {
+ if (strcmp (direct_config->disable_module[i], name) == 0) {
+ D_INFO( "Direct/Modules: suppress module '%s'\n", direct_config->disable_module[i] );
+ return 1;
+ }
+
+ i++;
+ }
+
+ return 0;
+}
+
+void
+direct_modules_register( DirectModuleDir *directory,
+ unsigned int abi_version,
+ const char *name,
+ const void *funcs )
+{
+ DirectModuleEntry *entry;
+
+ D_ASSERT( directory != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( funcs != NULL );
+
+ D_DEBUG_AT( Direct_Modules, "Registering '%s' ('%s')...\n", name, directory->path );
+
+#ifdef DYNAMIC_LINKING
+ if ((entry = lookup_by_name( directory, name )) != NULL) {
+ D_MAGIC_ASSERT( entry, DirectModuleEntry );
+
+ entry->loaded = true;
+ entry->funcs = funcs;
+
+ return;
+ }
+#endif
+
+ if (directory->loading) {
+ entry = directory->loading;
+ D_MAGIC_ASSERT( entry, DirectModuleEntry );
+
+ directory->loading = NULL;
+ }
+ else {
+ entry = D_CALLOC( 1, sizeof(DirectModuleEntry) );
+ if (!entry) {
+ D_OOM();
+ return;
+ }
+
+ D_MAGIC_SET( entry, DirectModuleEntry );
+ }
+
+ entry->directory = directory;
+ entry->loaded = true;
+ entry->name = D_STRDUP( name );
+ entry->funcs = funcs;
+
+ entry->disabled = suppress_module( name );
+
+ if (abi_version != directory->abi_version) {
+ D_ERROR( "Direct/Modules: ABI version of '%s' (%d) does not match %d!\n",
+ entry->file ? entry->file : entry->name,
+ abi_version, directory->abi_version );
+
+ entry->disabled = true;
+ }
+
+ direct_list_prepend( &directory->entries, &entry->link );
+
+ D_DEBUG_AT( Direct_Modules, "...registered.\n" );
+}
+
+void
+direct_modules_unregister( DirectModuleDir *directory,
+ const char *name )
+{
+ DirectModuleEntry *entry;
+
+ D_DEBUG_AT( Direct_Modules, "Unregistering '%s' ('%s')...\n", name, directory->path );
+
+#ifdef DYNAMIC_LINKING
+ entry = lookup_by_name( directory, name );
+ if (!entry) {
+ D_ERROR( "Direct/Modules: Unregister failed, could not find '%s' module!\n", name );
+ return;
+ }
+
+ D_MAGIC_ASSERT( entry, DirectModuleEntry );
+
+ D_FREE( entry->name );
+
+ direct_list_remove( &directory->entries, &entry->link );
+
+ D_MAGIC_CLEAR( entry );
+
+ D_FREE( entry );
+#endif
+
+ D_DEBUG_AT( Direct_Modules, "...unregistered.\n" );
+}
+
+int
+direct_modules_explore_directory( DirectModuleDir *directory )
+{
+#ifdef DYNAMIC_LINKING
+ DIR *dir;
+ struct dirent *entry = NULL;
+ struct dirent tmp;
+ int count = 0;
+ const char *pathfront = "";
+ const char *path;
+ char *buf;
+
+ D_ASSERT( directory != NULL );
+ D_ASSERT( directory->path != NULL );
+
+ D_DEBUG_AT( Direct_Modules, "%s( '%s' )\n", __FUNCTION__, directory->path );
+
+ path = directory->path;
+
+ if (path[0] != '/') {
+ pathfront = direct_config->module_dir;
+ if (!pathfront)
+ pathfront = MODULEDIR;
+ }
+
+ buf = alloca( strlen(pathfront) + 1 + strlen(path) + 1 ); /* pre, slash, post, 0 */
+ sprintf( buf, "%s/%s", pathfront, path );
+
+ dir = opendir( buf );
+ if (!dir) {
+ D_DEBUG_AT( Direct_Modules, " -> ERROR opening directory: %s!\n", strerror(errno) );
+ return 0;
+ }
+
+ while (readdir_r( dir, &tmp, &entry ) == 0 && entry) {
+ void *handle;
+ DirectModuleEntry *module;
+ int entry_len = strlen(entry->d_name);
+
+ if (entry_len < 4 ||
+ entry->d_name[entry_len-1] != 'o' ||
+ entry->d_name[entry_len-2] != 's')
+ continue;
+
+ if (lookup_by_file( directory, entry->d_name ))
+ continue;
+
+
+ module = D_CALLOC( 1, sizeof(DirectModuleEntry) );
+ if (!module)
+ continue;
+
+ D_MAGIC_SET( module, DirectModuleEntry );
+
+ module->directory = directory;
+ module->dynamic = true;
+ module->file = D_STRDUP( entry->d_name );
+ if (!module->file) {
+ D_MAGIC_CLEAR( module );
+ D_FREE( module );
+ continue;
+ }
+
+ directory->loading = module;
+
+ if ((handle = open_module( module )) != NULL) {
+ if (!module->loaded) {
+ int len;
+ void (*func)( void );
+
+ D_ERROR( "Direct/Modules: Module '%s' did not register itself after loading! "
+ "Trying default module constructor...\n", entry->d_name );
+
+ len = strlen( entry->d_name );
+
+ entry->d_name[len-3] = 0;
+
+ func = dlsym( handle, entry->d_name + 3 );
+ if (func) {
+ func();
+
+ if (!module->loaded) {
+ D_ERROR( "Direct/Modules: ... even did not register after "
+ "explicitly calling the module constructor!\n" );
+ }
+ }
+ else {
+ D_ERROR( "Direct/Modules: ... default contructor not found!\n" );
+ }
+
+ if (!module->loaded) {
+ module->disabled = true;
+
+ direct_list_prepend( &directory->entries,
+ &module->link );
+ }
+ }
+
+ if (module->disabled) {
+ module->loaded = false;
+
+ /* may call direct_modules_unregister() */
+ dlclose( handle );
+ }
+ else {
+ module->handle = handle;
+
+ count++;
+ }
+ }
+ else {
+ module->disabled = true;
+
+ direct_list_prepend( &directory->entries, &module->link );
+ }
+
+ directory->loading = NULL;
+ }
+
+ closedir( dir );
+
+ return count;
+#else
+ return 0;
+#endif
+}
+
+const void *
+direct_module_ref( DirectModuleEntry *module )
+{
+ D_MAGIC_ASSERT( module, DirectModuleEntry );
+
+ if (module->disabled)
+ return NULL;
+
+#ifdef DYNAMIC_LINKING
+ if (!module->loaded && !load_module( module ))
+ return NULL;
+#endif
+
+ module->refs++;
+
+ return module->funcs;
+}
+
+void
+direct_module_unref( DirectModuleEntry *module )
+{
+ D_MAGIC_ASSERT( module, DirectModuleEntry );
+ D_ASSERT( module->refs > 0 );
+
+ if (--module->refs)
+ return;
+
+#ifdef DYNAMIC_LINKING
+ if (module->dynamic)
+ unload_module( module );
+#endif
+}
+
+/******************************************************************************/
+
+#ifdef DYNAMIC_LINKING
+
+static DirectModuleEntry *
+lookup_by_name( const DirectModuleDir *directory,
+ const char *name )
+{
+ DirectLink *l;
+
+ D_ASSERT( directory != NULL );
+ D_ASSERT( name != NULL );
+
+ direct_list_foreach (l, directory->entries) {
+ DirectModuleEntry *entry = (DirectModuleEntry*) l;
+
+ D_MAGIC_ASSERT( entry, DirectModuleEntry );
+
+ if (!entry->name)
+ continue;
+
+ if (!strcmp( entry->name, name ))
+ return entry;
+ }
+
+ return NULL;
+}
+
+static DirectModuleEntry *
+lookup_by_file( const DirectModuleDir *directory,
+ const char *file )
+{
+ DirectLink *l;
+
+ D_ASSERT( directory != NULL );
+ D_ASSERT( file != NULL );
+
+ direct_list_foreach (l, directory->entries) {
+ DirectModuleEntry *entry = (DirectModuleEntry*) l;
+
+ D_MAGIC_ASSERT( entry, DirectModuleEntry );
+
+ if (!entry->file)
+ continue;
+
+ if (!strcmp( entry->file, file ))
+ return entry;
+ }
+
+ return NULL;
+}
+
+static bool
+load_module( DirectModuleEntry *module )
+{
+ D_MAGIC_ASSERT( module, DirectModuleEntry );
+ D_ASSERT( module->dynamic == true );
+ D_ASSERT( module->file != NULL );
+ D_ASSERT( module->loaded == false );
+ D_ASSERT( module->disabled == false );
+
+ module->handle = open_module( module );
+
+ return module->loaded;
+}
+
+static void
+unload_module( DirectModuleEntry *module )
+{
+ void *handle;
+
+ D_MAGIC_ASSERT( module, DirectModuleEntry );
+ D_ASSERT( module->dynamic == true );
+ D_ASSERT( module->handle != NULL );
+ D_ASSERT( module->loaded == true );
+
+ handle = module->handle;
+
+ module->handle = NULL;
+ module->loaded = false;
+
+ /* may call direct_modules_unregister() */
+ dlclose( handle );
+}
+
+static void *
+open_module( DirectModuleEntry *module )
+{
+ DirectModuleDir *directory;
+ const char *pathfront = "";
+ const char *path;
+ char *buf;
+ void *handle;
+
+ D_MAGIC_ASSERT( module, DirectModuleEntry );
+
+ D_ASSERT( module->file != NULL );
+ D_ASSERT( module->directory != NULL );
+ D_ASSERT( module->directory->path != NULL );
+
+ directory = module->directory;
+ path = directory->path;
+
+ if (path[0] != '/') {
+ pathfront = direct_config->module_dir;
+ if (!pathfront)
+ pathfront = MODULEDIR;
+ }
+
+ buf = alloca( strlen( pathfront ) + 1 + strlen( path ) + 1 + strlen( module->file ) + 1 );
+ sprintf( buf, "%s/%s/%s", pathfront, path, module->file );
+
+ D_DEBUG_AT( Direct_Modules, "Loading '%s'...\n", buf );
+
+ handle = dlopen( buf, RTLD_NOW );
+ if (!handle)
+ D_DLERROR( "Direct/Modules: Unable to dlopen `%s'!\n", buf );
+
+ return handle;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/modules.h b/Source/DirectFB/lib/direct/modules.h
new file mode 100755
index 0000000..ba11b83
--- /dev/null
+++ b/Source/DirectFB/lib/direct/modules.h
@@ -0,0 +1,95 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__MODULES_H__
+#define __DIRECT__MODULES_H__
+
+#include <pthread.h>
+
+#include <direct/types.h>
+#include <direct/list.h>
+#include <direct/util.h>
+
+
+struct __D_DirectModuleEntry {
+ DirectLink link;
+
+ int magic;
+
+ DirectModuleDir *directory;
+
+ bool loaded;
+ bool dynamic;
+ bool disabled;
+
+ char *name;
+ const void *funcs;
+
+ int refs;
+ char *file;
+ void *handle;
+};
+
+struct __D_DirectModuleDir {
+ pthread_mutex_t lock;
+
+ const char *path;
+ unsigned int abi_version;
+
+ DirectLink *entries;
+
+ DirectModuleEntry *loading;
+};
+
+#define DECLARE_MODULE_DIRECTORY(d) \
+ extern DirectModuleDir d
+
+#define DEFINE_MODULE_DIRECTORY(d,p,n) \
+ DirectModuleDir d = { \
+ .lock = PTHREAD_MUTEX_INITIALIZER, \
+ .path = p, \
+ .abi_version = n, \
+ .entries = NULL, \
+ .loading = NULL, \
+ }
+
+int direct_modules_explore_directory( DirectModuleDir *directory );
+
+void direct_modules_register( DirectModuleDir *directory,
+ unsigned int abi_version,
+ const char *name,
+ const void *funcs );
+
+void direct_modules_unregister( DirectModuleDir *directory,
+ const char *name );
+
+const void *direct_module_ref ( DirectModuleEntry *module );
+void direct_module_unref( DirectModuleEntry *module );
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/ppc_asm.h b/Source/DirectFB/lib/direct/ppc_asm.h
new file mode 100755
index 0000000..c35192b
--- /dev/null
+++ b/Source/DirectFB/lib/direct/ppc_asm.h
@@ -0,0 +1,115 @@
+/* Condition Register Bit Fields */
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+
+/* General Purpose Registers (GPRs) */
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+
+/* Floating Point Registers (FPRs) */
+
+#define fr0 0
+#define fr1 1
+#define fr2 2
+#define fr3 3
+#define fr4 4
+#define fr5 5
+#define fr6 6
+#define fr7 7
+#define fr8 8
+#define fr9 9
+#define fr10 10
+#define fr11 11
+#define fr12 12
+#define fr13 13
+#define fr14 14
+#define fr15 15
+#define fr16 16
+#define fr17 17
+#define fr18 18
+#define fr19 19
+#define fr20 20
+#define fr21 21
+#define fr22 22
+#define fr23 23
+#define fr24 24
+#define fr25 25
+#define fr26 26
+#define fr27 27
+#define fr28 28
+#define fr29 29
+#define fr30 30
+#define fr31 31
+
+#define vr0 0
+#define vr1 1
+#define vr2 2
+#define vr3 3
+#define vr4 4
+#define vr5 5
+#define vr6 6
+#define vr7 7
+#define vr8 8
+#define vr9 9
+#define vr10 10
+#define vr11 11
+#define vr12 12
+#define vr13 13
+#define vr14 14
+#define vr15 15
+#define vr16 16
+#define vr17 17
+#define vr18 18
+#define vr19 19
+#define vr20 20
+#define vr21 21
+#define vr22 22
+#define vr23 23
+#define vr24 24
+#define vr25 25
+#define vr26 26
+#define vr27 27
+#define vr28 28
+#define vr29 29
+#define vr30 30
+#define vr31 31
diff --git a/Source/DirectFB/lib/direct/ppcasm_memcpy.S b/Source/DirectFB/lib/direct/ppcasm_memcpy.S
new file mode 100755
index 0000000..04b695b
--- /dev/null
+++ b/Source/DirectFB/lib/direct/ppcasm_memcpy.S
@@ -0,0 +1,77 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ *
+ * In a mail from Paul on 23.10.2006 05:47:
+ *
+ * You may put an LGPL permission statement on that code, replacing the
+ * GPL permission statement. From a technical point of view, I'm not
+ * sure that the code in ppcasm_memcpy_cachable.S is the best thing to
+ * use in userspace, though; for one thing, it has a cache line size
+ * assumption encoded into it. Why don't you just use the glibc memcpy?
+ * It's pretty well optimized these days, AFAIK.
+ *
+ * Paul.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ppc_asm.h"
+
+ .globl direct_ppcasm_memcpy
+direct_ppcasm_memcpy:
+ srwi. r7,r5,3
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
diff --git a/Source/DirectFB/lib/direct/ppcasm_memcpy.h b/Source/DirectFB/lib/direct/ppcasm_memcpy.h
new file mode 100755
index 0000000..4e7edaf
--- /dev/null
+++ b/Source/DirectFB/lib/direct/ppcasm_memcpy.h
@@ -0,0 +1,7 @@
+#ifndef __DIRECT__PPCASM_MEMCPY_H__
+#define __DIRECT__PPCASM_MEMCPY_H__
+
+void *direct_ppcasm_cacheable_memcpy( void *dest, const void *src, size_t n);
+void *direct_ppcasm_memcpy ( void *dest, const void *src, size_t n);
+
+#endif
diff --git a/Source/DirectFB/lib/direct/ppcasm_memcpy_cachable.S b/Source/DirectFB/lib/direct/ppcasm_memcpy_cachable.S
new file mode 100755
index 0000000..920dea2
--- /dev/null
+++ b/Source/DirectFB/lib/direct/ppcasm_memcpy_cachable.S
@@ -0,0 +1,180 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ *
+ * In a mail from Paul on 23.10.2006 05:47:
+ *
+ * You may put an LGPL permission statement on that code, replacing the
+ * GPL permission statement. From a technical point of view, I'm not
+ * sure that the code in ppcasm_memcpy_cachable.S is the best thing to
+ * use in userspace, though; for one thing, it has a cache line size
+ * assumption encoded into it. Why don't you just use the glibc memcpy?
+ * It's pretty well optimized these days, AFAIK.
+ *
+ * Paul.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#define __ASSEMBLY__
+
+#include <linux/config.h>
+
+#if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
+#define L1_CACHE_LINE_SIZE 16
+#define LG_L1_CACHE_LINE_SIZE 4
+#elif defined(CONFIG_PPC64BRIDGE)
+#define L1_CACHE_LINE_SIZE 128
+#define LG_L1_CACHE_LINE_SIZE 7
+#else
+#define L1_CACHE_LINE_SIZE 32
+#define LG_L1_CACHE_LINE_SIZE 5
+#endif
+
+#include "ppc_asm.h"
+
+#define COPY_16_BYTES \
+ lwz r7,4(r4); \
+ lwz r8,8(r4); \
+ lwz r9,12(r4); \
+ lwzu r10,16(r4); \
+ stw r7,4(r6); \
+ stw r8,8(r6); \
+ stw r9,12(r6); \
+ stwu r10,16(r6)
+
+#define COPY_16_BYTES_WITHEX(n) \
+8 ## n ## 0: \
+ lwz r7,4(r4); \
+8 ## n ## 1: \
+ lwz r8,8(r4); \
+8 ## n ## 2: \
+ lwz r9,12(r4); \
+8 ## n ## 3: \
+ lwzu r10,16(r4); \
+8 ## n ## 4: \
+ stw r7,4(r6); \
+8 ## n ## 5: \
+ stw r8,8(r6); \
+8 ## n ## 6: \
+ stw r9,12(r6); \
+8 ## n ## 7: \
+ stwu r10,16(r6)
+
+#define COPY_16_BYTES_EXCODE(n) \
+9 ## n ## 0: \
+ addi r5,r5,-(16 * n); \
+ b 104f; \
+9 ## n ## 1: \
+ addi r5,r5,-(16 * n); \
+ b 105f; \
+.section __ex_table,"a"; \
+ .align 2; \
+ .long 8 ## n ## 0b,9 ## n ## 0b; \
+ .long 8 ## n ## 1b,9 ## n ## 0b; \
+ .long 8 ## n ## 2b,9 ## n ## 0b; \
+ .long 8 ## n ## 3b,9 ## n ## 0b; \
+ .long 8 ## n ## 4b,9 ## n ## 1b; \
+ .long 8 ## n ## 5b,9 ## n ## 1b; \
+ .long 8 ## n ## 6b,9 ## n ## 1b; \
+ .long 8 ## n ## 7b,9 ## n ## 1b; \
+ .text
+
+ .text
+
+
+CACHELINE_MASK = (L1_CACHE_LINE_SIZE - 1)
+
+ .global direct_ppcasm_cacheable_memcpy
+direct_ppcasm_cacheable_memcpy:
+#if 0 /* this part causes "error loading shared library: unexpected reloc type
+ 0x0b (???) */
+ add r7,r3,r5 /* test if the src & dst overlap */
+ add r8,r4,r5
+ cmplw 0,r4,r7
+ cmplw 1,r3,r8
+ crand 0,0,4 /* cr0.lt &= cr1.lt */
+ blt ppcasm_memcpy /* if regions overlap */
+#endif
+ addi r4,r4,-4
+ addi r6,r3,-4
+ neg r0,r3
+ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
+ beq 58f
+
+ cmplw 0,r5,r0 /* is this more than total to do? */
+ blt 63f /* if not much to do */
+ andi. r8,r0,3 /* get it word-aligned first */
+ subf r5,r0,r5
+ mtctr r8
+ beq+ 61f
+70: lbz r9,4(r4) /* do some bytes */
+ stb r9,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 70b
+61: srwi. r0,r0,2
+ mtctr r0
+ beq 58f
+72: lwzu r9,4(r4) /* do some words */
+ stwu r9,4(r6)
+ bdnz 72b
+
+58: srwi. r0,r5,LG_L1_CACHE_LINE_SIZE /* complete cachelines */
+ clrlwi r5,r5,32-LG_L1_CACHE_LINE_SIZE
+ li r11,4
+ mtctr r0
+ beq 63f
+53:
+#if !defined(CONFIG_8xx)
+ dcbz r11,r6
+#endif
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+#endif
+#endif
+#endif
+ bdnz 53b
+
+63: srwi. r0,r5,2
+ mtctr r0
+ beq 64f
+30: lwzu r0,4(r4)
+ stwu r0,4(r6)
+ bdnz 30b
+
+64: andi. r0,r5,3
+ mtctr r0
+ beq+ 65f
+40: lbz r0,4(r4)
+ stb r0,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 40b
+65: blr
+
diff --git a/Source/DirectFB/lib/direct/serial.h b/Source/DirectFB/lib/direct/serial.h
new file mode 100755
index 0000000..d201708
--- /dev/null
+++ b/Source/DirectFB/lib/direct/serial.h
@@ -0,0 +1,118 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__SERIAL_H__
+#define __DIRECT__SERIAL_H__
+
+#include <direct/types.h>
+#include <direct/debug.h>
+
+struct __D_DirectSerial {
+ int magic;
+
+ u32 value;
+ u32 overflow;
+};
+
+static __inline__ void
+direct_serial_init( DirectSerial *serial )
+{
+ D_ASSERT( serial != NULL );
+
+ serial->value = 0;
+ serial->overflow = 0;
+
+ D_MAGIC_SET( serial, DirectSerial );
+}
+
+static __inline__ void
+direct_serial_deinit( DirectSerial *serial )
+{
+ D_MAGIC_CLEAR( serial );
+}
+
+static __inline__ void
+direct_serial_increase( DirectSerial *serial )
+{
+ D_MAGIC_ASSERT( serial, DirectSerial );
+
+ if (! ++serial->value)
+ serial->overflow++;
+}
+
+static __inline__ void
+direct_serial_copy( DirectSerial *serial, const DirectSerial *source )
+{
+ D_MAGIC_ASSERT( serial, DirectSerial );
+ D_MAGIC_ASSERT( source, DirectSerial );
+
+ serial->value = source->value;
+ serial->overflow = source->overflow;
+}
+
+static __inline__ bool
+direct_serial_check( DirectSerial *serial, const DirectSerial *source )
+{
+ D_MAGIC_ASSERT( serial, DirectSerial );
+ D_MAGIC_ASSERT( source, DirectSerial );
+
+ if (serial->overflow < source->overflow)
+ return false;
+ else if (serial->overflow == source->overflow && serial->value < source->value)
+ return false;
+
+ D_ASSUME( serial->value == source->value );
+
+ return true;
+}
+
+static __inline__ bool
+direct_serial_update( DirectSerial *serial, const DirectSerial *source )
+{
+ D_MAGIC_ASSERT( serial, DirectSerial );
+ D_MAGIC_ASSERT( source, DirectSerial );
+
+ if (serial->overflow < source->overflow) {
+ serial->overflow = source->overflow;
+ serial->value = source->value;
+
+ return true;
+ }
+ else if (serial->overflow == source->overflow && serial->value < source->value) {
+ serial->value = source->value;
+
+ return true;
+ }
+
+ D_ASSUME( serial->value == source->value );
+
+ return false;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/signals.c b/Source/DirectFB/lib/direct/signals.c
new file mode 100755
index 0000000..5b0310a
--- /dev/null
+++ b/Source/DirectFB/lib/direct/signals.c
@@ -0,0 +1,480 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <pthread.h>
+
+#include <signal.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <direct/clock.h>
+#include <direct/conf.h>
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/signals.h>
+#include <direct/system.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+D_DEBUG_DOMAIN( Direct_Signals, "Direct/Signals", "Signal handling" );
+
+
+struct __D_DirectSignalHandler {
+ DirectLink link;
+
+ int magic;
+
+ int num;
+ DirectSignalHandlerFunc func;
+ void *ctx;
+};
+
+/**************************************************************************************************/
+
+typedef struct {
+ int signum;
+ struct sigaction old_action;
+} SigHandled;
+
+static int sigs_to_handle[] = { /*SIGALRM,*/ SIGHUP, SIGINT, /*SIGPIPE,*/ /*SIGPOLL,*/
+ SIGTERM, /*SIGUSR1, SIGUSR2,*/ /*SIGVTALRM,*/
+ /*SIGSTKFLT,*/ SIGABRT, SIGFPE, SIGILL, SIGQUIT,
+ SIGSEGV, SIGTRAP, /*SIGSYS, SIGEMT,*/ SIGBUS,
+ SIGXCPU, SIGXFSZ };
+
+#define NUM_SIGS_TO_HANDLE ((int)D_ARRAY_SIZE( sigs_to_handle ))
+
+static SigHandled sigs_handled[NUM_SIGS_TO_HANDLE];
+
+static DirectLink *handlers = NULL;
+static pthread_mutex_t handlers_lock;
+
+/**************************************************************************************************/
+
+static void install_handlers( void );
+static void remove_handlers( void );
+
+/**************************************************************************************************/
+
+DirectResult
+direct_signals_initialize( void )
+{
+ D_DEBUG_AT( Direct_Signals, "Initializing...\n" );
+
+ direct_util_recursive_pthread_mutex_init( &handlers_lock );
+
+ install_handlers();
+
+ return DR_OK;
+}
+
+DirectResult
+direct_signals_shutdown( void )
+{
+ D_DEBUG_AT( Direct_Signals, "Shutting down...\n" );
+
+ remove_handlers();
+
+ pthread_mutex_destroy( &handlers_lock );
+
+ return DR_OK;
+}
+
+void
+direct_signals_block_all( void )
+{
+ sigset_t signals;
+
+ D_DEBUG_AT( Direct_Signals, "Blocking all signals from now on!\n" );
+
+ sigfillset( &signals );
+
+ if (pthread_sigmask( SIG_BLOCK, &signals, NULL ))
+ D_PERROR( "Direct/Signals: Setting signal mask failed!\n" );
+}
+
+DirectResult
+direct_signal_handler_add( int num,
+ DirectSignalHandlerFunc func,
+ void *ctx,
+ DirectSignalHandler **ret_handler )
+{
+ DirectSignalHandler *handler;
+
+ D_ASSERT( func != NULL );
+ D_ASSERT( ret_handler != NULL );
+
+ D_DEBUG_AT( Direct_Signals,
+ "Adding handler %p for signal %d with context %p...\n", func, num, ctx );
+
+ handler = D_CALLOC( 1, sizeof(DirectSignalHandler) );
+ if (!handler) {
+ D_WARN( "out of memory" );
+ return DR_NOLOCALMEMORY;
+ }
+
+ handler->num = num;
+ handler->func = func;
+ handler->ctx = ctx;
+
+ D_MAGIC_SET( handler, DirectSignalHandler );
+
+ pthread_mutex_lock( &handlers_lock );
+ direct_list_append( &handlers, &handler->link );
+ pthread_mutex_unlock( &handlers_lock );
+
+ *ret_handler = handler;
+
+ return DR_OK;
+}
+
+DirectResult
+direct_signal_handler_remove( DirectSignalHandler *handler )
+{
+ D_MAGIC_ASSERT( handler, DirectSignalHandler );
+
+ D_DEBUG_AT( Direct_Signals, "Removing handler %p for signal %d with context %p...\n",
+ handler->func, handler->num, handler->ctx );
+
+ pthread_mutex_lock( &handlers_lock );
+ direct_list_remove( &handlers, &handler->link );
+ pthread_mutex_unlock( &handlers_lock );
+
+ D_MAGIC_CLEAR( handler );
+
+ D_FREE( handler );
+
+ return DR_OK;
+}
+
+/**************************************************************************************************/
+
+static bool
+show_segv( const siginfo_t *info )
+{
+ switch (info->si_code) {
+#ifdef SEGV_MAPERR
+ case SEGV_MAPERR:
+ direct_log_printf( NULL, " (at %p, invalid address) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef SEGV_ACCERR
+ case SEGV_ACCERR:
+ direct_log_printf( NULL, " (at %p, invalid permissions) <--\n", info->si_addr );
+ return true;
+#endif
+ }
+ return false;
+}
+
+static bool
+show_bus( const siginfo_t *info )
+{
+ switch (info->si_code) {
+#ifdef BUG_ADRALN
+ case BUS_ADRALN:
+ direct_log_printf( NULL, " (at %p, invalid address alignment) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef BUS_ADRERR
+ case BUS_ADRERR:
+ direct_log_printf( NULL, " (at %p, non-existent physical address) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef BUS_OBJERR
+ case BUS_OBJERR:
+ direct_log_printf( NULL, " (at %p, object specific hardware error) <--\n", info->si_addr );
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+static bool
+show_ill( const siginfo_t *info )
+{
+ switch (info->si_code) {
+#ifdef ILL_ILLOPC
+ case ILL_ILLOPC:
+ direct_log_printf( NULL, " (at %p, illegal opcode) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_ILLOPN
+ case ILL_ILLOPN:
+ direct_log_printf( NULL, " (at %p, illegal operand) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_ILLADR
+ case ILL_ILLADR:
+ direct_log_printf( NULL, " (at %p, illegal addressing mode) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_ILLTRP
+ case ILL_ILLTRP:
+ direct_log_printf( NULL, " (at %p, illegal trap) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_PRVOPC
+ case ILL_PRVOPC:
+ direct_log_printf( NULL, " (at %p, privileged opcode) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_PRVREG
+ case ILL_PRVREG:
+ direct_log_printf( NULL, " (at %p, privileged register) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_COPROC
+ case ILL_COPROC:
+ direct_log_printf( NULL, " (at %p, coprocessor error) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef ILL_BADSTK
+ case ILL_BADSTK:
+ direct_log_printf( NULL, " (at %p, internal stack error) <--\n", info->si_addr );
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+static bool
+show_fpe( const siginfo_t *info )
+{
+ switch (info->si_code) {
+#ifdef FPE_INTDIV
+ case FPE_INTDIV:
+ direct_log_printf( NULL, " (at %p, integer divide by zero) <--\n", info->si_addr );
+ return true;
+#endif
+#ifdef FPE_FLTDIV
+ case FPE_FLTDIV:
+ direct_log_printf( NULL, " (at %p, floating point divide by zero) <--\n", info->si_addr );
+ return true;
+#endif
+ }
+
+ direct_log_printf( NULL, " (at %p) <--\n", info->si_addr );
+
+ return true;
+}
+
+static bool
+show_any( const siginfo_t *info )
+{
+ switch (info->si_code) {
+#ifdef SI_USER
+ case SI_USER:
+ direct_log_printf( NULL, " (sent by pid %d, uid %d) <--\n", info->si_pid, info->si_uid );
+ return true;
+#endif
+#ifdef SI_KERNEL
+ case SI_KERNEL:
+ direct_log_printf( NULL, " (sent by the kernel) <--\n" );
+ return true;
+#endif
+ }
+ return false;
+}
+
+static void
+#ifdef SA_SIGINFO
+signal_handler( int num, siginfo_t *info, void *foo )
+#else
+signal_handler( int num )
+#endif
+{
+ DirectLink *l, *n;
+ void *addr = NULL;
+ int pid = direct_gettid();
+ long long millis = direct_clock_get_millis();
+
+ fflush(stdout);
+ fflush(stderr);
+
+ direct_log_printf( NULL, "(!) [%5d: %4lld.%03lld] --> Caught signal %d",
+ pid, millis/1000, millis%1000, num );
+
+#ifdef SA_SIGINFO
+ if (info && info > (siginfo_t*) 0x100) {
+ bool shown = false;
+
+ if (info->si_code > 0 && info->si_code < 0x80) {
+ addr = info->si_addr;
+
+ switch (num) {
+ case SIGSEGV:
+ shown = show_segv( info );
+ break;
+
+ case SIGBUS:
+ shown = show_bus( info );
+ break;
+
+ case SIGILL:
+ shown = show_ill( info );
+ break;
+
+ case SIGFPE:
+ shown = show_fpe( info );
+ break;
+
+ default:
+ direct_log_printf( NULL, " <--\n" );
+ addr = NULL;
+ shown = true;
+ break;
+ }
+ }
+ else
+ shown = show_any( info );
+
+ if (!shown)
+ direct_log_printf( NULL, " (unknown origin) <--\n" );
+ }
+ else
+#endif
+ direct_log_printf( NULL, ", no siginfo available <--\n" );
+
+ direct_trace_print_stacks();
+
+ /* Loop through all handlers. */
+ pthread_mutex_lock( &handlers_lock );
+
+ direct_list_foreach_safe (l, n, handlers) {
+ DirectSignalHandler *handler = (DirectSignalHandler*) l;
+
+ if (handler->num != num && handler->num != DIRECT_SIGNAL_ANY)
+ continue;
+
+ switch (handler->func( num, addr, handler->ctx )) {
+ case DSHR_OK:
+ break;
+
+ case DSHR_REMOVE:
+ direct_list_remove( &handlers, &handler->link );
+ D_MAGIC_CLEAR( handler );
+ D_FREE( handler );
+ break;
+
+ case DSHR_RESUME:
+ millis = direct_clock_get_millis();
+
+ direct_log_printf( NULL, "(!) [%5d: %4lld.%03lld] -> cured!\n",
+ pid, millis / 1000, millis % 1000 );
+ pthread_mutex_unlock( &handlers_lock );
+ return;
+
+ default:
+ D_BUG( "unknown result" );
+ break;
+ }
+ }
+
+ pthread_mutex_unlock( &handlers_lock );
+
+
+// sleep(100);
+
+
+ remove_handlers();
+
+ raise( num );
+
+ abort();
+
+ exit( -num );
+}
+
+/**************************************************************************************************/
+
+static void
+install_handlers( void )
+{
+ int i;
+
+ for (i=0; i<NUM_SIGS_TO_HANDLE; i++) {
+ sigs_handled[i].signum = -1;
+
+ if (direct_config->sighandler && !sigismember( &direct_config->dont_catch,
+ sigs_to_handle[i] ))
+ {
+ struct sigaction action;
+ int signum = sigs_to_handle[i];
+
+#ifdef SA_SIGINFO
+ action.sa_sigaction = signal_handler;
+ action.sa_flags = SA_SIGINFO;
+#else
+ action.sa_handler = signal_handler;
+ action.sa_flags = 0;
+#endif
+
+ if (signum != SIGSEGV)
+ action.sa_flags |= SA_NODEFER;
+
+ sigemptyset( &action.sa_mask );
+
+ if (sigaction( signum, &action, &sigs_handled[i].old_action )) {
+ D_PERROR( "Direct/Signals: "
+ "Unable to install signal handler for signal %d!\n", signum );
+ continue;
+ }
+
+ sigs_handled[i].signum = signum;
+ }
+ }
+}
+
+static void
+remove_handlers( void )
+{
+ int i;
+
+ for (i=0; i<NUM_SIGS_TO_HANDLE; i++) {
+ if (sigs_handled[i].signum != -1) {
+ int signum = sigs_handled[i].signum;
+
+ if (sigaction( signum, &sigs_handled[i].old_action, NULL )) {
+ D_PERROR( "Direct/Signals: "
+ "Unable to restore previous handler for signal %d!\n", signum );
+ }
+
+ sigs_handled[i].signum = -1;
+ }
+ }
+}
+
diff --git a/Source/DirectFB/lib/direct/signals.h b/Source/DirectFB/lib/direct/signals.h
new file mode 100755
index 0000000..8765fe1
--- /dev/null
+++ b/Source/DirectFB/lib/direct/signals.h
@@ -0,0 +1,70 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__SIGNALS_H__
+#define __DIRECT__SIGNALS_H__
+
+#include <direct/types.h>
+
+
+typedef enum {
+ DSHR_OK,
+ DSHR_REMOVE,
+ DSHR_RESUME
+} DirectSignalHandlerResult;
+
+typedef DirectSignalHandlerResult (*DirectSignalHandlerFunc)( int num,
+ void *addr,
+ void *ctx );
+
+
+DirectResult direct_signals_initialize( void );
+DirectResult direct_signals_shutdown( void );
+
+/*
+ * Modifies the current thread's signal mask to block everything.
+ * Should be called by input threads once to avoid killing themselves
+ * in the signal handler by deinitializing all input drivers.
+ */
+void direct_signals_block_all( void );
+
+/*
+ * Signal number to use when registering a handler for any interrupt.
+ */
+#define DIRECT_SIGNAL_ANY -1
+
+
+DirectResult direct_signal_handler_add ( int num,
+ DirectSignalHandlerFunc func,
+ void *ctx,
+ DirectSignalHandler **ret_handler );
+
+DirectResult direct_signal_handler_remove( DirectSignalHandler *handler );
+
+
+#endif
diff --git a/Source/DirectFB/lib/direct/stream.c b/Source/DirectFB/lib/direct/stream.c
new file mode 100755
index 0000000..1e531d9
--- /dev/null
+++ b/Source/DirectFB/lib/direct/stream.c
@@ -0,0 +1,2286 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <direct/build.h>
+#include <direct/types.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/debug.h>
+#include <direct/util.h>
+
+#include <direct/stream.h>
+
+
+struct __D_DirectStream {
+ int magic;
+ int ref;
+
+ int fd;
+ unsigned int offset;
+ int length;
+
+ char *mime;
+
+ /* cache for piped streams */
+ void *cache;
+ unsigned int cache_size;
+
+#if DIRECT_BUILD_NETWORK
+ /* remote streams data */
+ struct {
+ int sd;
+
+ char *host;
+ int port;
+ struct addrinfo *addr;
+
+ char *user;
+ char *pass;
+ char *auth;
+
+ char *path;
+
+ int redirects;
+
+ void *data;
+
+ bool real_rtsp;
+ bool real_pack;
+ } remote;
+#endif
+
+ DirectResult (*wait) ( DirectStream *stream,
+ unsigned int length,
+ struct timeval *tv );
+ DirectResult (*peek) ( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out );
+ DirectResult (*read) ( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out );
+ DirectResult (*seek) ( DirectStream *stream,
+ unsigned int offset );
+};
+
+
+static void direct_stream_close( DirectStream *stream );
+
+
+#if DIRECT_BUILD_NETWORK
+D_DEBUG_DOMAIN( Direct_Stream, "Direct/Stream", "Stream wrapper" );
+#endif
+
+/************************** Begin Network Support ***************************/
+
+#if DIRECT_BUILD_NETWORK
+
+#define NET_TIMEOUT 15
+#define HTTP_PORT 80
+#define FTP_PORT 21
+#define RTSP_PORT 554
+#define HTTP_MAX_REDIRECTS 15
+
+static DirectResult http_open( DirectStream *stream, const char *filename );
+static DirectResult ftp_open ( DirectStream *stream, const char *filename );
+static DirectResult rtsp_open( DirectStream *stream, const char *filename );
+
+
+static inline char* trim( char *s )
+{
+ char *e;
+
+#define space( c ) ((c) == ' ' || (c) == '\t' || \
+ (c) == '\r' || (c) == '\n' || \
+ (c) == '"' || (c) == '\'')
+
+ for (; space(*s); s++);
+
+ e = s + strlen(s) - 1;
+ for (; e > s && space(*e); *e-- = '\0');
+
+#undef space
+
+ return s;
+}
+
+static void
+parse_url( const char *url, char **ret_host, int *ret_port,
+ char **ret_user, char **ret_pass, char **ret_path )
+{
+ char *host = NULL;
+ int port = 0;
+ char *user = NULL;
+ char *pass = NULL;
+ char *path;
+ char *tmp;
+
+ tmp = strchr( url, '/' );
+ if (tmp) {
+ host = alloca( tmp - url + 1 );
+ memcpy( host, url, tmp - url );
+ host[tmp-url] = '\0';
+ path = tmp;
+ } else {
+ host = alloca( strlen( url ) + 1 );
+ memcpy( host, url, strlen( url ) + 1 );
+ path = "/";
+ }
+
+ tmp = strrchr( host, '@' );
+ if (tmp) {
+ *tmp = '\0';
+ pass = strchr( host, ':' );
+ if (pass) {
+ *pass = '\0';
+ pass++;
+ }
+ user = host;
+ host = tmp + 1;
+ }
+
+ tmp = strchr( host, ':' );
+ if (tmp) {
+ port = strtol( tmp+1, NULL, 10 );
+ *tmp = '\0';
+ }
+
+ /* IPv6 variant (host within brackets) */
+ if (*host == '[') {
+ host++;
+ tmp = strchr( host, ']' );
+ if (tmp)
+ *tmp = '\0';
+ }
+
+ if (ret_host)
+ *ret_host = D_STRDUP( host );
+
+ if (ret_port && port)
+ *ret_port = port;
+
+ if (ret_user && user)
+ *ret_user = D_STRDUP( user );
+
+ if (ret_pass && pass)
+ *ret_pass = D_STRDUP( pass );
+
+ if (ret_path)
+ *ret_path = D_STRDUP( path );
+}
+
+/*****************************************************************************/
+
+static int
+net_response( DirectStream *stream, char *buf, size_t size )
+{
+ fd_set set;
+ struct timeval tv;
+ int i;
+
+ FD_ZERO( &set );
+ FD_SET( stream->remote.sd, &set );
+
+ for (i = 0; i < size-1; i++) {
+ tv.tv_sec = NET_TIMEOUT;
+ tv.tv_usec = 0;
+ select( stream->remote.sd+1, &set, NULL, NULL, &tv );
+
+ if (recv( stream->remote.sd, buf+i, 1, 0 ) != 1)
+ break;
+
+ if (buf[i] == '\n') {
+ if (i > 0 && buf[i-1] == '\r')
+ i--;
+ break;
+ }
+ }
+
+ buf[i] = '\0';
+
+ D_DEBUG_AT( Direct_Stream, "got [%s].\n", buf );
+
+ return i;
+}
+
+static int
+net_command( DirectStream *stream, char *buf, size_t size )
+{
+ fd_set s;
+ struct timeval t;
+ int status;
+ int version;
+ char space;
+
+ FD_ZERO( &s );
+ FD_SET( stream->remote.sd, &s );
+
+ t.tv_sec = NET_TIMEOUT;
+ t.tv_usec = 0;
+
+ switch (select( stream->remote.sd+1, NULL, &s, NULL, &t )) {
+ case 0:
+ D_DEBUG_AT( Direct_Stream, "Timeout!\n" );
+ case -1:
+ return -1;
+ }
+
+ send( stream->remote.sd, buf, strlen(buf), 0 );
+ send( stream->remote.sd, "\r\n", 2, 0 );
+
+ D_DEBUG_AT( Direct_Stream, "sent [%s].\n", buf );
+
+ while (net_response( stream, buf, size ) > 0) {
+ status = 0;
+ if (sscanf( buf, "HTTP/1.%d %3d", &version, &status ) == 2 ||
+ sscanf( buf, "RTSP/1.%d %3d", &version, &status ) == 2 ||
+ sscanf( buf, "ICY %3d", &status ) == 1 ||
+ sscanf( buf, "%3d%[ ]", &status, &space ) == 2)
+ return status;
+ }
+
+ return 0;
+}
+
+static DirectResult
+net_wait( DirectStream *stream,
+ unsigned int length,
+ struct timeval *tv )
+{
+ fd_set s;
+
+ if (stream->cache_size >= length)
+ return DR_OK;
+
+ if (stream->fd == -1)
+ return DR_EOF;
+
+ FD_ZERO( &s );
+ FD_SET( stream->fd, &s );
+
+ switch (select( stream->fd+1, &s, NULL, NULL, tv )) {
+ case 0:
+ if (!tv && !stream->cache_size)
+ return DR_EOF;
+ return DR_TIMEOUT;
+ case -1:
+ return errno2result( errno );
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+net_peek( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out )
+{
+ char *tmp;
+ int size;
+
+ if (offset < 0)
+ return DR_UNSUPPORTED;
+
+ tmp = alloca( length + offset );
+
+ size = recv( stream->fd, tmp, length+offset, MSG_PEEK );
+ switch (size) {
+ case 0:
+ return DR_EOF;
+ case -1:
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return DR_BUFFEREMPTY;
+ return errno2result( errno );
+ default:
+ if (size < offset)
+ return DR_BUFFEREMPTY;
+ size -= offset;
+ break;
+ }
+
+ direct_memcpy( buf, tmp+offset, size );
+
+ if (read_out)
+ *read_out = size;
+
+ return DR_OK;
+}
+
+static DirectResult
+net_read( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out )
+{
+ int size;
+
+ size = recv( stream->fd, buf, length, 0 );
+ switch (size) {
+ case 0:
+ return DR_EOF;
+ case -1:
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return DR_BUFFEREMPTY;
+ return errno2result( errno );
+ }
+
+ stream->offset += size;
+
+ if (read_out)
+ *read_out = size;
+
+ return DR_OK;
+}
+
+static DirectResult
+net_connect( struct addrinfo *addr, int sock, int proto, int *ret_fd )
+{
+ DirectResult ret = DR_OK;
+ int fd = -1;
+ struct addrinfo *tmp;
+
+ D_ASSERT( addr != NULL );
+ D_ASSERT( ret_fd != NULL );
+
+ for (tmp = addr; tmp; tmp = tmp->ai_next) {
+ int err;
+
+ fd = socket( tmp->ai_family, sock, proto );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_DEBUG_AT( Direct_Stream,
+ "failed to create socket!\n\t->%s",
+ strerror(errno) );
+ continue;
+ }
+
+ fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK );
+
+ D_DEBUG_AT( Direct_Stream,
+ "connecting to %s...\n", tmp->ai_canonname );
+
+ if (proto == IPPROTO_UDP)
+ err = bind( fd, tmp->ai_addr, tmp->ai_addrlen );
+ else
+ err = connect( fd, tmp->ai_addr, tmp->ai_addrlen );
+
+ if (err == 0 || errno == EINPROGRESS) {
+ struct timeval t = { NET_TIMEOUT, 0 };
+ fd_set s;
+
+ /* Join multicast group? */
+ if (tmp->ai_addr->sa_family == AF_INET) {
+ struct sockaddr_in *saddr = (struct sockaddr_in *) tmp->ai_addr;
+
+ if (IN_MULTICAST( ntohl(saddr->sin_addr.s_addr) )) {
+ struct ip_mreq req;
+
+ D_DEBUG_AT( Direct_Stream,
+ "joining multicast group (%u.%u.%u.%u)...\n",
+ (u8)tmp->ai_addr->sa_data[2], (u8)tmp->ai_addr->sa_data[3],
+ (u8)tmp->ai_addr->sa_data[4], (u8)tmp->ai_addr->sa_data[5] );
+
+ req.imr_multiaddr.s_addr = saddr->sin_addr.s_addr;
+ req.imr_interface.s_addr = 0;
+
+ err = setsockopt( fd, SOL_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req) );
+ if (err < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Direct/Stream: Could not join multicast group (%u.%u.%u.%u)!\n",
+ (u8)tmp->ai_addr->sa_data[2], (u8)tmp->ai_addr->sa_data[3],
+ (u8)tmp->ai_addr->sa_data[4], (u8)tmp->ai_addr->sa_data[5] );
+ close( fd );
+ continue;
+ }
+
+ setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, saddr, sizeof(*saddr) );
+ }
+ }
+
+ FD_ZERO( &s );
+ FD_SET( fd, &s );
+
+ err = select( fd+1, NULL, &s, NULL, &t );
+ if (err < 1) {
+ D_DEBUG_AT( Direct_Stream, "...connection failed.\n" );
+
+ close( fd );
+ fd = -1;
+
+ if (err == 0) {
+ ret = DR_TIMEOUT;
+ continue;
+ } else {
+ ret = errno2result( errno );
+ break;
+ }
+ }
+
+ D_DEBUG_AT( Direct_Stream, "...connected.\n" );
+
+ ret = DR_OK;
+ break;
+ }
+ }
+
+ *ret_fd = fd;
+
+ return ret;
+}
+
+static DirectResult
+net_open( DirectStream *stream, const char *filename, int proto )
+{
+ DirectResult ret = DR_OK;
+ int sock = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
+ struct addrinfo hints;
+ char port[16];
+
+ parse_url( filename,
+ &stream->remote.host,
+ &stream->remote.port,
+ &stream->remote.user,
+ &stream->remote.pass,
+ &stream->remote.path );
+
+ snprintf( port, sizeof(port), "%d", stream->remote.port );
+
+ memset( &hints, 0, sizeof(hints) );
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = sock;
+ hints.ai_family = PF_UNSPEC;
+
+ if (getaddrinfo( stream->remote.host, port,
+ &hints, &stream->remote.addr )) {
+ D_ERROR( "Direct/Stream: "
+ "failed to resolve host '%s'!\n", stream->remote.host );
+ return DR_FAILURE;
+ }
+
+ ret = net_connect( stream->remote.addr, sock, proto, &stream->remote.sd );
+ if (ret)
+ return ret;
+
+ stream->fd = stream->remote.sd;
+ stream->length = -1;
+ stream->wait = net_wait;
+ stream->peek = net_peek;
+ stream->read = net_read;
+
+ return ret;
+}
+
+/*****************************************************************************/
+
+static DirectResult
+http_seek( DirectStream *stream, unsigned int offset )
+{
+ DirectResult ret;
+ char buf[1280];
+ int status, len;
+
+ close( stream->remote.sd );
+ stream->remote.sd = -1;
+
+ ret = net_connect( stream->remote.addr,
+ SOCK_STREAM, IPPROTO_TCP, &stream->remote.sd );
+ if (ret)
+ return ret;
+
+ stream->fd = stream->remote.sd;
+
+ len = snprintf( buf, sizeof(buf),
+ "GET %s HTTP/1.0\r\n"
+ "Host: %s:%d\r\n",
+ stream->remote.path,
+ stream->remote.host,
+ stream->remote.port );
+ if (stream->remote.auth) {
+ len += snprintf( buf+len, sizeof(buf)-len,
+ "Authorization: Basic %s\r\n",
+ stream->remote.auth );
+ }
+ snprintf( buf+len, sizeof(buf)-len,
+ "User-Agent: DirectFB/%s\r\n"
+ "Accept: */*\r\n"
+ "Range: bytes=%d-\r\n"
+ "Connection: Close\r\n",
+ DIRECTFB_VERSION, offset );
+
+ status = net_command( stream, buf, sizeof(buf) );
+ switch (status) {
+ case 200 ... 299:
+ stream->offset = offset;
+ break;
+ default:
+ if (status)
+ D_DEBUG_AT( Direct_Stream,
+ "server returned status %d.\n", status );
+ return DR_FAILURE;
+ }
+
+ /* discard remaining headers */
+ while (net_response( stream, buf, sizeof(buf) ) > 0);
+
+ return DR_OK;
+}
+
+static DirectResult
+http_open( DirectStream *stream, const char *filename )
+{
+ DirectResult ret;
+ char buf[1280];
+ int status, len;
+
+ stream->remote.port = HTTP_PORT;
+
+ ret = net_open( stream, filename, IPPROTO_TCP );
+ if (ret)
+ return ret;
+
+ if (stream->remote.user) {
+ char *tmp;
+
+ if (stream->remote.pass) {
+ tmp = alloca( strlen( stream->remote.user ) +
+ strlen( stream->remote.pass ) + 2 );
+ len = sprintf( tmp, "%s:%s",
+ stream->remote.user, stream->remote.pass );
+ } else {
+ tmp = alloca( strlen( stream->remote.user ) + 2 );
+ len = sprintf( tmp, "%s:", stream->remote.user );
+ }
+
+ stream->remote.auth = direct_base64_encode( tmp, len );
+ }
+
+ len = snprintf( buf, sizeof(buf),
+ "GET %s HTTP/1.0\r\n"
+ "Host: %s:%d\r\n",
+ stream->remote.path,
+ stream->remote.host,
+ stream->remote.port );
+ if (stream->remote.auth) {
+ len += snprintf( buf+len, sizeof(buf)-len,
+ "Authorization: Basic %s\r\n",
+ stream->remote.auth );
+ }
+ snprintf( buf+len, sizeof(buf)-len,
+ "User-Agent: DirectFB/%s\r\n"
+ "Accept: */*\r\n"
+ "Connection: Close\r\n",
+ DIRECTFB_VERSION );
+
+ status = net_command( stream, buf, sizeof(buf) );
+
+ while (net_response( stream, buf, sizeof(buf) ) > 0) {
+ if (!strncasecmp( buf, "Accept-Ranges:", 14 )) {
+ if (strcmp( trim( buf+14 ), "none" ))
+ stream->seek = http_seek;
+ }
+ else if (!strncasecmp( buf, "Content-Type:", 13 )) {
+ char *mime = trim( buf+13 );
+ char *tmp = strchr( mime, ';' );
+ if (tmp)
+ *tmp = '\0';
+ if (stream->mime)
+ D_FREE( stream->mime );
+ stream->mime = D_STRDUP( mime );
+ }
+ else if (!strncasecmp( buf, "Content-Length:", 15 )) {
+ char *tmp = trim( buf+15 );
+ if (sscanf( tmp, "%d", &stream->length ) < 1)
+ sscanf( tmp, "bytes=%d", &stream->length );
+ }
+ else if (!strncasecmp( buf, "Location:", 9 )) {
+ direct_stream_close( stream );
+ stream->seek = NULL;
+
+ if (++stream->remote.redirects > HTTP_MAX_REDIRECTS) {
+ D_ERROR( "Direct/Stream: "
+ "reached maximum number of redirects (%d).\n",
+ HTTP_MAX_REDIRECTS );
+ return DR_LIMITEXCEEDED;
+ }
+
+ filename = trim( buf+9 );
+ if (!strncmp( filename, "http://", 7 ))
+ return http_open( stream, filename+7 );
+ if (!strncmp( filename, "ftp://", 6 ))
+ return ftp_open( stream, filename+6 );
+ if (!strncmp( filename, "rtsp://", 7 ))
+ return rtsp_open( stream, filename+7 );
+
+ return DR_UNSUPPORTED;
+ }
+ }
+
+ switch (status) {
+ case 200 ... 299:
+ break;
+ default:
+ if (status)
+ D_DEBUG_AT( Direct_Stream,
+ "server returned status %d.\n", status );
+ return (status == 404) ? DR_FILENOTFOUND : DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+/*****************************************************************************/
+
+static DirectResult
+ftp_open_pasv( DirectStream *stream, char *buf, size_t size )
+{
+ DirectResult ret;
+ int i, len;
+
+ snprintf( buf, size, "PASV" );
+ if (net_command( stream, buf, size ) != 227)
+ return DR_FAILURE;
+
+ /* parse IP and port for passive mode */
+ for (i = 4; buf[i]; i++) {
+ unsigned int d[6];
+
+ if (sscanf( &buf[i], "%u,%u,%u,%u,%u,%u",
+ &d[0], &d[1], &d[2], &d[3], &d[4], &d[5] ) == 6)
+ {
+ struct addrinfo hints, *addr;
+
+ /* address */
+ len = snprintf( buf, size,
+ "%u.%u.%u.%u",
+ d[0], d[1], d[2], d[3] );
+ /* port */
+ snprintf( buf+len+1, size-len-1,
+ "%u", ((d[4] & 0xff) << 8) | (d[5] & 0xff) );
+
+ memset( &hints, 0, sizeof(hints) );
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+
+ if (getaddrinfo( buf, buf+len+1, &hints, &addr )) {
+ D_DEBUG_AT( Direct_Stream,
+ "failed to resolve host '%s'.\n", buf );
+ return DR_FAILURE;
+ }
+
+ ret = net_connect( addr, SOCK_STREAM, IPPROTO_TCP, &stream->fd );
+
+ freeaddrinfo( addr );
+
+ return ret;
+ }
+ }
+
+ return DR_FAILURE;
+}
+
+static DirectResult
+ftp_seek( DirectStream *stream, unsigned int offset )
+{
+ DirectResult ret = DR_OK;
+ char buf[512];
+
+ if (stream->fd > 0) {
+ int status;
+
+ close( stream->fd );
+ stream->fd = -1;
+
+ /* ignore response */
+ while (net_response( stream, buf, sizeof(buf) ) > 0) {
+ if (sscanf( buf, "%3d%[ ]", &status, buf ) == 2)
+ break;
+ }
+ }
+
+ ret = ftp_open_pasv( stream, buf, sizeof(buf) );
+ if (ret)
+ return ret;
+
+ snprintf( buf, sizeof(buf), "REST %d", offset );
+ if (net_command( stream, buf, sizeof(buf) ) != 350)
+ goto error;
+
+ snprintf( buf, sizeof(buf), "RETR %s", stream->remote.path );
+ switch (net_command( stream, buf, sizeof(buf) )) {
+ case 150:
+ case 125:
+ break;
+ default:
+ goto error;
+ }
+
+ stream->offset = offset;
+
+ return DR_OK;
+
+error:
+ close( stream->fd );
+ stream->fd = -1;
+
+ return DR_FAILURE;
+}
+
+static DirectResult
+ftp_open( DirectStream *stream, const char *filename )
+{
+ DirectResult ret;
+ int status = 0;
+ char buf[512];
+
+ stream->remote.port = FTP_PORT;
+
+ ret = net_open( stream, filename, IPPROTO_TCP );
+ if (ret)
+ return ret;
+
+ while (net_response( stream, buf, sizeof(buf) ) > 0) {
+ if (sscanf( buf, "%3d%[ ]", &status, buf ) == 2)
+ break;
+ }
+ if (status != 220)
+ return DR_FAILURE;
+
+ /* login */
+ snprintf( buf, sizeof(buf), "USER %s", stream->remote.user ? : "anonymous" );
+ switch (net_command( stream, buf, sizeof(buf) )) {
+ case 230:
+ case 331:
+ break;
+ default:
+ return DR_FAILURE;
+ }
+
+ if (stream->remote.pass) {
+ snprintf( buf, sizeof(buf), "PASS %s", stream->remote.pass );
+ if (net_command( stream, buf, sizeof(buf) ) != 230)
+ return DR_FAILURE;
+ }
+
+ /* enter binary mode */
+ snprintf( buf, sizeof(buf), "TYPE I" );
+ if (net_command( stream, buf, sizeof(buf) ) != 200)
+ return DR_FAILURE;
+
+ /* get file size */
+ snprintf( buf, sizeof(buf), "SIZE %s", stream->remote.path );
+ if (net_command( stream, buf, sizeof(buf) ) == 213)
+ stream->length = strtol( buf+4, NULL, 10 );
+
+ /* enter passive mode by default */
+ ret = ftp_open_pasv( stream, buf, sizeof(buf) );
+ if (ret)
+ return ret;
+
+ /* retrieve file */
+ snprintf( buf, sizeof(buf), "RETR %s", stream->remote.path );
+ switch (net_command( stream, buf, sizeof(buf) )) {
+ case 125:
+ case 150:
+ break;
+ default:
+ return DR_FAILURE;
+ }
+
+ stream->seek = ftp_seek;
+
+ return DR_OK;
+}
+
+/*****************************************************************************/
+
+typedef struct {
+ s8 pt; // payload type (-1: dymanic)
+ u8 type; // codec type
+ const char *name;
+ const char *mime;
+ u32 fcc;
+} RTPPayload;
+
+typedef struct {
+ char *control;
+
+ int pt;
+ const RTPPayload *payload;
+
+ int dur; // duration
+ int abr; // avg bitrate
+ int mbr; // max bitrate
+ int aps; // avg packet size
+ int mps; // max packet size
+ int str; // start time
+ int prl; // preroll
+
+ char *mime;
+ int mime_size;
+
+ void *data;
+ int data_size;
+} SDPStreamDesc;
+
+#define PAYLOAD_VIDEO 1
+#define PAYLOAD_AUDIO 2
+
+#define FCC( a, b, c, d ) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
+
+static const RTPPayload payloads[] = {
+ { 31, PAYLOAD_VIDEO, "H261", "video/h261", FCC('H','2','6','1') },
+ { 34, PAYLOAD_VIDEO, "H263", "video/h263", FCC('H','2','6','3') },
+ //{ -1, PAYLOAD_VIDEO, "H264", "video/h264", FCC('H','2','6','4') },
+ { 32, PAYLOAD_VIDEO, "MPV", "video/mpeg", FCC('M','P','E','G') },
+ { 33, 0, "MP2T", "video/mpegts", 0 },
+ { -1, PAYLOAD_VIDEO, "MP4V-ES", "video/mpeg4", FCC('M','P','4','S') },
+ { 14, PAYLOAD_AUDIO, "MPA", "audio/mpeg", 0x0055 },
+ //{ -1, PAYLOAD_AUDIO, "mpeg4-generic", "audio/aac", 0x00ff },
+};
+
+#define NUM_PAYLOADS D_ARRAY_SIZE( payloads )
+
+static DirectResult
+sdp_parse( DirectStream *stream, int length, SDPStreamDesc **ret_streams, int *ret_num )
+{
+ char *buf, *tmp;
+ SDPStreamDesc *desc = NULL;
+ int num = 0;
+ fd_set set;
+ struct timeval tv;
+ int i;
+
+ buf = D_CALLOC( 1, length+1 );
+ if (!buf)
+ return D_OOM();
+
+ FD_ZERO( &set );
+ FD_SET( stream->remote.sd, &set );
+
+ for (tmp = buf; length;) {
+ int size;
+
+ tv.tv_sec = NET_TIMEOUT;
+ tv.tv_usec = 0;
+ select( stream->remote.sd+1, &set, NULL, NULL, &tv );
+
+ size = recv( stream->remote.sd, tmp, length, MSG_WAITALL );
+ if (size < 1)
+ break;
+ tmp += size;
+ length -= size;
+ }
+
+ for (tmp = buf; tmp && *tmp;) {
+ char *end;
+
+ end = strchr( tmp, '\n' );
+ if (end) {
+ if (end > tmp && *(end-1) == '\r')
+ *(end-1) = '\0';
+ *end = '\0';
+ }
+
+ D_DEBUG_AT( Direct_Stream, "SDP [%s]\n", tmp );
+
+ switch (*tmp) {
+ case 'm':
+ /* media */
+ if (*(tmp+1) == '=') {
+ desc = D_REALLOC( desc, ++num*sizeof(SDPStreamDesc) );
+ memset( &desc[num-1], 0, sizeof(SDPStreamDesc) );
+
+ tmp += 2;
+ if (sscanf( tmp, "audio %d RTP/AVP %d", &i, &desc[num-1].pt ) == 2 ||
+ sscanf( tmp, "video %d RTP/AVP %d", &i, &desc[num-1].pt ) == 2) {
+ for (i = 0; i < NUM_PAYLOADS; i++) {
+ if (desc[num-1].pt == payloads[i].pt) {
+ desc[num-1].payload = &payloads[i];
+ desc[num-1].mime = D_STRDUP( payloads[i].mime );
+ desc[num-1].mime_size = strlen( payloads[i].mime );
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case 'a':
+ /* attribute */
+ if (*(tmp+1) == '=' && num) {
+ tmp += 2;
+ if (!strncmp( tmp, "control:", 8 )) {
+ desc[num-1].control = D_STRDUP( trim( tmp+8 ) );
+ }
+ else if (!strncmp( tmp, "rtpmap:", 7 )) {
+ if (!desc[num-1].payload && desc[num-1].pt) {
+ char *sep;
+
+ tmp = strchr( trim( tmp+7 ), ' ' );
+ if (!tmp) break;
+ sep = strchr( ++tmp, '/' );
+ if (sep) *sep = '\0';
+
+ for (i = 0; i < NUM_PAYLOADS; i++) {
+ if (strcmp( tmp, payloads[i].name ))
+ continue;
+ desc[num-1].payload = &payloads[i];
+ desc[num-1].mime = D_STRDUP( payloads[i].mime );
+ desc[num-1].mime_size = strlen( payloads[i].mime );
+ break;
+ }
+ }
+ }
+ else if (!strncmp( tmp, "length:npt=", 11 )) {
+ double val = atof( tmp+11 );
+ desc[num-1].dur = val * 1000.0;
+ }
+ else if (!strncmp( tmp, "mimetype:string;", 16 )) {
+ if (desc[num-1].mime)
+ D_FREE( desc[num-1].mime );
+ desc[num-1].mime = D_STRDUP( trim( tmp+16 ) );
+ desc[num-1].mime_size = strlen( desc[num-1].mime );
+ }
+ else if (!strncmp( tmp, "AvgBitRate:", 11 )) {
+ sscanf( tmp+11, "integer;%d", &desc[num-1].abr );
+ }
+ else if (!strncmp( tmp, "MaxBitRate:", 11 )) {
+ sscanf( tmp+11, "integer;%d", &desc[num-1].mbr );
+ }
+ else if (!strncmp( tmp, "AvgPacketSize:", 14 )) {
+ sscanf( tmp+14, "integer;%d", &desc[num-1].aps );
+ }
+ else if (!strncmp( tmp, "MaxPacketSize:", 14 )) {
+ sscanf( tmp+14, "integer;%d", &desc[num-1].mps );
+ }
+ else if (!strncmp( tmp, "StartTime:", 10 )) {
+ sscanf( tmp+10, "integer;%d", &desc[num-1].str );
+ }
+ else if (!strncmp( tmp, "Preroll:", 8 )) {
+ sscanf( tmp+8, "integer;%d", &desc[num-1].prl );
+ }
+ else if (!strncmp( tmp, "OpaqueData:buffer;", 18 )) {
+ desc[num-1].data =
+ direct_base64_decode( trim( tmp+18 ),
+ &desc[num-1].data_size );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ tmp = end;
+ if (tmp) tmp++;
+ }
+
+ D_FREE( buf );
+
+ *ret_streams = desc;
+ *ret_num = num;
+
+ return desc ? DR_OK : DR_EOF;
+}
+
+static void
+sdp_free( SDPStreamDesc *streams, int num )
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ if (streams[i].control)
+ D_FREE( streams[i].control );
+ if (streams[i].mime)
+ D_FREE( streams[i].mime );
+ if (streams[i].data)
+ D_FREE( streams[i].data );
+ }
+ D_FREE( streams );
+}
+
+static DirectResult
+rmf_write_header( SDPStreamDesc *streams, int n_streams, void **ret_buf, unsigned int *ret_size )
+{
+ unsigned char *dst, *tmp;
+ int abr = 0;
+ int mbr = 0;
+ int aps = 0;
+ int mps = 0;
+ int str = 0;
+ int prl = 0;
+ int dur = 0;
+ int i, len;
+
+ len = 86 + n_streams*46;
+ for (i = 0; i < n_streams; i++) {
+ abr += streams[i].abr;
+ aps += streams[i].aps;
+ if (mbr < streams[i].mbr)
+ mbr = streams[i].mbr;
+ if (mps < streams[i].mps)
+ mps = streams[i].mps;
+ if (dur < streams[i].dur)
+ dur = streams[i].dur;
+ if (streams[i].mime)
+ len += streams[i].mime_size;
+ if (streams[i].data)
+ len += streams[i].data_size;
+ else if (streams[i].payload)
+ len += 74;
+ }
+
+ *ret_buf = dst = D_MALLOC( len );
+ if (!dst)
+ return D_OOM();
+ *ret_size = len;
+
+ /* RMF */
+ dst[0] = '.'; dst[1] = 'R', dst[2] = 'M'; dst[3] = 'F';
+ dst[4] = dst[5] = dst[6] = 0; dst[7] = 18; // size
+ dst[8] = dst[9] = 0; // version
+ dst[10] = dst[11] = dst[12] = dst[13] = 0; // ??
+ dst[14] = dst[15] = dst[16] = 0; dst[17] = 4+n_streams; // num streams
+ dst += 18;
+
+ /* PROP */
+ dst[0] = 'P'; dst[1] = 'R'; dst[2] = 'O'; dst[3] = 'P';
+ dst[4] = dst[5] = dst[6] = 0; dst[7] = 50;
+ dst[8] = dst[9] = 0;
+ dst[10] = mbr>>24; dst[11] = mbr>>16; dst[12] = mbr>>8; dst[13] = mbr;
+ dst[14] = abr>>24; dst[15] = abr>>16; dst[16] = abr>>8; dst[17] = abr;
+ dst[18] = mps>>24; dst[19] = mps>>16; dst[20] = mps>>8; dst[21] = mps;
+ dst[22] = aps>>24; dst[23] = aps>>16; dst[24] = aps>>8; dst[25] = aps;
+ dst[26] = dst[27] = dst[28] = dst[29] = 0; // num packets
+ dst[30] = dur>>24; dst[31] = dur>>16; dst[32] = dur>>8; dst[33] = dur;
+ dst[34] = dst[35] = dst[36] = dst[37] = 0; // preroll
+ dst[38] = dst[39] = dst[40] = dst[41] = 0; // index offset
+ dst[42] = len>>24; dst[43] = len>>16; dst[44] = len>>8; dst[45] = len;
+ dst[46] = 0; dst[47] = n_streams; // num streams
+ dst[48] = 0; dst[49] = 7; // flags
+ dst += 50;
+
+ for (i = 0; i < n_streams; i++) {
+ len = 46 + streams[i].mime_size;
+ if (streams[i].data)
+ len += streams[i].data_size;
+ else if (streams[i].payload)
+ len += 74;
+
+ abr = streams[i].abr;
+ mbr = streams[i].mbr;
+ aps = streams[i].aps;
+ mps = streams[i].mps;
+ str = streams[i].str;
+ prl = streams[i].prl;
+ dur = streams[i].dur;
+
+ /* MDPR */
+ dst[0] = 'M'; dst[1] = 'D'; dst[2] = 'P'; dst[3] = 'R';
+ dst[4] = len>>24; dst[5] = len>>16; dst[6] = len>>8; dst[7] = len;
+ dst[8] = dst[9] = 0;
+ dst[10] = 0; dst[11] = i;
+ dst[12] = mbr>>24; dst[13] = mbr>>16; dst[14] = mbr>>8; dst[15] = mbr;
+ dst[16] = abr>>24; dst[17] = abr>>16; dst[18] = abr>>8; dst[19] = abr;
+ dst[20] = mps>>24; dst[21] = mps>>16; dst[22] = mps>>8; dst[23] = mps;
+ dst[24] = aps>>24; dst[25] = aps>>16; dst[26] = aps>>8; dst[27] = aps;
+ dst[28] = str>>24; dst[29] = str>>16; dst[30] = str>>8; dst[31] = str;
+ dst[32] = prl>>24; dst[33] = prl>>16; dst[34] = prl>>8; dst[35] = prl;
+ dst[36] = dur>>24; dst[37] = dur>>16; dst[38] = dur>>8; dst[39] = dur;
+ dst += 40;
+
+ /* description */
+ *dst++ = 0;
+ /* mimetype */
+ *dst++ = streams[i].mime_size;
+ for (tmp = (unsigned char*)streams[i].mime; tmp && *tmp;)
+ *dst++ = *tmp++;
+
+ /* codec data */
+ if (streams[i].data) {
+ len = streams[i].data_size;
+ dst[0] = len>>24; dst[1] = len>>16; dst[2] = len>>8; dst[3] = len;
+ direct_memcpy( dst+4, streams[i].data, streams[i].data_size );
+ dst += len+4;
+ }
+ else if (streams[i].payload) {
+ u32 fcc = streams[i].payload->fcc;
+
+ dst[0] = dst[1] = dst[2] = 0; dst[3] = 74;
+ dst += 4;
+ memset( dst, 0, 74 );
+
+ if (streams[i].payload->type == PAYLOAD_AUDIO) {
+ dst[0] = '.'; dst[1] = 'r'; dst[2] = 'a'; dst[3] = 0xfd;
+ dst[4] = 0; dst[5] = 5; // version
+ dst[66] = fcc; dst[67] = fcc>>8; dst[68] = fcc>>16; dst[69] = fcc>>24;
+ }
+ else {
+ dst[0] = dst[1] = dst[2] = 0; dst[3] = 34;
+ dst[4] = 'V'; dst[5] = 'I'; dst[6] = 'D'; dst[7] = 'O';
+ dst[8] = fcc; dst[9] = fcc>>8; dst[10] = fcc>>16; dst[11] = fcc>>24;
+ dst[30] = 0x10;
+ }
+ dst += 74;
+ }
+ else {
+ dst[0] = dst[1] = dst[2] = dst[3] = 0;
+ dst += 4;
+ }
+ }
+
+ /* DATA */
+ dst[0] = 'D'; dst[1] = 'A'; dst[2] = 'T'; dst[3] = 'A';
+ dst[4] = dst[5] = dst[6] = 0; dst[7] = 18; // size
+ dst[8] = dst[9] = 0; // version
+ dst[10] = dst[11] = dst[12] = dst[13] = 0; // num packets
+ dst[14] = dst[15] = dst[16] = dst[17] = 0; // next data
+
+ return DR_OK;
+}
+
+static int
+rmf_write_pheader( unsigned char *dst, int id, int sz, unsigned int ts )
+{
+ /* version */
+ dst[0] = dst[1] = 0;
+ /* length */
+ dst[2] = (sz+12)>>8; dst[3] = sz+12;
+ /* indentifier */
+ dst[4] = id>>8; dst[5] = id;
+ /* timestamp */
+ dst[6] = ts>>24; dst[7] = ts>>16; dst[8] = ts>>8; dst[9] = ts;
+ /* reserved */
+ dst[10] = 0;
+ /* flags */
+ dst[11] = 0;
+
+ return 12;
+}
+
+static void
+real_calc_challenge2( char response[64], char checksum[32], char *challenge )
+{
+ const unsigned char xor_table[37] = {
+ 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
+ 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
+ 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
+ 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
+ 0x10, 0x57, 0x05, 0x18, 0x54
+ };
+ char buf[128];
+ char md5[16];
+ int len;
+ int i;
+
+ memset( response, 0, 64 );
+ memset( checksum, 0, 32 );
+
+ buf[0] = 0xa1; buf[1] = 0xe9; buf[2] = 0x14; buf[3] = 0x9d;
+ buf[4] = 0x0e; buf[5] = 0x6b; buf[6] = 0x3b; buf[7] = 0x59;
+ memset( buf+8, 0, 120 );
+
+ len = strlen( challenge );
+ if (len == 40) {
+ challenge[32] = '\0';
+ len = 32;
+ }
+ memcpy( buf+8, challenge, MAX(len,56) );
+
+ for (i = 0; i < 37; i++)
+ buf[8+i] ^= xor_table[i];
+
+ /* compute response */
+ direct_md5_sum( md5, buf, 64 );
+ /* convert to ascii */
+ for (i = 0; i < 16; i++) {
+ char a, b;
+ a = (md5[i] >> 4) & 15;
+ b = md5[i] & 15;
+ response[i*2+0] = ((a < 10) ? (a + 48) : (a + 87)) & 255;
+ response[i*2+1] = ((b < 10) ? (b + 48) : (b + 87)) & 255;
+ }
+ /* tail */
+ len = strlen( response );
+ direct_snputs( &response[len], "01d0a8e3", 64-len );
+
+ /* compute checksum */
+ for (i = 0; i < len/4; i++)
+ checksum[i] = response[i*4];
+}
+
+static DirectResult
+rtsp_session_open( DirectStream *stream )
+{
+ DirectResult ret;
+ int status;
+ int cseq = 0;
+ SDPStreamDesc *streams = NULL;
+ int n_streams = 0;
+ char session[32] = {0, };
+ char challen[64] = {0, };
+ char buf[1280];
+ int i, len;
+
+ snprintf( buf, sizeof(buf),
+ "OPTIONS rtsp://%s:%d RTSP/1.0\r\n"
+ "CSeq: %d\r\n"
+ "User-Agent: DirectFB/%s\r\n"
+ "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"
+ "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"
+ "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"
+ "GUID: 00000000-0000-0000-0000-000000000000\r\n"
+ "RegionData: 0\r\n",
+ stream->remote.host,
+ stream->remote.port,
+ ++cseq, DIRECTFB_VERSION );
+
+ if (net_command( stream, buf, sizeof(buf) ) != 200)
+ return DR_FAILURE;
+
+ while (net_response( stream, buf, sizeof(buf) ) > 0) {
+ if (!strncmp( buf, "RealChallenge1:", 15 )) {
+ snprintf( challen, sizeof(challen), "%s", trim( buf+15 ) );
+ stream->remote.real_rtsp = true;
+ }
+ }
+
+ len = snprintf( buf, sizeof(buf),
+ "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n"
+ "CSeq: %d\r\n"
+ "Accept: application/sdp\r\n"
+ "Bandwidth: 10485800\r\n",
+ stream->remote.host,
+ stream->remote.port,
+ stream->remote.path,
+ ++cseq );
+ if (stream->remote.real_rtsp) {
+ snprintf( buf+len, sizeof(buf)-len,
+ "GUID: 00000000-0000-0000-0000-000000000000\r\n"
+ "RegionData: 0\r\n"
+ "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586\r\n"
+ "SupportsMaximumASMBandwidth: 1\r\n"
+ "Require: com.real.retain-entity-for-setup\r\n" );
+ }
+
+ status = net_command( stream, buf, sizeof(buf) );
+ if (status != 200)
+ return (status == 404) ? DR_FILENOTFOUND : DR_FAILURE;
+
+ len = 0;
+ while (net_response( stream, buf, sizeof(buf) ) > 0) {
+ if (!strncasecmp( buf, "ETag:", 5 )) {
+ snprintf( session, sizeof(session), "%s", trim( buf+5 ) );
+ }
+ else if (!strncasecmp( buf, "Content-Length:", 15 )) {
+ char *tmp = trim( buf+15 );
+ if (sscanf( tmp, "%d", &len ) != 1)
+ sscanf( tmp, "bytes=%d", &len );
+ }
+ }
+
+ if (!len) {
+ D_DEBUG_AT( Direct_Stream, "Couldn't get sdp length!\n" );
+ return DR_FAILURE;
+ }
+
+ ret = sdp_parse( stream, len, &streams, &n_streams );
+ if (ret)
+ return ret;
+
+ for (i = 0; i < n_streams; i++) {
+ /* skip unhandled payload types */
+ if (!stream->remote.real_rtsp && !streams[i].payload)
+ continue;
+
+ len = snprintf( buf, sizeof(buf),
+ "SETUP rtsp://%s:%d%s/%s RTSP/1.0\r\n"
+ "CSeq: %d\r\n",
+ stream->remote.host,
+ stream->remote.port,
+ stream->remote.path,
+ streams[i].control, ++cseq );
+ if (*session) {
+ if (*challen) {
+ char response[64];
+ char checksum[32];
+
+ real_calc_challenge2( response, checksum, challen );
+ len += snprintf( buf+len, sizeof(buf)-len,
+ "RealChallenge2: %s, sd=%s\r\n",
+ response, checksum );
+ *challen = '\0';
+ }
+ len += snprintf( buf+len, sizeof(buf)-len,
+ "%s: %s\r\n",
+ i ? "Session" : "If-Match", session );
+ }
+ snprintf( buf+len, sizeof(buf)-len,
+ "Transport: %s\r\n",
+ stream->remote.real_rtsp
+ ? "x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"
+ : "RTP/AVP/TCP;unicast" );
+
+ if (net_command( stream, buf, sizeof(buf) ) != 200) {
+ sdp_free( streams, n_streams );
+ return DR_FAILURE;
+ }
+
+ while (net_response( stream, buf, sizeof(buf) ) > 0) {
+ if (!strncmp( buf, "Session:", 8 ))
+ snprintf( session, sizeof(session), "%s", trim( buf+8 ) );
+ }
+ }
+
+ len = snprintf( buf, sizeof(buf),
+ "PLAY rtsp://%s:%d%s RTSP/1.0\r\n"
+ "CSeq: %d\r\n",
+ stream->remote.host,
+ stream->remote.port,
+ stream->remote.path,
+ ++cseq );
+ if (*session) {
+ len += snprintf( buf+len, sizeof(buf)-len,
+ "Session: %s\r\n", session );
+ }
+ snprintf( buf+len, sizeof(buf)-len,
+ "Range: npt=0-\r\n"
+ "Connection: Close\r\n" );
+
+ if (net_command( stream, buf, sizeof(buf) ) != 200) {
+ sdp_free( streams, n_streams );
+ return DR_FAILURE;
+ }
+
+ /* discard remaining headers */
+ while (net_response( stream, buf, sizeof(buf) ) > 0);
+
+ /* revert to blocking mode */
+ fcntl( stream->fd, F_SETFL,
+ fcntl( stream->fd, F_GETFL ) & ~O_NONBLOCK );
+
+ if (!stream->remote.real_rtsp) {
+ RTPPayload *p;
+
+ stream->remote.data = D_CALLOC( 1, (n_streams+1)*sizeof(RTPPayload) );
+ if (!stream->remote.data) {
+ sdp_free( streams, n_streams );
+ return D_OOM();
+ }
+
+ p = (RTPPayload*) stream->remote.data;
+ for (i = 0; i < n_streams; i++) {
+ if (streams[i].payload) {
+ *p = *(streams[i].payload);
+ p->pt = streams[i].pt;
+ p++;
+ }
+ }
+ }
+
+ stream->remote.real_pack = true;
+ if (n_streams == 1 && streams[0].mime) {
+ if (!strcmp( streams[0].mime, "audio/mpeg" ) ||
+ !strcmp( streams[0].mime, "audio/aac" ) ||
+ !strcmp( streams[0].mime, "video/mpeg" ) ||
+ !strcmp( streams[0].mime, "video/mpegts" ))
+ {
+ stream->mime = D_STRDUP( streams[0].mime );
+ stream->remote.real_pack = false;
+ }
+ }
+ if (stream->remote.real_pack) {
+ ret = rmf_write_header( streams, n_streams,
+ &stream->cache, &stream->cache_size );
+ if (ret) {
+ sdp_free( streams, n_streams );
+ return ret;
+ }
+ stream->mime = D_STRDUP( "application/vnd.rn-realmedia" );
+ }
+
+ sdp_free( streams, n_streams );
+
+ return DR_OK;
+}
+
+static DirectResult
+rvp_read_packet( DirectStream *stream )
+{
+ unsigned char buf[9];
+ int size;
+ int len;
+ unsigned char id;
+ unsigned int ts;
+
+ while (1) {
+ do {
+ size = recv( stream->fd, buf, 1, MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ } while (buf[0] != '$');
+
+ size = recv( stream->fd, buf, 7, MSG_WAITALL );
+ if (size < 7)
+ return DR_EOF;
+
+ len = (buf[0] << 16) + (buf[1] << 8) + buf[2];
+ id = buf[3];
+ if (id != 0x40 && id != 0x42) {
+ if (buf[5] == 0x06) // EOS
+ return DR_EOF;
+ size = recv( stream->fd, buf, 9, MSG_WAITALL );
+ if (size < 9)
+ return DR_EOF;
+ id = buf[5];
+ len -= 9;
+ }
+ id = (id >> 1) & 1;
+
+ size = recv( stream->fd, buf, 6, MSG_WAITALL );
+ if (size < 6)
+ return DR_EOF;
+ ts = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+
+ len -= 10;
+ if (len > 0) {
+ unsigned char *dst;
+
+ size = len + 12;
+ stream->cache = D_REALLOC( stream->cache, stream->cache_size+size );
+ if (!stream->cache)
+ return D_OOM();
+ dst = stream->cache+stream->cache_size;
+ stream->cache_size += size;
+
+ dst += rmf_write_pheader( dst, id, len, ts );
+
+ while (len) {
+ size = recv( stream->fd, dst, len, MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ dst += size;
+ len -= size;
+ }
+ break;
+ }
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+rtp_read_packet( DirectStream *stream )
+{
+ RTPPayload *payloads = (RTPPayload*)stream->remote.data;
+ unsigned char buf[12];
+ int size;
+ int len;
+ unsigned char id;
+ unsigned short seq;
+ unsigned int ts;
+ int skip;
+
+ while (1) {
+ RTPPayload *p;
+
+ do {
+ size = recv( stream->fd, buf, 1, MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ } while (buf[0] != '$');
+
+ size = recv( stream->fd, buf, 3, MSG_WAITALL );
+ if (size < 3)
+ return DR_EOF;
+
+ id = buf[0];
+ len = (buf[1] << 8) | buf[2];
+ if (len < 12)
+ continue;
+
+ size = recv( stream->fd, buf, 12, MSG_WAITALL );
+ if (size < 12)
+ return DR_EOF;
+ len -= 12;
+
+ if ((buf[0] & 0xc0) != (2 << 6))
+ D_DEBUG_AT( Direct_Stream, "Bad RTP version %d!\n", buf[0] );
+ seq = (buf[2] << 8) | buf[3];
+ ts = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+
+ for (p = payloads; p->pt; p++) {
+ if (p->pt == (buf[1] & 0x7f))
+ break;
+ }
+
+ switch (p->pt) {
+ case 0: // Unhandled
+ skip = len;
+ break;
+ case 14: // MPEG Audio
+ skip = 4;
+ break;
+ case 32: // MPEG Video
+ size = recv( stream->fd, buf, 1, MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ len--;
+ skip = 3;
+ if (buf[0] & (1 << 2))
+ skip += 4;
+ break;
+ case 34: // H263
+ size = recv( stream->fd, buf, 1, MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ len--;
+ skip = 3;
+ if (buf[0] & (1 << 7))
+ skip += 4;
+ if (buf[0] & (1 << 6))
+ skip += 4;
+ break;
+ default:
+ skip = 0;
+ break;
+ }
+
+ while (skip) {
+ size = recv( stream->fd, buf, MIN(skip,12), MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ len -= size;
+ skip -= size;
+ }
+
+ if (len > 0) {
+ unsigned char *dst;
+
+ size = len;
+ if (stream->remote.real_pack) {
+ size += 12;
+ if (p->type == PAYLOAD_VIDEO)
+ size += 7;
+ }
+
+ stream->cache = D_REALLOC( stream->cache, stream->cache_size+size );
+ if (!stream->cache)
+ return D_OOM();
+ dst = stream->cache+stream->cache_size;
+ stream->cache_size += size;
+
+ if (stream->remote.real_pack) {
+ if (p->type == PAYLOAD_VIDEO) {
+ dst += rmf_write_pheader( dst, id, len+7, ts );
+ dst[0] = 0x81;
+ dst[1] = 0x01;
+ dst[2] = (len | 0x4000)>>8; dst[3] = len;
+ dst[4] = (len | 0x4000)>>8; dst[5] = len;
+ dst[6] = seq;
+ dst += 7;
+ } else {
+ dst += rmf_write_pheader( dst, id, len, ts );
+ }
+ }
+
+ while (len) {
+ size = recv( stream->fd, dst, len, MSG_WAITALL );
+ if (size < 1)
+ return DR_EOF;
+ dst += size;
+ len -= size;
+ }
+ break;
+ }
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+rtsp_peek( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out )
+{
+ DirectResult ret;
+ unsigned int len;
+
+ if (offset < 0)
+ return DR_UNSUPPORTED;
+
+ len = length + offset;
+ while (len > stream->cache_size) {
+ ret = (stream->remote.real_rtsp)
+ ? rvp_read_packet( stream )
+ : rtp_read_packet( stream );
+ if (ret) {
+ if (stream->cache_size < offset)
+ return ret;
+ break;
+ }
+ }
+
+ len = MIN( stream->cache_size-offset, length );
+ direct_memcpy( buf, stream->cache+offset, len );
+
+ if (read_out)
+ *read_out = len;
+
+ return DR_OK;
+}
+
+static DirectResult
+rtsp_read( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out )
+{
+ DirectResult ret;
+ unsigned int size = 0;
+
+ while (size < length) {
+ if (stream->cache_size) {
+ unsigned int len = MIN( stream->cache_size, length-size );
+
+ direct_memcpy( buf+size, stream->cache, len );
+ size += len;
+ stream->cache_size -= len;
+
+ if (stream->cache_size) {
+ direct_memcpy( stream->cache,
+ stream->cache+len, stream->cache_size );
+ } else {
+ D_FREE( stream->cache );
+ stream->cache = NULL;
+ }
+ }
+
+ if (size < length) {
+ ret = (stream->remote.real_rtsp)
+ ? rvp_read_packet( stream )
+ : rtp_read_packet( stream );
+ if (ret) {
+ if (!size)
+ return ret;
+ break;
+ }
+ }
+ }
+
+ stream->offset += size;
+
+ if (read_out)
+ *read_out = size;
+
+ return DR_OK;
+}
+
+static DirectResult
+rtsp_open( DirectStream *stream, const char *filename )
+{
+ DirectResult ret;
+
+ stream->remote.port = RTSP_PORT;
+
+ ret = net_open( stream, filename, IPPROTO_TCP );
+ if (ret)
+ return ret;
+
+ ret = rtsp_session_open( stream );
+ if (ret) {
+ close( stream->remote.sd );
+ return ret;
+ }
+
+ stream->peek = rtsp_peek;
+ stream->read = rtsp_read;
+
+ return DR_OK;
+}
+
+#endif /* DIRECT_BUILD_NETWORK */
+
+/************************** End of Network Support ***************************/
+
+static DirectResult
+pipe_wait( DirectStream *stream,
+ unsigned int length,
+ struct timeval *tv )
+{
+ fd_set s;
+
+ if (stream->cache_size >= length)
+ return DR_OK;
+
+ FD_ZERO( &s );
+ FD_SET( stream->fd, &s );
+
+ switch (select( stream->fd+1, &s, NULL, NULL, tv )) {
+ case 0:
+ if (!tv && !stream->cache_size)
+ return DR_EOF;
+ return DR_TIMEOUT;
+ case -1:
+ return errno2result( errno );
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+pipe_peek( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out )
+{
+ unsigned int size = length;
+ int len;
+
+ if (offset < 0)
+ return DR_UNSUPPORTED;
+
+ len = length + offset;
+ if (len > stream->cache_size) {
+ ssize_t s;
+
+ stream->cache = D_REALLOC( stream->cache, len );
+ if (!stream->cache) {
+ stream->cache_size = 0;
+ return D_OOM();
+ }
+
+ s = read( stream->fd,
+ stream->cache + stream->cache_size,
+ len - stream->cache_size );
+ if (s < 0) {
+ if (errno != EAGAIN || stream->cache_size == 0)
+ return errno2result( errno );
+ s = 0;
+ }
+
+ stream->cache_size += s;
+ if (stream->cache_size <= offset)
+ return DR_BUFFEREMPTY;
+
+ size = stream->cache_size - offset;
+ }
+
+ direct_memcpy( buf, stream->cache+offset, size );
+
+ if (read_out)
+ *read_out = size;
+
+ return DR_OK;
+}
+
+static DirectResult
+pipe_read( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out )
+{
+ unsigned int size = 0;
+
+ if (stream->cache_size) {
+ size = MIN( stream->cache_size, length );
+
+ direct_memcpy( buf, stream->cache, size );
+
+ length -= size;
+ stream->cache_size -= size;
+
+ if (stream->cache_size) {
+ direct_memcpy( stream->cache,
+ stream->cache+size, stream->cache_size );
+ } else {
+ D_FREE( stream->cache );
+ stream->cache = NULL;
+ }
+ }
+
+ if (length) {
+ ssize_t s;
+
+ s = read( stream->fd, buf+size, length-size );
+ switch (s) {
+ case 0:
+ if (!size)
+ return DR_EOF;
+ break;
+ case -1:
+ if (!size) {
+ return (errno == EAGAIN)
+ ? DR_BUFFEREMPTY
+ : errno2result( errno );
+ }
+ break;
+ default:
+ size += s;
+ break;
+ }
+ }
+
+ stream->offset += size;
+
+ if (read_out)
+ *read_out = size;
+
+ return DR_OK;
+}
+
+/*****************************************************************************/
+
+static DirectResult
+file_peek( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out )
+{
+ DirectResult ret = DR_OK;
+ ssize_t size;
+
+ if (lseek( stream->fd, offset, SEEK_CUR ) < 0)
+ return DR_FAILURE;
+
+ size = read( stream->fd, buf, length );
+ switch (size) {
+ case 0:
+ ret = DR_EOF;
+ break;
+ case -1:
+ ret = (errno == EAGAIN)
+ ? DR_BUFFEREMPTY
+ : errno2result( errno );
+ size = 0;
+ break;
+ }
+
+ if (lseek( stream->fd, - offset - size, SEEK_CUR ) < 0)
+ return DR_FAILURE;
+
+ if (read_out)
+ *read_out = size;
+
+ return ret;
+}
+
+static DirectResult
+file_read( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out )
+{
+ ssize_t size;
+
+ size = read( stream->fd, buf, length );
+ switch (size) {
+ case 0:
+ return DR_EOF;
+ case -1:
+ if (errno == EAGAIN)
+ return DR_BUFFEREMPTY;
+ return errno2result( errno );
+ }
+
+ stream->offset += size;
+
+ if (read_out)
+ *read_out = size;
+
+ return DR_OK;
+}
+
+static DirectResult
+file_seek( DirectStream *stream, unsigned int offset )
+{
+ off_t off;
+
+ off = lseek( stream->fd, offset, SEEK_SET );
+ if (off < 0)
+ return DR_FAILURE;
+
+ stream->offset = off;
+
+ return DR_OK;
+}
+
+static DirectResult
+file_open( DirectStream *stream, const char *filename, int fileno )
+{
+ if (filename)
+ stream->fd = open( filename, O_RDONLY | O_NONBLOCK );
+ else
+ stream->fd = dup( fileno );
+
+ if (stream->fd < 0)
+ return errno2result( errno );
+
+ fcntl( stream->fd, F_SETFL,
+ fcntl( stream->fd, F_GETFL ) | O_NONBLOCK );
+
+ if (lseek( stream->fd, 0, SEEK_CUR ) < 0 && errno == ESPIPE) {
+ stream->length = -1;
+ stream->wait = pipe_wait;
+ stream->peek = pipe_peek;
+ stream->read = pipe_read;
+ }
+ else {
+ struct stat s;
+
+ if (fstat( stream->fd, &s ) < 0)
+ return errno2result( errno );
+
+ stream->length = s.st_size;
+ stream->peek = file_peek;
+ stream->read = file_read;
+ stream->seek = file_seek;
+ }
+
+ return DR_OK;
+}
+
+/*****************************************************************************/
+
+DirectResult
+direct_stream_create( const char *filename,
+ DirectStream **ret_stream )
+{
+ DirectStream *stream;
+ DirectResult ret;
+
+ D_ASSERT( filename != NULL );
+ D_ASSERT( ret_stream != NULL );
+
+ stream = D_CALLOC( 1, sizeof(DirectStream) );
+ if (!stream)
+ return D_OOM();
+
+ D_MAGIC_SET( stream, DirectStream );
+
+ stream->ref = 1;
+ stream->fd = -1;
+
+ if (!strncmp( filename, "stdin:/", 7 )) {
+ ret = file_open( stream, NULL, STDIN_FILENO );
+ }
+ else if (!strncmp( filename, "file:/", 6 )) {
+ ret = file_open( stream, filename+6, -1 );
+ }
+ else if (!strncmp( filename, "fd:/", 4 )) {
+ ret = (filename[4] >= '0' && filename[4] <= '9')
+ ? file_open( stream, NULL, atoi(filename+4) ) : DR_INVARG;
+ }
+#if DIRECT_BUILD_NETWORK
+ else if (!strncmp( filename, "http://", 7 ) ||
+ !strncmp( filename, "unsv://", 7 )) {
+ ret = http_open( stream, filename+7 );
+ }
+ else if (!strncmp( filename, "ftp://", 6 )) {
+ ret = ftp_open( stream, filename+6 );
+ }
+ else if (!strncmp( filename, "rtsp://", 7 )) {
+ ret = rtsp_open( stream, filename+7 );
+ }
+ else if (!strncmp( filename, "tcp://", 6 )) {
+ ret = net_open( stream, filename+6, IPPROTO_TCP );
+ }
+ else if (!strncmp( filename, "udp://", 6 )) {
+ ret = net_open( stream, filename+6, IPPROTO_UDP );
+ }
+#endif
+ else {
+ ret = file_open( stream, filename, -1 );
+ }
+
+ if (ret) {
+ direct_stream_close( stream );
+ D_FREE( stream );
+ return ret;
+ }
+
+ *ret_stream = stream;
+
+ return DR_OK;
+}
+
+DirectStream*
+direct_stream_dup( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ stream->ref++;
+
+ return stream;
+}
+
+int
+direct_stream_fileno( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ return stream->fd;
+}
+
+bool
+direct_stream_seekable( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ return stream->seek ? true : false;
+}
+
+bool
+direct_stream_remote( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+#if DIRECT_BUILD_NETWORK
+ if (stream->remote.host)
+ return true;
+#endif
+ return false;
+}
+
+const char*
+direct_stream_mime( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ return stream->mime;
+}
+
+unsigned int
+direct_stream_offset( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ return stream->offset;
+}
+
+unsigned int
+direct_stream_length( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ return (stream->length >= 0) ? stream->length : stream->offset;
+}
+
+DirectResult
+direct_stream_wait( DirectStream *stream,
+ unsigned int length,
+ struct timeval *tv )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ if (length && stream->wait)
+ return stream->wait( stream, length, tv );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_stream_peek( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out )
+{
+ D_ASSERT( stream != NULL );
+ D_ASSERT( length != 0 );
+ D_ASSERT( buf != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ if (stream->length >= 0 && (stream->offset + offset) >= stream->length)
+ return DR_EOF;
+
+ if (stream->peek)
+ return stream->peek( stream, length, offset, buf, read_out );
+
+ return DR_UNSUPPORTED;
+}
+
+DirectResult
+direct_stream_read( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out )
+{
+ D_ASSERT( stream != NULL );
+ D_ASSERT( length != 0 );
+ D_ASSERT( buf != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ if (stream->length >= 0 && stream->offset >= stream->length)
+ return DR_EOF;
+
+ if (stream->read)
+ return stream->read( stream, length, buf, read_out );
+
+ return DR_UNSUPPORTED;
+}
+
+DirectResult
+direct_stream_seek( DirectStream *stream,
+ unsigned int offset )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ if (stream->offset == offset)
+ return DR_OK;
+
+ if (stream->length >= 0 && offset > stream->length)
+ offset = stream->length;
+
+ if (stream->seek)
+ return stream->seek( stream, offset );
+
+ return DR_UNSUPPORTED;
+}
+
+static void
+direct_stream_close( DirectStream *stream )
+{
+#if DIRECT_BUILD_NETWORK
+ if (stream->remote.host) {
+ D_FREE( stream->remote.host );
+ stream->remote.host = NULL;
+ }
+
+ if (stream->remote.user) {
+ D_FREE( stream->remote.user );
+ stream->remote.user = NULL;
+ }
+
+ if (stream->remote.pass) {
+ D_FREE( stream->remote.pass );
+ stream->remote.pass = NULL;
+ }
+
+ if (stream->remote.auth) {
+ D_FREE( stream->remote.auth );
+ stream->remote.auth = NULL;
+ }
+
+ if (stream->remote.path) {
+ D_FREE( stream->remote.path );
+ stream->remote.path = NULL;
+ }
+
+ if (stream->remote.addr) {
+ freeaddrinfo( stream->remote.addr );
+ stream->remote.addr = NULL;
+ }
+
+ if (stream->remote.data) {
+ D_FREE( stream->remote.data );
+ stream->remote.data = NULL;
+ }
+
+ if (stream->remote.sd > 0) {
+ close( stream->remote.sd );
+ stream->remote.sd = -1;
+ }
+#endif
+
+ if (stream->mime) {
+ D_FREE( stream->mime );
+ stream->mime = NULL;
+ }
+
+ if (stream->cache) {
+ D_FREE( stream->cache );
+ stream->cache = NULL;
+ stream->cache_size = 0;
+ }
+
+ if (stream->fd >= 0) {
+ fcntl( stream->fd, F_SETFL,
+ fcntl( stream->fd, F_GETFL ) & ~O_NONBLOCK );
+ close( stream->fd );
+ stream->fd = -1;
+ }
+}
+
+void
+direct_stream_destroy( DirectStream *stream )
+{
+ D_ASSERT( stream != NULL );
+
+ D_MAGIC_ASSERT( stream, DirectStream );
+
+ if (--stream->ref == 0) {
+ direct_stream_close( stream );
+
+ D_FREE( stream );
+ }
+}
diff --git a/Source/DirectFB/lib/direct/stream.h b/Source/DirectFB/lib/direct/stream.h
new file mode 100755
index 0000000..6b77690
--- /dev/null
+++ b/Source/DirectFB/lib/direct/stream.h
@@ -0,0 +1,129 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__STREAM_H__
+#define __DIRECT__STREAM_H__
+
+#include <stdio.h>
+#include <sys/time.h>
+
+#include <direct/types.h>
+
+/*
+ * Create a stream wrapper.
+ *
+ * 'filename' can be a plain file name or one of the following:
+ * http://<host>[:<port>]/<path>
+ * unsv://<host>[:<port>]/<path>
+ * ftp://<host>[:<port>]/<path>
+ * rtsp://<host>[:<port>]/<path>
+ * tcp://<host>:<port>
+ * udp://<host>:<port>
+ * file:/<path>
+ * fd:/<fileno>
+ * stdin:/
+ */
+DirectResult direct_stream_create ( const char *filename,
+ DirectStream **ret_stream );
+
+/*
+ * Duplicate the stream (never fails).
+ */
+DirectStream *direct_stream_dup ( DirectStream *stream );
+
+/*
+ * Return the file descriptor associated to the stream.
+ */
+int direct_stream_fileno ( DirectStream *stream );
+
+/*
+ * True if stream is seekable.
+ */
+bool direct_stream_seekable( DirectStream *stream );
+
+/*
+ * True if stream originates from a remote host.
+ */
+bool direct_stream_remote ( DirectStream *stream );
+
+/*
+ * Get the mime description of the stream.
+ * Returns NULL if the information is not available.
+ */
+const char* direct_stream_mime ( DirectStream *stream );
+
+/*
+ * Get stream length.
+ */
+unsigned int direct_stream_length ( DirectStream *stream );
+
+/*
+ * Get stream position.
+ */
+unsigned int direct_stream_offset ( DirectStream *stream );
+
+/*
+ * Wait for data to be available.
+ * If 'timeout' is NULL, the function blocks indefinitely.
+ * Set the 'timeout' to 0 to make the function return immediatly.
+ */
+DirectResult direct_stream_wait ( DirectStream *stream,
+ unsigned int length,
+ struct timeval *timeout );
+
+/*
+ * Peek 'length' bytes of data at offset 'offset' from the stream.
+ */
+DirectResult direct_stream_peek ( DirectStream *stream,
+ unsigned int length,
+ int offset,
+ void *buf,
+ unsigned int *read_out );
+
+/*
+ * Fetch 'length' bytes of data from the stream.
+ */
+DirectResult direct_stream_read ( DirectStream *stream,
+ unsigned int length,
+ void *buf,
+ unsigned int *read_out );
+
+/*
+ * Seek to the specified absolute offset within the stream.
+ */
+DirectResult direct_stream_seek ( DirectStream *stream,
+ unsigned int offset );
+
+/*
+ * Destroy the stream wrapper.
+ */
+void direct_stream_destroy ( DirectStream *stream );
+
+
+#endif /* __DIRECT__STREAM_H__ */
+
diff --git a/Source/DirectFB/lib/direct/system.c b/Source/DirectFB/lib/direct/system.c
new file mode 100755
index 0000000..b4b5b29
--- /dev/null
+++ b/Source/DirectFB/lib/direct/system.c
@@ -0,0 +1,68 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <direct/build.h>
+#include <direct/system.h>
+
+#if DIRECT_BUILD_GETTID && defined(HAVE_LINUX_UNISTD_H)
+#include <linux/unistd.h>
+#endif
+
+__attribute__((no_instrument_function))
+pid_t
+direct_gettid( void )
+{
+ pid_t tid = -1;
+#if DIRECT_BUILD_GETTID && defined(__NR_gettid) /* present on linux >= 2.4.20 */
+ tid = syscall(__NR_gettid);
+#endif
+ if (tid < 0)
+ tid = getpid();
+
+ return tid;
+}
+
+long
+direct_pagesize( void )
+{
+ return sysconf( _SC_PAGESIZE );
+}
+
+unsigned long
+direct_page_align( unsigned long value )
+{
+ unsigned long mask = sysconf( _SC_PAGESIZE ) - 1;
+
+ return (value + mask) & ~mask;
+}
+
diff --git a/Source/DirectFB/lib/direct/system.h b/Source/DirectFB/lib/direct/system.h
new file mode 100755
index 0000000..5cfe74e
--- /dev/null
+++ b/Source/DirectFB/lib/direct/system.h
@@ -0,0 +1,40 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__SYSTEM_H__
+#define __DIRECT__SYSTEM_H__
+
+#include <sys/types.h>
+
+pid_t direct_gettid( void );
+long direct_pagesize( void );
+
+unsigned long direct_page_align( unsigned long value );
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/thread.c b/Source/DirectFB/lib/direct/thread.c
new file mode 100755
index 0000000..91c66fc
--- /dev/null
+++ b/Source/DirectFB/lib/direct/thread.c
@@ -0,0 +1,795 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <pthread.h>
+#include <signal.h>
+#include <sched.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/signals.h>
+#include <direct/system.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+D_DEBUG_DOMAIN( Direct_Thread, "Direct/Thread", "Thread management" );
+D_DEBUG_DOMAIN( Direct_ThreadInit, "Direct/Thread/Init", "Thread initialization" );
+
+
+/* FIXME: DIRECT_THREAD_WAIT_INIT is required, but should be optional. */
+#define DIRECT_THREAD_WAIT_INIT
+
+
+struct __D_DirectThread {
+ int magic;
+
+ pthread_t thread; /* The pthread thread identifier. */
+ pid_t tid;
+
+ char *name;
+
+ DirectThreadType type; /* The thread's type, e.g. input thread. */
+ DirectThreadMainFunc main; /* The thread's main routine (or entry point). */
+ void *arg; /* Custom argument passed to the main routine. */
+
+ bool canceled; /* Set when direct_thread_cancel() is called. */
+ bool joining; /* Set when direct_thread_join() is called. */
+ bool joined; /* Set when direct_thread_join() has finished. */
+ bool detached; /* Set when direct_thread_detach() is called. */
+ bool terminated; /* Set when direct_thread_terminate() is called. */
+
+#ifdef DIRECT_THREAD_WAIT_INIT
+ bool init; /* Set to true before calling the main routine. */
+#endif
+
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+
+ unsigned int counter;
+};
+
+struct __D_DirectThreadInitHandler {
+ DirectLink link;
+
+ int magic;
+
+ DirectThreadInitFunc func;
+ void *arg;
+};
+
+/******************************************************************************/
+
+/*
+ * Wrapper around pthread's main routine to pass additional arguments
+ * and setup things like signal masks and scheduling priorities.
+ */
+static void *direct_thread_main( void *arg );
+
+/******************************************************************************/
+
+static pthread_mutex_t handler_lock = PTHREAD_MUTEX_INITIALIZER;
+static DirectLink *handlers = NULL;
+
+/******************************************************************************/
+
+DirectThreadInitHandler *
+direct_thread_add_init_handler( DirectThreadInitFunc func,
+ void *arg )
+{
+ DirectThreadInitHandler *handler;
+
+ handler = D_CALLOC( 1, sizeof(DirectThreadInitHandler) );
+ if (!handler) {
+ D_WARN( "out of memory" );
+ return NULL;
+ }
+
+ handler->func = func;
+ handler->arg = arg;
+
+ D_MAGIC_SET( handler, DirectThreadInitHandler );
+
+ pthread_mutex_lock( &handler_lock );
+
+ direct_list_append( &handlers, &handler->link );
+
+ pthread_mutex_unlock( &handler_lock );
+
+ return handler;
+}
+
+void
+direct_thread_remove_init_handler( DirectThreadInitHandler *handler )
+{
+ D_MAGIC_ASSERT( handler, DirectThreadInitHandler );
+
+ pthread_mutex_lock( &handler_lock );
+
+ direct_list_remove( &handlers, &handler->link );
+
+ pthread_mutex_unlock( &handler_lock );
+
+ D_MAGIC_CLEAR( handler );
+
+ D_FREE( handler );
+}
+
+/******************************************************************************/
+
+static pthread_mutex_t key_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_key_t thread_key = -1;
+
+/******************************************************************************/
+
+DirectThread *
+direct_thread_create( DirectThreadType thread_type,
+ DirectThreadMainFunc thread_main,
+ void *arg,
+ const char *name )
+{
+ DirectThread *thread;
+ pthread_attr_t attr;
+ struct sched_param param;
+ int policy;
+ int priority;
+ size_t stack_size;
+
+ D_ASSERT( thread_main != NULL );
+ D_ASSERT( name != NULL );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %s, %p(%p), '%s' )\n", __FUNCTION__,
+ direct_thread_type_name(thread_type), thread_main, arg, name );
+
+ /* Create the key for the TSD (thread specific data). */
+ pthread_mutex_lock( &key_lock );
+
+ if (thread_key == -1)
+ pthread_key_create( &thread_key, NULL );
+
+ pthread_mutex_unlock( &key_lock );
+
+ /* Allocate thread structure. */
+ thread = D_CALLOC( 1, sizeof(DirectThread) );
+ if (!thread) {
+ D_OOM();
+ return NULL;
+ }
+
+ /* Write thread information to structure. */
+ thread->name = D_STRDUP( name );
+ thread->type = thread_type;
+ thread->main = thread_main;
+ thread->arg = arg;
+
+ /* Initialize to -1 for synchronization. */
+ thread->thread = (pthread_t) -1;
+ thread->tid = (pid_t) -1;
+
+ /* Initialize mutex and condition. */
+ direct_util_recursive_pthread_mutex_init( &thread->lock );
+ pthread_cond_init( &thread->cond, NULL );
+
+ D_MAGIC_SET( thread, DirectThread );
+
+ /* Initialize scheduling and other parameters. */
+ pthread_attr_init( &attr );
+
+#ifdef PTHREAD_EXPLICIT_SCHED
+ pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
+#endif
+
+ /* Select scheduler. */
+ switch (direct_config->thread_scheduler) {
+ case DCTS_FIFO:
+ policy = SCHED_FIFO;
+ break;
+
+ case DCTS_RR:
+ policy = SCHED_RR;
+ break;
+
+ default:
+ policy = SCHED_OTHER;
+ break;
+ }
+
+ if (pthread_attr_setschedpolicy( &attr, policy ))
+ D_PERROR( "Direct/Thread: Could not set scheduling policy to %s!\n", direct_thread_policy_name(policy) );
+
+ /* Read (back) value. */
+ pthread_attr_getschedpolicy( &attr, &policy );
+
+ /* Select priority. */
+ switch (thread->type) {
+ case DTT_CLEANUP:
+ case DTT_INPUT:
+ case DTT_OUTPUT:
+ case DTT_MESSAGING:
+ case DTT_CRITICAL:
+ priority = thread->type * direct_config->thread_priority_scale / 100;
+ break;
+
+ default:
+ priority = direct_config->thread_priority;
+ break;
+ }
+
+ D_DEBUG_AT( Direct_ThreadInit, " -> %s (%d) [%d;%d]\n", direct_thread_policy_name(policy), priority,
+ sched_get_priority_min( policy ), sched_get_priority_max( policy ) );
+
+ if (priority < sched_get_priority_min( policy ))
+ priority = sched_get_priority_min( policy );
+
+ if (priority > sched_get_priority_max( policy ))
+ priority = sched_get_priority_max( policy );
+
+ param.sched_priority = priority;
+
+ if (pthread_attr_setschedparam( &attr, &param ))
+ D_PERROR( "Direct/Thread: Could not set scheduling priority to %d!\n", priority );
+
+ /* Select stack size? */
+ if (direct_config->thread_stack_size > 0) {
+ if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size ))
+ D_PERROR( "Direct/Thread: Could not set stack size to %d!\n", direct_config->thread_stack_size );
+ }
+
+ /* Read (back) value. */
+ pthread_attr_getstacksize( &attr, &stack_size );
+
+ /* Lock the thread mutex. */
+ D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" );
+ pthread_mutex_lock( &thread->lock );
+
+ /* Create and run the thread. */
+ D_DEBUG_AT( Direct_ThreadInit, " -> creating...\n" );
+ pthread_create( &thread->thread, &attr, direct_thread_main, thread );
+
+ pthread_attr_destroy( &attr );
+
+ pthread_getschedparam( thread->thread, &policy, &param );
+
+ D_INFO( "Direct/Thread: Started '%s' (%d) [%s %s/%s %d/%d] <%zu>...\n",
+ name, thread->tid, direct_thread_type_name(thread_type),
+ direct_thread_policy_name(policy), direct_thread_scheduler_name(direct_config->thread_scheduler),
+ param.sched_priority, priority, stack_size );
+
+#ifdef DIRECT_THREAD_WAIT_INIT
+ /* Wait for completion of the thread's initialization. */
+ while (!thread->init) {
+ D_DEBUG_AT( Direct_ThreadInit, " -> waiting...\n" );
+ pthread_cond_wait( &thread->cond, &thread->lock );
+ }
+
+ D_DEBUG_AT( Direct_ThreadInit, " -> ...thread is running.\n" );
+#endif
+
+ /* Unlock the thread mutex. */
+ D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" );
+ pthread_mutex_unlock( &thread->lock );
+
+ D_DEBUG_AT( Direct_ThreadInit, " -> returning %p\n", thread );
+
+ return thread;
+}
+
+DirectThread *
+direct_thread_self( void )
+{
+ DirectThread *thread = pthread_getspecific( thread_key );
+
+ if (thread)
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ return thread;
+}
+
+const char *
+direct_thread_get_name( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->name != NULL );
+
+ return thread->name;
+}
+
+pid_t
+direct_thread_get_tid( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ return thread->tid;
+}
+
+__attribute__((no_instrument_function))
+const char *
+direct_thread_self_name( void )
+{
+ DirectThread *thread = pthread_getspecific( thread_key );
+
+ /*
+ * This function is called by debugging functions, e.g. debug messages, assertions etc.
+ * Therefore no assertions are made here, because they would loop forever if they fail.
+ */
+
+#ifndef MACOS
+ return thread ? thread->name : NULL;
+#else
+ return "debug";
+#endif
+}
+
+void
+direct_thread_set_name( const char *name )
+{
+ char *copy;
+ DirectThread *thread = pthread_getspecific( thread_key );
+
+ D_DEBUG_AT( Direct_Thread, "%s( '%s' )\n", __FUNCTION__, name );
+
+ /* Support this function for non-direct threads. */
+ if (!thread) {
+ D_DEBUG_AT( Direct_Thread, " -> attaching unknown thread %d\n", direct_gettid() );
+
+ /* Create the key for the TSD (thread specific data). */
+ pthread_mutex_lock( &key_lock );
+
+ if (thread_key == -1)
+ pthread_key_create( &thread_key, NULL );
+
+ pthread_mutex_unlock( &key_lock );
+
+
+ thread = D_CALLOC( 1, sizeof(DirectThread) );
+ if (!thread) {
+ D_OOM();
+ return;
+ }
+
+ thread->thread = pthread_self();
+ thread->tid = direct_gettid();
+
+ D_MAGIC_SET( thread, DirectThread );
+
+ pthread_setspecific( thread_key, thread );
+ }
+ else
+ D_DEBUG_AT( Direct_Thread, " -> was '%s' (%d)\n", thread->name, direct_gettid() );
+
+ /* Duplicate string. */
+ copy = D_STRDUP( name );
+ if (!copy) {
+ D_OOM();
+ return;
+ }
+
+ /* Free old string. */
+ if (thread->name)
+ D_FREE( thread->name );
+
+ /* Keep the copy. */
+ thread->name = copy;
+}
+
+DirectResult
+direct_thread_wait( DirectThread *thread, int timeout_ms )
+{
+ unsigned int old_counter = thread->counter;
+
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d, %dms )\n", __FUNCTION__,
+ thread->main, thread->name, thread->tid, timeout_ms );
+
+ while (old_counter == thread->counter && !thread->terminated)
+ pthread_cond_wait( &thread->cond, &thread->lock );
+
+ if (thread->terminated)
+ return DR_DEAD;
+
+ return DR_OK;
+}
+
+void
+direct_thread_notify( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ pthread_mutex_lock( &thread->lock );
+
+ thread->counter++;
+
+ pthread_mutex_unlock( &thread->lock );
+
+ pthread_cond_broadcast( &thread->cond );
+}
+
+void
+direct_thread_lock( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ pthread_mutex_lock( &thread->lock );
+}
+
+void
+direct_thread_unlock( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ pthread_mutex_unlock( &thread->lock );
+}
+
+void
+direct_thread_terminate( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+ D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ thread->terminated = true;
+
+ direct_thread_notify( thread );
+}
+
+void
+direct_thread_cancel( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+ D_ASSERT( !pthread_equal( thread->thread, pthread_self() ) );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ thread->canceled = true;
+
+#if DIRECT_BUILD_NO_PTHREAD_CANCEL
+ D_UNIMPLEMENTED();
+#else
+ pthread_cancel( thread->thread );
+#endif
+}
+
+bool
+direct_thread_is_canceled( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ return thread->canceled;
+}
+
+void
+direct_thread_detach( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+ D_ASSERT( !pthread_equal( thread->thread, pthread_self() ) );
+
+ D_ASSUME( !thread->canceled );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ thread->detached = true;
+
+ pthread_detach( thread->thread );
+}
+
+bool
+direct_thread_is_detached( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ return thread->detached;
+}
+
+void
+direct_thread_testcancel( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+ D_ASSERT( pthread_equal( thread->thread, pthread_self() ) );
+
+#if DIRECT_BUILD_NO_PTHREAD_CANCEL
+ D_UNIMPLEMENTED();
+#else
+ /* Quick check before calling the pthread function. */
+ if (thread->canceled)
+ pthread_testcancel();
+#endif
+}
+
+void
+direct_thread_join( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSERT( thread->thread != -1 );
+
+ D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) );
+ D_ASSUME( !thread->joining );
+ D_ASSUME( !thread->joined );
+ D_ASSUME( !thread->detached );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ if (thread->detached) {
+ D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" );
+ return;
+ }
+
+ if (!thread->joining && !pthread_equal( thread->thread, pthread_self() )) {
+ thread->joining = true;
+
+ D_DEBUG_AT( Direct_Thread, " -> joining...\n" );
+
+ pthread_join( thread->thread, NULL );
+
+ thread->joined = true;
+
+ D_DEBUG_AT( Direct_Thread, " -> joined.\n" );
+ }
+}
+
+bool
+direct_thread_is_joined( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ return thread->joined;
+}
+
+void
+direct_thread_destroy( DirectThread *thread )
+{
+ D_MAGIC_ASSERT( thread, DirectThread );
+ D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) );
+ D_ASSUME( !thread->detached );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ if (thread->detached) {
+ D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" );
+ return;
+ }
+
+ if (!thread->joined && !pthread_equal( thread->thread, pthread_self() )) {
+ if (thread->canceled)
+ D_DEBUG_AT( Direct_Thread, " -> cancled but not joined!\n" );
+ else {
+ D_DEBUG_AT( Direct_Thread, " -> still running!\n" );
+
+ if (thread->name)
+ D_ERROR( "Direct/Thread: Canceling '%s' (%d)!\n", thread->name, thread->tid );
+ else
+ D_ERROR( "Direct/Thread: Canceling %d!\n", thread->tid );
+
+ thread->detached = true;
+
+ pthread_detach( thread->thread );
+
+ direct_thread_cancel( thread );
+
+ return;
+ }
+ }
+
+ D_MAGIC_CLEAR( thread );
+
+ D_FREE( thread->name );
+ D_FREE( thread );
+}
+
+/******************************************************************************/
+
+#if DIRECT_BUILD_TEXT
+const char *
+direct_thread_type_name( DirectThreadType type )
+{
+ switch (type) {
+ case DTT_DEFAULT:
+ return "DEFAULT";
+
+ case DTT_CLEANUP:
+ return "CLEANUP";
+
+ case DTT_INPUT:
+ return "INPUT";
+
+ case DTT_OUTPUT:
+ return "OUTPUT";
+
+ case DTT_MESSAGING:
+ return "MESSAGING";
+
+ case DTT_CRITICAL:
+ return "CRITICAL";
+ }
+
+ return "<unknown>";
+}
+
+const char *
+direct_thread_scheduler_name( DirectConfigThreadScheduler scheduler )
+{
+ switch (scheduler) {
+ case DCTS_OTHER:
+ return "OTHER";
+
+ case DCTS_FIFO:
+ return "FIFO";
+
+ case DCTS_RR:
+ return "RR";
+ }
+
+ return "<unknown>";
+}
+
+const char *
+direct_thread_policy_name( int policy )
+{
+ switch (policy) {
+ case SCHED_OTHER:
+ return "OTHER";
+
+ case SCHED_FIFO:
+ return "FIFO";
+
+ case SCHED_RR:
+ return "RR";
+ }
+
+ return "<unknown>";
+}
+#endif
+
+/******************************************************************************/
+
+static void
+direct_thread_cleanup( void *arg )
+{
+ DirectThread *thread = arg;
+
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
+
+ if (thread->detached) {
+ D_MAGIC_CLEAR( thread );
+
+ D_FREE( thread->name );
+ D_FREE( thread );
+ }
+}
+
+/******************************************************************************/
+
+static void *
+direct_thread_main( void *arg )
+{
+ void *ret;
+ DirectThread *thread = arg;
+ DirectThreadInitHandler *handler;
+ pid_t tid;
+
+ tid = direct_gettid();
+
+ D_DEBUG_AT( Direct_ThreadInit, "%s( %p ) <- tid %d\n", __FUNCTION__, arg, tid );
+
+ D_DEBUG_AT( Direct_ThreadInit, " -> starting...\n" );
+
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ pthread_cleanup_push( direct_thread_cleanup, thread );
+
+
+ pthread_setspecific( thread_key, thread );
+
+ thread->tid = tid;
+
+
+ /* Call all init handlers. */
+ pthread_mutex_lock( &handler_lock );
+
+ direct_list_foreach (handler, handlers)
+ handler->func( thread, handler->arg );
+
+ pthread_mutex_unlock( &handler_lock );
+
+
+ /* Have all signals handled by the main thread. */
+ if (direct_config->thread_block_signals)
+ direct_signals_block_all();
+
+ /* Lock the thread mutex. */
+ D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" );
+ pthread_mutex_lock( &thread->lock );
+
+ /* Indicate that our initialization has completed. */
+ thread->init = true;
+
+#ifdef DIRECT_THREAD_WAIT_INIT
+ D_DEBUG_AT( Direct_ThreadInit, " -> signalling...\n" );
+ pthread_cond_signal( &thread->cond );
+#endif
+
+ /* Unlock the thread mutex. */
+ D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" );
+ pthread_mutex_unlock( &thread->lock );
+
+ if (thread->joining) {
+ D_DEBUG_AT( Direct_Thread, " -> Being joined before entering main routine!\n" );
+ return NULL;
+ }
+
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ /* Call main routine. */
+ D_DEBUG_AT( Direct_ThreadInit, " -> running...\n" );
+ ret = thread->main( thread, thread->arg );
+
+ D_DEBUG_AT( Direct_Thread, " -> Returning %p from '%s' (%s, %d)...\n",
+ ret, thread->name, direct_thread_type_name(thread->type), thread->tid );
+
+ D_MAGIC_ASSERT( thread, DirectThread );
+
+ pthread_cleanup_pop( 1 );
+
+ return ret;
+}
+
diff --git a/Source/DirectFB/lib/direct/thread.h b/Source/DirectFB/lib/direct/thread.h
new file mode 100755
index 0000000..18205c4
--- /dev/null
+++ b/Source/DirectFB/lib/direct/thread.h
@@ -0,0 +1,168 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__THREAD_H__
+#define __DIRECT__THREAD_H__
+
+#include <sys/types.h>
+
+#include <direct/types.h>
+#include <direct/conf.h>
+
+typedef enum {
+ DTT_DEFAULT = 0,
+ DTT_CLEANUP = -5,
+ DTT_INPUT = -10,
+ DTT_OUTPUT = -12,
+ DTT_MESSAGING = -15,
+ DTT_CRITICAL = -20
+} DirectThreadType;
+
+typedef void * (*DirectThreadMainFunc)( DirectThread *thread, void *arg );
+
+typedef void (*DirectThreadInitFunc)( DirectThread *thread, void *arg );
+
+
+/*
+ * Add a handler being called at the beginning of new threads.
+ */
+DirectThreadInitHandler *direct_thread_add_init_handler ( DirectThreadInitFunc func,
+ void *arg );
+
+/*
+ * Remove the specified handler.
+ */
+void direct_thread_remove_init_handler( DirectThreadInitHandler *handler );
+
+/*
+ * Create a new thread and start it.
+ * The thread type is relevant for the scheduling priority.
+ */
+DirectThread *direct_thread_create ( DirectThreadType thread_type,
+ DirectThreadMainFunc thread_main,
+ void *arg,
+ const char *name );
+
+/*
+ * Returns the thread of the caller.
+ */
+DirectThread *direct_thread_self ( void );
+
+/*
+ * Returns the name of the specified thread.
+ */
+const char *direct_thread_get_name ( DirectThread *thread );
+
+/*
+ * Returns the thread ID of the specified thread.
+ */
+pid_t direct_thread_get_tid ( DirectThread *thread );
+
+/*
+ * Returns the name of the calling thread.
+ */
+const char *direct_thread_self_name ( void );
+
+/*
+ * Changes the name of the calling thread.
+ */
+void direct_thread_set_name ( const char *name );
+
+/*
+ * Wait on the thread object to be notified via direct_thread_notify().
+ */
+DirectResult direct_thread_wait ( DirectThread *thread,
+ int timeout_ms );
+
+/*
+ * Notify the thread object waking up callers of direct_thread_wait().
+ */
+void direct_thread_notify ( DirectThread *thread );
+
+void direct_thread_lock ( DirectThread *thread );
+void direct_thread_unlock ( DirectThread *thread );
+
+/*
+ * Kindly ask the thread to terminate (for joining without thread cancellation).
+ */
+void direct_thread_terminate ( DirectThread *thread );
+
+/*
+ * Cancel a running thread.
+ */
+void direct_thread_cancel ( DirectThread *thread );
+
+/*
+ * Returns true if the specified thread has been canceled.
+ */
+bool direct_thread_is_canceled( DirectThread *thread );
+
+/*
+ * Detach a thread.
+ */
+void direct_thread_detach ( DirectThread *thread );
+
+/*
+ * Returns true if the specified thread has been detached.
+ */
+bool direct_thread_is_detached( DirectThread *thread );
+
+/*
+ * Check if the calling thread is canceled.
+ * Must not be called by other threads than 'thread'.
+ * This function won't return if the thread is canceled.
+ */
+void direct_thread_testcancel ( DirectThread *thread );
+
+/*
+ * Wait until a running thread is terminated.
+ */
+void direct_thread_join ( DirectThread *thread );
+
+/*
+ * Returns true if the specified thread has been join.
+ */
+bool direct_thread_is_joined ( DirectThread *thread );
+
+/*
+ * Free resources allocated by direct_thread_create.
+ * If the thread is still running it will be killed.
+ */
+void direct_thread_destroy ( DirectThread *thread );
+
+/*
+ * Utilities for stringification.
+ */
+#if DIRECT_BUILD_TEXT
+const char *direct_thread_type_name ( DirectThreadType type );
+const char *direct_thread_scheduler_name( DirectConfigThreadScheduler scheduler );
+const char *direct_thread_policy_name ( int policy );
+#endif
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/trace.c b/Source/DirectFB/lib/direct/trace.c
new file mode 100755
index 0000000..d895333
--- /dev/null
+++ b/Source/DirectFB/lib/direct/trace.c
@@ -0,0 +1,676 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <direct/build.h>
+#include <direct/list.h>
+#include <direct/log.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/system.h>
+#include <direct/thread.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+
+#ifdef PIC
+#define DYNAMIC_LINKING
+#endif
+
+
+#if DIRECT_BUILD_TRACE
+
+#ifdef DYNAMIC_LINKING
+#include <dlfcn.h>
+#endif
+
+#define MAX_BUFFERS 200
+#define MAX_LEVEL 200
+
+#define NAME_LEN 92
+
+
+typedef enum {
+ TF_NONE = 0x00000000,
+
+ TF_DEBUG = 0x00000001
+} TraceFlags;
+
+typedef struct {
+ void *addr;
+ TraceFlags flags;
+} Trace;
+
+struct __D_DirectTraceBuffer {
+ pid_t tid;
+ char *name;
+ int level;
+ bool in_trace;
+ Trace trace[MAX_LEVEL];
+};
+
+/**************************************************************************************************/
+
+static DirectTraceBuffer *buffers[MAX_BUFFERS];
+static int buffers_num = 0;
+static pthread_mutex_t buffers_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_key_t trace_key = -1;
+
+/**************************************************************************************************/
+
+__attribute__((no_instrument_function))
+static void
+buffer_destroy( void *arg )
+{
+ int i;
+ DirectTraceBuffer *buffer = arg;
+
+ pthread_mutex_lock( &buffers_lock );
+
+ /* Remove from list. */
+ for (i=0; i<buffers_num; i++) {
+ if (buffers[i] == buffer)
+ break;
+ }
+
+ for (; i<buffers_num-1; i++)
+ buffers[i] = buffers[i+1];
+
+ buffers_num--;
+
+ /* Deallocate the buffer. */
+ direct_trace_free_buffer( buffer );
+
+ pthread_mutex_unlock( &buffers_lock );
+}
+
+__attribute__((no_instrument_function))
+static inline DirectTraceBuffer *
+get_trace_buffer( void )
+{
+ DirectTraceBuffer *buffer;
+
+ buffer = pthread_getspecific( trace_key );
+ if (!buffer) {
+ const char *name = direct_thread_self_name();
+
+ pthread_mutex_lock( &buffers_lock );
+
+ if (!buffers_num)
+ pthread_key_create( &trace_key, buffer_destroy );
+ else if (buffers_num == MAX_BUFFERS) {
+ D_ERROR( "Direct/Trace: Maximum number of threads (%d) reached!\n", MAX_BUFFERS );
+ pthread_mutex_unlock( &buffers_lock );
+ return NULL;
+ }
+
+ pthread_setspecific( trace_key,
+ buffer = calloc( 1, sizeof(DirectTraceBuffer) ) );
+
+ buffer->tid = direct_gettid();
+ buffer->name = name ? strdup( name ) : NULL;
+
+ buffers[buffers_num++] = buffer;
+
+ pthread_mutex_unlock( &buffers_lock );
+ }
+
+ return buffer;
+}
+
+/**************************************************************************************************/
+
+typedef struct {
+ long offset;
+ char name[NAME_LEN];
+} Symbol;
+
+typedef struct {
+ DirectLink link;
+
+ char *filename;
+ Symbol *symbols;
+ int capacity;
+ int num_symbols;
+} SymbolTable;
+
+static DirectLink *tables = NULL;
+static pthread_mutex_t tables_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+__attribute__((no_instrument_function))
+static void
+add_symbol( SymbolTable *table, long offset, const char *name )
+{
+ Symbol *symbol;
+
+ if (table->num_symbols == table->capacity) {
+ Symbol *symbols;
+ int capacity = table->capacity * 2;
+
+ if (!capacity)
+ capacity = 256;
+
+ symbols = malloc( capacity * sizeof(Symbol) );
+ if (!symbols) {
+ D_WARN( "out of memory" );
+ return;
+ }
+
+ direct_memcpy( symbols, table->symbols, table->num_symbols * sizeof(Symbol) );
+
+ free( table->symbols );
+
+ table->symbols = symbols;
+ table->capacity = capacity;
+ }
+
+ symbol = &table->symbols[ table->num_symbols++ ];
+
+ symbol->offset = offset;
+
+ direct_snputs( symbol->name, name, NAME_LEN );
+}
+
+__attribute__((no_instrument_function))
+static SymbolTable *
+load_symbols( const char *filename )
+{
+ SymbolTable *table;
+ FILE *fp = NULL;
+ bool is_pipe = false;
+ char file[1024];
+ char line[1024];
+ int command_len;
+ char *command;
+ const char *full_path = filename;
+ char *tmp;
+
+ if (filename) {
+ if (access( filename, R_OK ) < 0 && errno == ENOENT) {
+ int len;
+
+ if ((len = readlink( "/proc/self/exe", file, sizeof(file) - 1 )) < 0) {
+ D_PERROR( "Direct/Trace: readlink( \"/proc/self/exe\" ) failed!\n" );
+ return NULL;
+ }
+
+ file[len] = 0;
+
+
+ tmp = strrchr( file, '/' );
+ if (!tmp)
+ return NULL;
+
+ if (strcmp( filename, tmp + 1 ))
+ return NULL;
+
+ full_path = file;
+ }
+ }
+ else {
+ int len;
+
+ if ((len = readlink( "/proc/self/exe", file, sizeof(file) - 1 )) < 0) {
+ D_PERROR( "Direct/Trace: readlink( \"/proc/self/exe\" ) failed!\n" );
+ return NULL;
+ }
+
+ file[len] = 0;
+
+ full_path = file;
+ }
+
+ command_len = strlen( full_path ) + 32;
+ command = alloca( command_len );
+
+ /* First check if there's an "nm-n" file. */
+ tmp = strrchr( full_path, '/' );
+ if (!tmp)
+ return NULL;
+
+ *tmp = 0;
+ snprintf( command, command_len, "%s/nm-n.%s", full_path, tmp + 1 );
+ *tmp = '/';
+
+ if (access( command, R_OK ) == 0) {
+ fp = fopen( command, "r" );
+ if (!fp)
+ D_PERROR( "Direct/Trace: fopen( \"%s\", \"r\" ) failed!\n", command );
+ }
+ else {
+ snprintf( command, command_len, "%s.nm", full_path );
+ if (access( command, R_OK ) == 0) {
+ fp = fopen( command, "r" );
+ if (!fp)
+ D_PERROR( "Direct/Trace: fopen( \"%s\", \"r\" ) failed!\n", command );
+ }
+ }
+
+ /* Fallback to live mode. */
+ if (!fp) {
+ snprintf( command, command_len, "nm -n %s", full_path );
+
+ fp = popen( command, "r" );
+ if (!fp) {
+ D_PERROR( "Direct/Trace: popen( \"%s\", \"r\" ) failed!\n", command );
+ return NULL;
+ }
+
+ is_pipe = true;
+ }
+
+ table = calloc( 1, sizeof(SymbolTable) );
+ if (!table) {
+ D_OOM();
+ goto out;
+ }
+
+ if (filename)
+ table->filename = strdup( filename );
+
+ while (fgets( line, sizeof(line), fp )) {
+ int n;
+ int digits = sizeof(long) * 2;
+ long offset = 0;
+ int length = strlen(line);
+
+ if (line[0] == ' ' || length < (digits + 5) || line[length-1] != '\n')
+ continue;
+
+ if (line[digits + 1] != 't' && line[digits + 1] != 'T' && line[digits + 1] != 'W')
+ continue;
+
+ if (line[digits] != ' ' || line[digits + 2] != ' ' || line[digits + 3] == '.')
+ continue;
+
+ for (n=0; n<digits; n++) {
+ char c = line[n];
+
+ offset <<= 4;
+
+ if (c >= '0' && c <= '9')
+ offset |= c - '0';
+ else
+ offset |= c - 'a' + 10;
+ }
+
+ line[length-1] = 0;
+
+ add_symbol( table, offset, line + digits + 3 );
+ }
+
+out:
+ if (is_pipe)
+ pclose( fp );
+ else
+ fclose( fp );
+
+ return table;
+}
+
+__attribute__((no_instrument_function))
+static int
+compare_symbols(const void *x, const void *y)
+{
+ return *((const long*) x) - *((const long*) y);
+}
+
+__attribute__((no_instrument_function))
+static SymbolTable *
+find_table( const char *filename )
+{
+ SymbolTable *table;
+
+ if (filename) {
+ direct_list_foreach (table, tables) {
+ if (table->filename && !strcmp( filename, table->filename ))
+ return table;
+ }
+ }
+ else {
+ direct_list_foreach (table, tables) {
+ if (!table->filename)
+ return table;
+ }
+ }
+
+ return NULL;
+}
+
+/**************************************************************************************************/
+
+__attribute__((no_instrument_function))
+const char *
+direct_trace_lookup_symbol( const char *filename, long offset )
+{
+ Symbol *symbol;
+ SymbolTable *table;
+
+ pthread_mutex_lock( &tables_lock );
+
+ table = find_table( filename );
+ if (!table) {
+ table = load_symbols( filename );
+ if (!table) {
+ pthread_mutex_unlock( &tables_lock );
+ return false;
+ }
+
+ direct_list_prepend( &tables, &table->link );
+ }
+
+ pthread_mutex_unlock( &tables_lock );
+
+ symbol = bsearch( &offset, table->symbols, table->num_symbols,
+ sizeof(Symbol), compare_symbols );
+
+ return symbol ? symbol->name : NULL;
+}
+
+__attribute__((no_instrument_function))
+const char *
+direct_trace_lookup_file( void *address, void **ret_base )
+{
+#ifdef DYNAMIC_LINKING
+ Dl_info info;
+
+ if (dladdr( address, &info )) {
+ if (ret_base)
+ *ret_base = info.dli_fbase;
+
+ return info.dli_fname;
+ }
+ else
+#endif
+ {
+ if (ret_base)
+ *ret_base = NULL;
+ }
+
+ return NULL;
+}
+
+__attribute__((no_instrument_function))
+void
+direct_trace_print_stack( DirectTraceBuffer *buffer )
+{
+#ifdef DYNAMIC_LINKING
+ Dl_info info;
+#endif
+ int i;
+ int level;
+
+ if (!direct_config->trace)
+ return;
+
+ if (!buffer)
+ buffer = get_trace_buffer();
+
+ if (buffer->in_trace)
+ return;
+
+ buffer->in_trace = true;
+
+
+ level = buffer->level;
+ if (level > MAX_LEVEL) {
+ D_WARN( "only showing %d of %d items", MAX_LEVEL, level );
+ level = MAX_LEVEL;
+ }
+ else if (level == 0) {
+ buffer->in_trace = false;
+ return;
+ }
+
+ direct_log_lock( NULL );
+
+ if (buffer->name)
+ direct_log_printf( NULL, "(-) [%5d: -STACK- '%s']\n", buffer->tid, buffer->name );
+ else
+ direct_log_printf( NULL, "(-) [%5d: -STACK- ]\n", buffer->tid );
+
+ for (i=level-1; i>=0; i--) {
+ void *fn = buffer->trace[i].addr;
+
+#ifdef DYNAMIC_LINKING
+ if (dladdr( fn, &info )) {
+ if (info.dli_fname) {
+ const char *symbol = NULL;//info.dli_sname;
+
+ if (!symbol) {
+ symbol = direct_trace_lookup_symbol(info.dli_fname, (long)(fn - info.dli_fbase));
+ if (!symbol) {
+ symbol = direct_trace_lookup_symbol(info.dli_fname, (long)(fn));
+ if (!symbol) {
+ if (info.dli_sname)
+ symbol = info.dli_sname;
+ else
+ symbol = "??";
+ }
+ }
+ }
+
+ direct_log_printf( NULL, " #%-2d 0x%08lx in %s () from %s [%p]\n",
+ level - i - 1, (unsigned long) fn, symbol, info.dli_fname, info.dli_fbase );
+ }
+ else if (info.dli_sname) {
+ direct_log_printf( NULL, " #%-2d 0x%08lx in %s ()\n",
+ level - i - 1, (unsigned long) fn, info.dli_sname );
+ }
+ else
+ direct_log_printf( NULL, " #%-2d 0x%08lx in ?? ()\n",
+ level - i - 1, (unsigned long) fn );
+ }
+ else
+#endif
+ {
+ const char *symbol = direct_trace_lookup_symbol(NULL, (long)(fn));
+ direct_log_printf( NULL, " #%-2d 0x%08lx in %s ()\n",
+ level - i - 1, (unsigned long) fn, symbol ? symbol : "??" );
+ }
+ }
+
+ direct_log_printf( NULL, "\n" );
+ direct_log_unlock( NULL );
+
+ buffer->in_trace = false;
+}
+
+__attribute__((no_instrument_function))
+void
+direct_trace_print_stacks( void )
+{
+ int i;
+ DirectTraceBuffer *buffer = get_trace_buffer();
+
+ if (buffer->level)
+ direct_trace_print_stack( buffer );
+
+ pthread_mutex_lock( &buffers_lock );
+
+ for (i=0; i<buffers_num; i++) {
+ if (buffers[i] != buffer && buffers[i]->level)
+ direct_trace_print_stack( buffers[i] );
+ }
+
+ pthread_mutex_unlock( &buffers_lock );
+}
+
+__attribute__((no_instrument_function))
+int
+direct_trace_debug_indent( void )
+{
+ int in;
+ DirectTraceBuffer *buffer = get_trace_buffer();
+ int level = buffer->level - 1;
+
+ if (level < 0)
+ return 0;
+
+ buffer->trace[level--].flags |= TF_DEBUG;
+
+ for (in=0; level>=0; level--) {
+ if (buffer->trace[level].flags & TF_DEBUG)
+ in++;
+ }
+
+ return in;
+}
+
+__attribute__((no_instrument_function))
+DirectTraceBuffer *
+direct_trace_copy_buffer( DirectTraceBuffer *buffer )
+{
+ int level;
+ DirectTraceBuffer *copy;
+
+ if (!buffer)
+ buffer = get_trace_buffer();
+
+ level = buffer->level;
+ if (level > MAX_LEVEL) {
+ D_WARN( "only copying %d of %d items", MAX_LEVEL, level );
+ level = MAX_LEVEL;
+ }
+
+ copy = calloc( 1, sizeof(*buffer) - sizeof(buffer->trace) + sizeof(buffer->trace[0]) * level );
+ if (!copy)
+ return NULL;
+
+ if (buffer->name)
+ copy->name = strdup( buffer->name );
+
+ copy->tid = buffer->tid;
+ copy->level = buffer->level;
+
+ direct_memcpy( copy->trace, buffer->trace, level * sizeof(buffer->trace[0]) );
+
+ return copy;
+}
+
+__attribute__((no_instrument_function))
+void
+direct_trace_free_buffer( DirectTraceBuffer *buffer )
+{
+ if (buffer->name)
+ free( buffer->name );
+
+ free( buffer );
+}
+
+/**************************************************************************************************/
+
+__attribute__((no_instrument_function))
+void
+__cyg_profile_func_enter (void *this_fn,
+ void *call_site)
+{
+ if (direct_config->trace) {
+ DirectTraceBuffer *buffer = get_trace_buffer();
+ int level = buffer->level++;
+ Trace *trace = &buffer->trace[level];
+
+ if (level < MAX_LEVEL) {
+ trace->addr = this_fn;
+ trace->flags = TF_NONE;
+ }
+ }
+}
+
+__attribute__((no_instrument_function))
+void
+__cyg_profile_func_exit (void *this_fn,
+ void *call_site)
+{
+ if (direct_config->trace) {
+ DirectTraceBuffer *buffer = get_trace_buffer();
+
+ if (buffer->level > 0)
+ buffer->level--;
+ }
+}
+
+#else
+
+const char *
+direct_trace_lookup_symbol( const char *filename, long offset )
+{
+ return NULL;
+}
+
+const char *
+direct_trace_lookup_file( void *address, void **ret_base )
+{
+ if (ret_base)
+ *ret_base = NULL;
+
+ return NULL;
+}
+
+void
+direct_trace_print_stack( DirectTraceBuffer *buffer )
+{
+}
+
+void
+direct_trace_print_stacks( void )
+{
+}
+
+int
+direct_trace_debug_indent( void )
+{
+ return 0;
+}
+
+DirectTraceBuffer *
+direct_trace_copy_buffer( DirectTraceBuffer *buffer )
+{
+ return NULL;
+}
+
+void
+direct_trace_free_buffer( DirectTraceBuffer *buffer )
+{
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/trace.h b/Source/DirectFB/lib/direct/trace.h
new file mode 100755
index 0000000..2975522
--- /dev/null
+++ b/Source/DirectFB/lib/direct/trace.h
@@ -0,0 +1,98 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__TRACE_H__
+#define __DIRECT__TRACE_H__
+
+#include <direct/types.h>
+
+/***********************************************************************************************************************
+** Symbols
+*/
+
+/*
+ * Returns filename on success or NULL.
+ *
+ * Stores load address of object in 'ret_base' on success.
+ */
+const char *direct_trace_lookup_file ( void *address,
+ void **ret_base );
+
+/*
+ * Look up a symbol by filename and offset.
+ *
+ * Returns symbol name on success or NULL.
+ */
+const char *direct_trace_lookup_symbol( const char *filename,
+ long offset );
+
+/*
+ * Convenience function combining direct_trace_lookup_file() and direct_trace_lookup_symbol().
+ */
+static inline const char *
+direct_trace_lookup_symbol_at( void *address )
+{
+ void *base;
+ const char *filename;
+
+ filename = direct_trace_lookup_file( address, &base );
+
+ return direct_trace_lookup_symbol( filename, (unsigned long) address - (unsigned long) base );
+}
+
+/***********************************************************************************************************************
+** Stacks
+*/
+
+/*
+ * Print stack in 'buffer' or current if NULL.
+ */
+void direct_trace_print_stack( DirectTraceBuffer *buffer );
+
+/*
+ * Print stack of each known thread.
+ */
+void direct_trace_print_stacks( void );
+
+/*
+ * Returns indent level for debug output.
+ */
+int direct_trace_debug_indent( void );
+
+/*
+ * Create a copy of a stack in 'buffer' or of current if NULL.
+ */
+DirectTraceBuffer *direct_trace_copy_buffer( DirectTraceBuffer *buffer );
+
+/*
+ * Free a (copied) stack buffer.
+ */
+void direct_trace_free_buffer( DirectTraceBuffer *buffer );
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/tree.c b/Source/DirectFB/lib/direct/tree.c
new file mode 100755
index 0000000..38aac17
--- /dev/null
+++ b/Source/DirectFB/lib/direct/tree.c
@@ -0,0 +1,307 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ Balanced binary tree ported from glib-2.0.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <direct/mem.h>
+#include <direct/tree.h>
+
+
+static DirectNode *tree_node_new ( DirectTree *tree,
+ void *key,
+ void *value );
+
+static void tree_node_destroy ( DirectTree *tree,
+ DirectNode *node );
+
+static DirectNode *tree_node_insert ( DirectTree *tree,
+ DirectNode *node,
+ void *key,
+ void *value,
+ int *inserted );
+
+static DirectNode *tree_node_lookup ( DirectNode *node,
+ void *key );
+
+static DirectNode *tree_node_balance ( DirectNode *node );
+
+static DirectNode *tree_node_rotate_left ( DirectNode *node );
+
+static DirectNode *tree_node_rotate_right( DirectNode *node );
+
+
+DirectTree *
+direct_tree_new( void )
+{
+ return D_CALLOC( 1, sizeof (DirectTree) );
+}
+
+void
+direct_tree_destroy( DirectTree *tree )
+{
+ unsigned int i;
+
+ for (i = 0; i < 128; i++) {
+ if (tree->fast_keys[i])
+ D_FREE( tree->fast_keys[i] );
+ }
+
+ tree_node_destroy( tree, tree->root );
+
+ D_FREE( tree );
+}
+
+void
+direct_tree_insert( DirectTree *tree,
+ void *key,
+ void *value )
+{
+ int inserted = 0;
+ unsigned long fast_key = (unsigned long) key;
+
+ if (fast_key < 128)
+ tree->fast_keys[fast_key] = value;
+ else
+ tree->root = tree_node_insert( tree, tree->root, key, value, &inserted );
+}
+
+void *
+direct_tree_lookup( DirectTree *tree,
+ void *key )
+{
+ DirectNode *node;
+ unsigned long fast_key = (unsigned long) key;
+
+ if (fast_key < 128)
+ return tree->fast_keys[fast_key];
+
+ node = tree_node_lookup( tree->root, key );
+
+ return node ? node->value : NULL;
+}
+
+static DirectNode *
+tree_node_new( DirectTree *tree,
+ void *key,
+ void *value )
+{
+ DirectNode *node;
+
+ node = D_MALLOC(sizeof (DirectNode));
+
+ node->balance = 0;
+ node->left = NULL;
+ node->right = NULL;
+ node->key = key;
+ node->value = value;
+
+ return node;
+}
+
+static void
+tree_node_destroy (DirectTree *tree,
+ DirectNode *node)
+{
+ if (node) {
+ tree_node_destroy (tree, node->left);
+ tree_node_destroy (tree, node->right);
+
+ if (node->value)
+ D_FREE(node->value);
+
+ D_FREE(node);
+ }
+}
+
+static DirectNode *
+tree_node_insert (DirectTree *tree,
+ DirectNode *node,
+ void *key,
+ void *value,
+ int *inserted)
+{
+ int cmp;
+ int old_balance;
+
+ if (!node) {
+ *inserted = 1;
+ return tree_node_new (tree, key, value);
+ }
+
+ cmp = key - node->key;
+ if (cmp == 0) {
+ node->value = value;
+ return node;
+ }
+
+ if (cmp < 0) {
+ if (node->left) {
+ old_balance = node->left->balance;
+ node->left = tree_node_insert (tree, node->left,
+ key, value, inserted);
+
+ if ((old_balance != node->left->balance) && node->left->balance)
+ node->balance -= 1;
+ }
+ else {
+ *inserted = 1;
+ node->left = tree_node_new (tree, key, value);
+ node->balance -= 1;
+ }
+ }
+ else if (cmp > 0) {
+ if (node->right) {
+ old_balance = node->right->balance;
+ node->right = tree_node_insert (tree, node->right,
+ key, value, inserted);
+
+ if ((old_balance != node->right->balance) && node->right->balance)
+ node->balance += 1;
+ }
+ else {
+ *inserted = 1;
+ node->right = tree_node_new (tree, key, value);
+ node->balance += 1;
+ }
+ }
+
+ if (*inserted && (node->balance < -1 || node->balance > 1))
+ node = tree_node_balance (node);
+
+ return node;
+}
+
+static DirectNode *
+tree_node_lookup (DirectNode *node,
+ void *key)
+{
+ int cmp;
+
+ if (!node)
+ return NULL;
+
+ cmp = key - node->key;
+ if (cmp == 0)
+ return node;
+
+ if (cmp < 0 && node->left) {
+ return tree_node_lookup (node->left, key);
+ }
+ else if (cmp > 0 && node->right) {
+ return tree_node_lookup (node->right, key);
+ }
+
+ return NULL;
+}
+
+static DirectNode *
+tree_node_balance (DirectNode *node)
+{
+ if (node->balance < -1) {
+ if (node->left->balance > 0)
+ node->left = tree_node_rotate_left (node->left);
+ node = tree_node_rotate_right (node);
+ }
+ else if (node->balance > 1) {
+ if (node->right->balance < 0)
+ node->right = tree_node_rotate_right (node->right);
+ node = tree_node_rotate_left (node);
+ }
+
+ return node;
+}
+
+static DirectNode *
+tree_node_rotate_left (DirectNode *node)
+{
+ DirectNode *right;
+ int a_bal;
+ int b_bal;
+
+ right = node->right;
+
+ node->right = right->left;
+ right->left = node;
+
+ a_bal = node->balance;
+ b_bal = right->balance;
+
+ if (b_bal <= 0) {
+ if (a_bal >= 1)
+ right->balance = b_bal - 1;
+ else
+ right->balance = a_bal + b_bal - 2;
+ node->balance = a_bal - 1;
+ }
+ else {
+ if (a_bal <= b_bal)
+ right->balance = a_bal - 2;
+ else
+ right->balance = b_bal - 1;
+ node->balance = a_bal - b_bal - 1;
+ }
+
+ return right;
+}
+
+static DirectNode *
+tree_node_rotate_right (DirectNode *node)
+{
+ DirectNode *left;
+ int a_bal;
+ int b_bal;
+
+ left = node->left;
+
+ node->left = left->right;
+ left->right = node;
+
+ a_bal = node->balance;
+ b_bal = left->balance;
+
+ if (b_bal <= 0) {
+ if (b_bal > a_bal)
+ left->balance = b_bal + 1;
+ else
+ left->balance = a_bal + 2;
+ node->balance = a_bal - b_bal + 1;
+ }
+ else {
+ if (a_bal <= -1)
+ left->balance = b_bal + 1;
+ else
+ left->balance = a_bal + b_bal + 2;
+ node->balance = a_bal + 1;
+ }
+
+ return left;
+}
diff --git a/Source/DirectFB/lib/direct/tree.h b/Source/DirectFB/lib/direct/tree.h
new file mode 100755
index 0000000..165ed1c
--- /dev/null
+++ b/Source/DirectFB/lib/direct/tree.h
@@ -0,0 +1,67 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ Balanced binary tree ported from glib by Sven Neumann
+ <sven@convergence.de>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__TREE_H__
+#define __DIRECT__TREE_H__
+
+#include <direct/types.h>
+
+
+typedef struct __D_DirectNode DirectNode;
+
+struct __D_DirectTree
+{
+ DirectNode *root;
+ void *fast_keys[128];
+};
+
+struct __D_DirectNode
+{
+ int balance;
+ DirectNode *left;
+ DirectNode *right;
+ void *key;
+ void *value;
+};
+
+
+DirectTree *direct_tree_new ( void );
+
+void direct_tree_destroy( DirectTree *tree );
+
+void direct_tree_insert ( DirectTree *tree,
+ void *key,
+ void *value );
+
+void *direct_tree_lookup ( DirectTree *tree,
+ void *key );
+
+#endif
diff --git a/Source/DirectFB/lib/direct/types.h b/Source/DirectFB/lib/direct/types.h
new file mode 100755
index 0000000..2677e00
--- /dev/null
+++ b/Source/DirectFB/lib/direct/types.h
@@ -0,0 +1,169 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__TYPES_H__
+#define __DIRECT__TYPES_H__
+
+#include <direct/build.h>
+
+/*
+ * Define the bool type by including stdbool.h (preferably)...
+ */
+#if DIRECT_BUILD_STDBOOL
+# include <stdbool.h>
+/*
+ * ...or defining it ourself, if not using C++ or another definition
+ */
+#elif !defined(__cplusplus) && !defined(__bool_true_false_are_defined)
+# warning Fallback definition of bool using u8! Checking for 'flags & 0x100' or higher bits will be false :(
+ typedef u8 bool;
+# ifndef false
+# define false (0)
+# endif
+# ifndef true
+# define true (!false)
+# endif
+#endif /* DIRECT_BUILD_STDBOOL */
+
+
+#ifdef USE_KOS
+
+#include <sys/types.h>
+
+typedef uint8 u8;
+typedef uint16 u16;
+typedef uint32 u32;
+typedef uint64 u64;
+
+typedef sint8 s8;
+typedef sint16 s16;
+typedef sint32 s32;
+typedef sint64 s64;
+
+#else
+
+#include <stdint.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+#endif
+
+
+typedef enum {
+ DR_OK = 0x00000000, /* No error occured. */
+ DR_FAILURE, /* A general or unknown error occured. */
+ DR_INIT, /* A general initialization error occured. */
+ DR_BUG, /* Internal bug or inconsistency has been detected. */
+ DR_DEAD, /* Interface has a zero reference counter (available in debug mode). */
+ DR_UNSUPPORTED, /* The requested operation or an argument is (currently) not supported. */
+ DR_UNIMPLEMENTED, /* The requested operation is not implemented, yet. */
+ DR_ACCESSDENIED, /* Access to the resource is denied. */
+ DR_INVAREA, /* An invalid area has been specified or detected. */
+ DR_INVARG, /* An invalid argument has been specified. */
+ DR_NOLOCALMEMORY, /* There's not enough local system memory. */
+ DR_NOSHAREDMEMORY, /* There's not enough shared system memory. */
+ DR_LOCKED, /* The resource is (already) locked. */
+ DR_BUFFEREMPTY, /* The buffer is empty. */
+ DR_FILENOTFOUND, /* The specified file has not been found. */
+ DR_IO, /* A general I/O error occured. */
+ DR_BUSY, /* The resource or device is busy. */
+ DR_NOIMPL, /* No implementation for this interface or content type has been found. */
+ DR_TIMEOUT, /* The operation timed out. */
+ DR_THIZNULL, /* 'thiz' pointer is NULL. */
+ DR_IDNOTFOUND, /* No resource has been found by the specified id. */
+ DR_DESTROYED, /* The requested object has been destroyed. */
+ DR_FUSION, /* Internal fusion error detected, most likely related to IPC resources. */
+ DR_BUFFERTOOLARGE, /* Buffer is too large. */
+ DR_INTERRUPTED, /* The operation has been interrupted. */
+ DR_NOCONTEXT, /* No context available. */
+ DR_TEMPUNAVAIL, /* Temporarily unavailable. */
+ DR_LIMITEXCEEDED, /* Attempted to exceed limit, i.e. any kind of maximum size, count etc. */
+ DR_NOSUCHMETHOD, /* Requested method is not known. */
+ DR_NOSUCHINSTANCE, /* Requested instance is not known. */
+ DR_ITEMNOTFOUND, /* No such item found. */
+ DR_VERSIONMISMATCH, /* Some versions didn't match. */
+ DR_EOF, /* Reached end of file. */
+ DR_SUSPENDED, /* The requested object is suspended. */
+ DR_INCOMPLETE, /* The operation has been executed, but not completely. */
+ DR_NOCORE /* Core part not available. */
+} DirectResult;
+
+/*
+ * Generate result code base for API 'A','B','C', e.g. 'D','F','B'.
+ */
+#define D_RESULT_TYPE_BASE( a,b,c ) ((((unsigned)(a)&0x7f) * 0x02000000) + \
+ (((unsigned)(b)&0x7f) * 0x00040000) + \
+ (((unsigned)(c)&0x7f) * 0x00000800))
+
+/*
+ * Generate result code maximum for API 'A','B','C', e.g. 'D','F','B'.
+ */
+#define D_RESULT_TYPE_MAX( a,b,c ) (D_RESULT_TYPE_BASE(a,b,c) + 0x7ff)
+
+/*
+ * Check if given result code belongs to API 'A','B','C', e.g. 'D','F','B'.
+ */
+#define D_RESULT_TYPE_IS( code,a,b,c ) ((code) >= D_RESULT_TYPE_BASE(a,b,c) && (code) <= D_RESULT_TYPE_MAX(a,b,c))
+
+
+/*
+ * Return value of enumeration callbacks
+ */
+typedef enum {
+ DENUM_OK = 0x00000000, /* Proceed with enumeration */
+ DENUM_CANCEL = 0x00000001 /* Cancel enumeration */
+} DirectEnumerationResult;
+
+
+typedef u32 unichar;
+
+typedef struct __D_DirectCleanupHandler DirectCleanupHandler;
+typedef struct __D_DirectConfig DirectConfig;
+typedef struct __D_DirectHash DirectHash;
+typedef struct __D_DirectLink DirectLink;
+typedef struct __D_DirectLog DirectLog;
+typedef struct __D_DirectModuleDir DirectModuleDir;
+typedef struct __D_DirectModuleEntry DirectModuleEntry;
+typedef struct __D_DirectSerial DirectSerial;
+typedef struct __D_DirectSignalHandler DirectSignalHandler;
+typedef struct __D_DirectStream DirectStream;
+typedef struct __D_DirectTraceBuffer DirectTraceBuffer;
+typedef struct __D_DirectTree DirectTree;
+typedef struct __D_DirectThread DirectThread;
+typedef struct __D_DirectThreadInitHandler DirectThreadInitHandler;
+
+#endif
+
diff --git a/Source/DirectFB/lib/direct/utf8.c b/Source/DirectFB/lib/direct/utf8.c
new file mode 100755
index 0000000..75896da
--- /dev/null
+++ b/Source/DirectFB/lib/direct/utf8.c
@@ -0,0 +1,36 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ UTF8 routines ported from glib-2.0 and optimized
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/utf8.h>
+
+
+
diff --git a/Source/DirectFB/lib/direct/utf8.h b/Source/DirectFB/lib/direct/utf8.h
new file mode 100755
index 0000000..a073c65
--- /dev/null
+++ b/Source/DirectFB/lib/direct/utf8.h
@@ -0,0 +1,80 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ UTF8 routines ported from glib-2.0 and optimized
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__UTF8_H__
+#define __DIRECT__UTF8_H__
+
+#include <direct/types.h>
+
+
+#define DIRECT_UTF8_SKIP(c) (((u8)(c) < 0xc0) ? 1 : __direct_utf8_skip[(u8)(c)&0x3f])
+
+#define DIRECT_UTF8_GET_CHAR(p) (*(const u8*)(p) < 0xc0 ? \
+ *(const u8*)(p) : __direct_utf8_get_char((const u8*)(p)))
+
+
+/*
+ * Actually the last two fields used to be zero since they indicate an
+ * invalid UTF-8 string. Changed it to 1 to avoid endless looping on
+ * invalid input.
+ */
+static const char __direct_utf8_skip[64] = {
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
+};
+
+static __inline__ unichar __direct_utf8_get_char( const u8 *p )
+{
+ int len;
+ register unichar result = p[0];
+
+ if (result < 0xc0)
+ return result;
+
+ if (result > 0xfd)
+ return (unichar) -1;
+
+ len = __direct_utf8_skip[result & 0x3f];
+
+ result &= 0x7c >> len;
+
+ while (--len) {
+ int c = *(++p);
+
+ if ((c & 0xc0) != 0x80)
+ return (unichar) -1;
+
+ result = (result << 6) | (c & 0x3f);
+ }
+
+ return result;
+}
+
+#endif
diff --git a/Source/DirectFB/lib/direct/util.c b/Source/DirectFB/lib/direct/util.c
new file mode 100755
index 0000000..9e7a03a
--- /dev/null
+++ b/Source/DirectFB/lib/direct/util.c
@@ -0,0 +1,519 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+#include <direct/clock.h>
+
+#ifdef CLOCK_MONOTONIC
+#include <sys/syscall.h>
+#endif
+
+static int no_monotonic_pthread_clock;
+
+/*
+ * translates errno to DirectResult
+ */
+DirectResult
+errno2result( int erno )
+{
+ switch (erno) {
+ case 0:
+ return DR_OK;
+ case ENOENT:
+ return DR_FILENOTFOUND;
+ case EACCES:
+ case EPERM:
+ return DR_ACCESSDENIED;
+ case EBUSY:
+ case EAGAIN:
+ return DR_BUSY;
+ case ECONNREFUSED:
+ return DR_ACCESSDENIED;
+ case ENODEV:
+ case ENXIO:
+#ifdef ENOTSUP
+ /* ENOTSUP is not defined on NetBSD */
+ case ENOTSUP:
+#endif
+ return DR_UNSUPPORTED;
+ }
+
+ return DR_FAILURE;
+}
+
+const char *
+DirectResultString( DirectResult result )
+{
+ if (!D_RESULT_TYPE_IS( result, 0, 0, 0 ))
+ return "UNKNOWN RESULT CODE TYPE!";
+
+ switch (result) {
+ case DR_OK:
+ return "OK";
+ case DR_FAILURE:
+ return "General failure!";
+ case DR_INIT:
+ return "Initialization error!";
+ case DR_BUG:
+ return "Internal bug!";
+ case DR_DEAD:
+ return "Interface was released!";
+ case DR_UNSUPPORTED:
+ return "Not supported!";
+ case DR_UNIMPLEMENTED:
+ return "Not implemented!";
+ case DR_ACCESSDENIED:
+ return "Access denied!";
+ case DR_INVARG:
+ return "Invalid argument!";
+ case DR_NOLOCALMEMORY:
+ return "Out of memory!";
+ case DR_LOCKED:
+ return "Resource is locked!";
+ case DR_BUFFEREMPTY:
+ return "Buffer is empty!";
+ case DR_FILENOTFOUND:
+ return "File not found!";
+ case DR_IO:
+ return "General I/O error!";
+ case DR_NOIMPL:
+ return "No (suitable) implementation found!";
+ case DR_TIMEOUT:
+ return "Operation timed out!";
+ case DR_BUSY:
+ return "Resource is busy!";
+ case DR_THIZNULL:
+ return "'thiz' argument is NULL!";
+ case DR_IDNOTFOUND:
+ return "Requested ID not found!";
+ case DR_INVAREA:
+ return "Invalid area present!";
+ case DR_DESTROYED:
+ return "Resource was destroyed!";
+ case DR_FUSION:
+ return "Fusion IPC error detected!";
+ case DR_BUFFERTOOLARGE:
+ return "Buffer is too large!";
+ case DR_INTERRUPTED:
+ return "Operation has been interrupted!";
+ case DR_NOCONTEXT:
+ return "No context available!";
+ case DR_TEMPUNAVAIL:
+ return "Resource temporarily unavailable!";
+ case DR_LIMITEXCEEDED:
+ return "Limit has been exceeded!";
+ case DR_NOSUCHMETHOD:
+ return "No such (remote) method!";
+ case DR_NOSUCHINSTANCE:
+ return "No such (remote) instance!";
+ case DR_ITEMNOTFOUND:
+ return "Appropriate item not found!";
+ case DR_VERSIONMISMATCH:
+ return "Some versions didn't match!";
+ case DR_NOSHAREDMEMORY:
+ return "Out of shared memory!";
+ case DR_EOF:
+ return "End of file!";
+ case DR_SUSPENDED:
+ return "Object is suspended!";
+ case DR_INCOMPLETE:
+ return "Operation incomplete!";
+ case DR_NOCORE:
+ return "No core (loaded)!";
+ default:
+ break;
+ }
+
+ return "UNKNOWN RESULT CODE!";
+}
+
+int
+direct_safe_dup( int fd )
+{
+ int n = 0;
+ int fc[3];
+
+ while (fd >= 0 && fd <= 2) {
+ fc[n++] = fd;
+ fd = dup (fd);
+ }
+
+ while (n)
+ close (fc[--n]);
+
+ return fd;
+}
+
+int
+direct_try_open( const char *name1, const char *name2, int flags, bool error_msg )
+{
+ int fd;
+
+ fd = open (name1, flags);
+ if (fd >= 0)
+ return direct_safe_dup (fd);
+
+ if (errno != ENOENT) {
+ if (error_msg)
+ D_PERROR( "Direct/Util: opening '%s' failed\n", name1 );
+ return -1;
+ }
+
+ fd = open (name2, flags);
+ if (fd >= 0)
+ return direct_safe_dup (fd);
+
+ if (error_msg) {
+ if (errno == ENOENT)
+ D_PERROR( "Direct/Util: opening '%s' and '%s' failed\n", name1, name2 );
+ else
+ D_PERROR( "Direct/Util: opening '%s' failed\n", name2 );
+ }
+
+ return -1;
+}
+
+void
+direct_trim( char **s )
+{
+ int i;
+ int len = strlen( *s );
+
+ for (i = len-1; i >= 0; i--)
+ if ((*s)[i] <= ' ')
+ (*s)[i] = 0;
+ else
+ break;
+
+ while (**s)
+ if (**s <= ' ')
+ (*s)++;
+ else
+ return;
+}
+
+/*
+ * Utility function to initialize recursive mutexes.
+ */
+int
+direct_util_recursive_pthread_mutex_init( pthread_mutex_t *mutex )
+{
+ int ret;
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init( &attr );
+#if HAVE_DECL_PTHREAD_MUTEX_RECURSIVE
+ pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
+#endif
+ ret = pthread_mutex_init( mutex, &attr );
+ if (ret)
+ D_PERROR( "Direct/Lock: Could not initialize recursive mutex!\n" );
+
+ pthread_mutexattr_destroy( &attr );
+
+ return ret;
+}
+
+/*
+ * Utility function to initialize monotonic condition.
+ */
+int
+direct_util_monotonic_pthread_cond_init( pthread_cond_t *cond )
+{
+#if defined(CLOCK_MONOTONIC) && !defined(DIRECT_BUILD_NO_PTHREAD_CONDATTR)
+ int ret;
+ pthread_condattr_t attr;
+
+ struct timespec dummy;
+ pthread_condattr_init( &attr );
+
+ if(!no_monotonic_pthread_clock) {
+ if((syscall( __NR_clock_getres, CLOCK_MONOTONIC, &dummy ) == 0) &&
+ (pthread_condattr_setclock( &attr, CLOCK_MONOTONIC ) == 0))
+ ;
+ else
+ no_monotonic_pthread_clock = 1;
+ }
+
+ ret = pthread_cond_init( cond, &attr );
+ if (ret)
+ D_PERROR( "Direct/Lock: Could not initialize monotonic condition!\n" );
+
+ pthread_condattr_destroy( &attr );
+
+ return ret;
+#else
+ pthread_cond_init( cond, NULL );
+
+ return 0;
+#endif
+}
+
+/*
+ * Utility function to calibrate timeout for monotonic condition.
+ */
+void
+direct_util_get_monotonic_pthread_timeout( struct timespec *timeout,
+ int seconds,
+ int nano_seconds )
+{
+ struct timeval now;
+
+ if(no_monotonic_pthread_clock)
+ gettimeofday( &now, NULL );
+ else
+ direct_monotonic_gettimeofday( &now );
+
+ timeout->tv_sec = now.tv_sec + seconds;
+ timeout->tv_nsec = (now.tv_usec * 1000) + nano_seconds;
+
+ timeout->tv_sec += timeout->tv_nsec / 1000000000;
+ timeout->tv_nsec %= 1000000000;
+}
+
+/*
+ * Encode/Decode Base-64.
+ */
+char*
+direct_base64_encode( const void *data, int size )
+{
+ static const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/=";
+ const unsigned char *src = (const unsigned char*)data;
+ char *ret;
+ char *buf;
+
+ D_ASSERT( data != NULL );
+
+ buf = ret = D_MALLOC( (size + 2) / 3 * 4 + 1 );
+ if (!ret)
+ return NULL;
+
+ for (; size >= 3; size -= 3) {
+ buf[0] = enc[((src[0] & 0xfc) >> 2)];
+ buf[1] = enc[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)];
+ buf[2] = enc[((src[1] & 0x0f) << 2) | ((src[2] & 0xc0) >> 6)];
+ buf[3] = enc[((src[2] & 0x3f))];
+ buf += 4;
+ src += 3;
+ }
+
+ if (size > 0) {
+ buf[0] = enc[(src[0] & 0xfc) >> 2];
+
+ if (size > 1) {
+ buf[1] = enc[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)];
+ buf[2] = enc[((src[1] & 0x0f) << 2)];
+ } else {
+ buf[1] = enc[(src[0] & 0x03) << 4];
+ buf[2] = '=';
+ }
+
+ buf[3] = '=';
+ buf += 4;
+ }
+
+ *buf = '\0';
+
+ return ret;
+}
+
+void*
+direct_base64_decode( const char *string, int *ret_size )
+{
+ unsigned char dec[256];
+ unsigned char *ret;
+ unsigned char *buf;
+ int len;
+ int i, j;
+
+ D_ASSERT( string != NULL );
+
+ len = strlen( string );
+ buf = ret = D_MALLOC( len * 3 / 4 + 3 );
+ if (!ret)
+ return NULL;
+
+ /* generate decode table */
+ for (i = 0; i < 255; i++)
+ dec[i] = 0x80;
+ for (i = 'A'; i <= 'Z'; i++)
+ dec[i] = 0 + (i - 'A');
+ for (i = 'a'; i <= 'z'; i++)
+ dec[i] = 26 + (i - 'a');
+ for (i = '0'; i <= '9'; i++)
+ dec[i] = 52 + (i - '0');
+ dec['+'] = 62;
+ dec['/'] = 63;
+ dec['='] = 0;
+
+ /* decode */
+ for (j = 0; j < len; j += 4) {
+ unsigned char a[4], b[4];
+
+ for (i = 0; i < 4; i++) {
+ int c = string[i+j];
+ a[i] = c;
+ b[i] = dec[c];
+ }
+
+ *buf++ = (b[0] << 2) | (b[1] >> 4);
+ *buf++ = (b[1] << 4) | (b[2] >> 2);
+ *buf++ = (b[2] << 6) | (b[3] );
+ if (a[2] == '=' || a[3] == '=')
+ break;
+ }
+
+ *buf = '\0';
+
+ if (ret_size)
+ *ret_size = buf - ret;
+
+ return ret;
+}
+
+/*
+ * Compute MD5 sum.
+ */
+static const u8 S[4][4] = {
+ { 7, 12, 17, 22 }, /* Round 1 */
+ { 5, 9, 14, 20 }, /* Round 2 */
+ { 4, 11, 16, 23 }, /* Round 3 */
+ { 6, 10, 15, 21 } /* Round 4 */
+};
+
+static const u32 T[64] = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* Round 3 */
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* Round 4 */
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
+};
+
+static void
+md5_hash( u32 ABCD[4], u32 X[16] )
+{
+ u32 a = ABCD[3];
+ u32 b = ABCD[2];
+ u32 c = ABCD[1];
+ u32 d = ABCD[0];
+ int t;
+ int i;
+
+#ifdef WORDS_BIGENDIAN
+ for (i = 0; i < 16; i++)
+ X[i] = BSWAP32(X[i]);
+#endif
+
+ for (i = 0; i < 64; i++) {
+ t = S[i>>4][i&3];
+ a += T[i];
+ switch (i>>4) {
+ case 0: a += (d ^ (b&(c^d))) + X[ i &15]; break;
+ case 1: a += (c ^ (d&(c^b))) + X[(1+5*i)&15]; break;
+ case 2: a += (b^c^d) + X[(5+3*i)&15]; break;
+ case 3: a += (c^(b|~d)) + X[( 7*i)&15]; break;
+ }
+ a = b + ((a << t) | (a >> (32 - t)));
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ ABCD[0] += d;
+ ABCD[1] += c;
+ ABCD[2] += b;
+ ABCD[3] += a;
+}
+
+void
+direct_md5_sum( void *dst, const void *src, const int len )
+{
+ u8 block[64];
+ u32 ABCD[4];
+ int i, j;
+
+ D_ASSERT( dst != NULL );
+ D_ASSERT( src != NULL );
+
+ ABCD[0] = 0x10325476;
+ ABCD[1] = 0x98badcfe;
+ ABCD[2] = 0xefcdab89;
+ ABCD[3] = 0x67452301;
+
+ for (i = 0, j = 0; i < len; i++) {
+ block[j++] = ((const u8*)src)[i];
+ if (j == 64) {
+ md5_hash( ABCD, (u32*)block );
+ j = 0;
+ }
+ }
+
+ block[j++] = 0x80;
+ memset( &block[j], 0, 64-j );
+
+ if (j > 56) {
+ md5_hash( ABCD, (u32*)block );
+ memset( block, 0, 64 );
+ }
+
+ for (i = 0; i < 8; i++)
+ block[56+i] = ((u64)len << 3) >> (i << 3);
+
+ md5_hash( ABCD, (u32*)block );
+
+ for (i = 0; i < 4; i++)
+#ifdef WORDS_BIGENDIAN
+ ((u32*)dst)[i] = BSWAP32(ABCD[3-i]);
+#else
+ ((u32*)dst)[i] = ABCD[3-i];
+#endif
+}
diff --git a/Source/DirectFB/lib/direct/util.h b/Source/DirectFB/lib/direct/util.h
new file mode 100755
index 0000000..b93359e
--- /dev/null
+++ b/Source/DirectFB/lib/direct/util.h
@@ -0,0 +1,330 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__UTIL_H__
+#define __DIRECT__UTIL_H__
+
+#include <unistd.h>
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#include <sched.h>
+#endif
+
+#include <pthread.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef SIGN
+#define SIGN(x) (((x) < 0) ? -1 : (((x) > 0) ? 1 : 0))
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+#endif
+
+#ifndef CLAMP
+#define CLAMP(x,min,max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x))
+#endif
+
+#ifndef BSWAP16
+#define BSWAP16(x) (((u16)(x)>>8) | ((u16)(x)<<8))
+#endif
+
+#ifndef BSWAP32
+#define BSWAP32(x) ((((u32)(x)>>24) & 0x000000ff) | (((u32)(x)>> 8) & 0x0000ff00) | \
+ (((u32)(x)<< 8) & 0x00ff0000) | (((u32)(x)<<24) & 0xff000000))
+#endif
+
+
+#define D_FLAGS_SET(flags,f) do { (flags) |= (f); } while (0)
+#define D_FLAGS_CLEAR(flags,f) do { (flags) &= ~(f); } while (0)
+#define D_FLAGS_IS_SET(flags,f) (((flags) & (f)) != 0)
+#define D_FLAGS_ARE_SET(flags,f) (((flags) & (f)) == (f))
+#define D_FLAGS_ARE_IN(flags,f) (((flags) & ~(f)) == 0)
+#define D_FLAGS_INVALID(flags,f) (((flags) & ~(f)) != 0)
+
+#define D_FLAGS_ASSERT(flags,f) D_ASSERT( D_FLAGS_ARE_IN(flags,f) )
+
+#define D_ARRAY_SIZE(array) ((int)(sizeof(array) / sizeof((array)[0])))
+
+#define D_UTIL_SWAP(a,b) \
+ do { \
+ const typeof(a) x = (a); (a) = (b); (b) = x; \
+ } while (0)
+
+
+#if __GNUC__ >= 3
+#define D_CONST_FUNC __attribute__((const))
+#else
+#define D_CONST_FUNC
+#endif
+
+
+#define D_BITn32(f) (((f) & 0x00000001) ? 0 : \
+ ((f) & 0x00000002) ? 1 : \
+ ((f) & 0x00000004) ? 2 : \
+ ((f) & 0x00000008) ? 3 : \
+ ((f) & 0x00000010) ? 4 : \
+ ((f) & 0x00000020) ? 5 : \
+ ((f) & 0x00000040) ? 6 : \
+ ((f) & 0x00000080) ? 7 : \
+ ((f) & 0x00000100) ? 8 : \
+ ((f) & 0x00000200) ? 9 : \
+ ((f) & 0x00000400) ? 10 : \
+ ((f) & 0x00000800) ? 11 : \
+ ((f) & 0x00001000) ? 12 : \
+ ((f) & 0x00002000) ? 13 : \
+ ((f) & 0x00004000) ? 14 : \
+ ((f) & 0x00008000) ? 15 : \
+ ((f) & 0x00010000) ? 16 : \
+ ((f) & 0x00020000) ? 17 : \
+ ((f) & 0x00040000) ? 18 : \
+ ((f) & 0x00080000) ? 19 : \
+ ((f) & 0x00100000) ? 20 : \
+ ((f) & 0x00200000) ? 21 : \
+ ((f) & 0x00400000) ? 22 : \
+ ((f) & 0x00800000) ? 23 : \
+ ((f) & 0x01000000) ? 24 : \
+ ((f) & 0x02000000) ? 25 : \
+ ((f) & 0x04000000) ? 26 : \
+ ((f) & 0x08000000) ? 27 : \
+ ((f) & 0x10000000) ? 28 : \
+ ((f) & 0x20000000) ? 29 : \
+ ((f) & 0x40000000) ? 30 : \
+ ((f) & 0x80000000) ? 31 : -1)
+
+
+/*
+ * portable sched_yield() implementation
+ */
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#define direct_sched_yield() sched_yield()
+#else
+#define direct_sched_yield() usleep(1)
+#endif
+
+/*
+ * translates errno to DirectResult
+ */
+DirectResult errno2result( int erno );
+
+const char *DirectResultString( DirectResult result );
+
+/*
+ * duplicates a file descriptor as needed to ensure it's not stdin, stdout, or stderr
+ */
+int direct_safe_dup( int fd );
+
+int direct_try_open( const char *name1, const char *name2, int flags, bool error_msg );
+
+void direct_trim( char **s );
+
+/*
+ * Set a string with a maximum size including the zero termination.
+ *
+ * This acts like a strncpy(d,s,n), but always terminates the string like snprintf(d,n,"%s",s).
+ *
+ * Returns dest or NULL if n is zero.
+ */
+static __inline__ char *
+direct_snputs( char *dest,
+ const char *src,
+ size_t n )
+{
+ char *start = dest;
+
+ D_ASSERT( dest != NULL );
+ D_ASSERT( src != NULL );
+
+ if (!n)
+ return NULL;
+
+ for (; n>1 && *src; n--)
+ *dest++ = *src++;
+
+ *dest = 0;
+
+ return start;
+}
+
+/*
+ * Encode/Decode Base-64 strings.
+ */
+char *direct_base64_encode( const void *data, int size );
+void *direct_base64_decode( const char *string, int *ret_size );
+
+/*
+ * Compute MD5 sum (store 16-bytes long result in "dst").
+ */
+void direct_md5_sum( void *dst, const void *src, const int len );
+
+/*
+ * Slow implementation, but quite fast if only low bits are set.
+ */
+static __inline__ int
+direct_util_count_bits( unsigned int mask )
+{
+ register int ret = 0;
+
+ while (mask) {
+ ret += mask & 1;
+ mask >>= 1;
+ }
+
+ return ret;
+}
+
+/*
+ * Generic alignment routine.
+ */
+static __inline__ int
+direct_util_align( int value,
+ int alignment )
+{
+ if (alignment > 1) {
+ int tail = value % alignment;
+
+ if (tail)
+ value += alignment - tail;
+ }
+
+ return value;
+}
+
+/*
+ * Utility function to initialize recursive mutexes.
+ */
+int direct_util_recursive_pthread_mutex_init( pthread_mutex_t *mutex );
+
+/*
+ * Utility function to calibrate timeout for monotonic condition.
+ */
+void direct_util_get_monotonic_pthread_timeout( struct timespec *timeout,
+ int seconds,
+ int nano_seconds );
+
+/*
+ * Utility function to initialize monotonic condition.
+ */
+int direct_util_monotonic_pthread_cond_init( pthread_cond_t *cond );
+
+/* floor and ceil implementation to get rid of libm */
+
+/*
+ IEEE floor for computers that round to nearest or even.
+
+ 'f' must be between -4194304 and 4194303.
+
+ This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1",
+ but uses some IEEE specific tricks for better speed.
+*/
+static __inline__ int
+D_IFLOOR(float f)
+{
+ int ai, bi;
+ double af, bf;
+
+ af = (3 << 22) + 0.5 + (double)f;
+ bf = (3 << 22) + 0.5 - (double)f;
+
+#if defined(__GNUC__) && defined(__i386__)
+ /*
+ GCC generates an extra fstp/fld without this.
+ */
+ __asm__ __volatile__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
+ __asm__ __volatile__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
+#else
+ {
+ union { int i; float f; } u;
+ u.f = af; ai = u.i;
+ u.f = bf; bi = u.i;
+ }
+#endif
+
+ return (ai - bi) >> 1;
+}
+
+
+/*
+ IEEE ceil for computers that round to nearest or even.
+
+ 'f' must be between -4194304 and 4194303.
+
+ This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1",
+ but uses some IEEE specific tricks for better speed.
+*/
+static __inline__ int
+D_ICEIL(float f)
+{
+ int ai, bi;
+ double af, bf;
+
+ af = (3 << 22) + 0.5 + (double)f;
+ bf = (3 << 22) + 0.5 - (double)f;
+
+#if defined(__GNUC__) && defined(__i386__)
+ /*
+ GCC generates an extra fstp/fld without this.
+ */
+ __asm__ __volatile__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
+ __asm__ __volatile__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
+#else
+ {
+ union { int i; float f; } u;
+ u.f = af; ai = u.i;
+ u.f = bf; bi = u.i;
+ }
+#endif
+
+ return (ai - bi + 1) >> 1;
+}
+
+static __inline__ int
+direct_log2( int val )
+{
+ register int ret = 0;
+
+ while (val >> ++ret);
+
+ if ((1 << --ret) < val)
+ ret++;
+
+ return ret;
+}
+
+
+#endif
diff --git a/Source/DirectFB/lib/fusion/Makefile.am b/Source/DirectFB/lib/fusion/Makefile.am
new file mode 100755
index 0000000..b97afe1
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/Makefile.am
@@ -0,0 +1,100 @@
+## Makefile.am for DirectFB/lib/fusion
+
+SUBDIRS = shm
+
+
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\"
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = fusion.pc
+
+
+# If the old location isn't cleared, builds of external modules fail
+install-exec-local:
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/core/fusion
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/fusion
+
+
+includedir = @INCLUDEDIR@/fusion
+
+include_HEADERS = \
+ arena.h \
+ build.h \
+ call.h \
+ conf.h \
+ fusion.h \
+ fusion_internal.h \
+ hash.h \
+ lock.h \
+ object.h \
+ property.h \
+ protocol.h \
+ reactor.h \
+ ref.h \
+ shmalloc.h \
+ types.h \
+ vector.h
+
+
+lib_LTLIBRARIES = libfusion.la
+
+libfusion_la_SOURCES = \
+ arena.c \
+ call.c \
+ conf.c \
+ fusion.c \
+ hash.c \
+ lock.c \
+ object.c \
+ property.c \
+ reactor.c \
+ ref.c \
+ shmalloc.c \
+ vector.c
+
+libfusion_la_LIBADD = \
+ shm/libfusion_shm.la \
+ ../direct/libdirect.la
+
+libfusion_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ $(DFB_LDFLAGS)
+
+
+#
+## and now rebuild the static version with the *correct* object files
+#
+if BUILD_STATIC
+
+clean-local:
+ rm -f libfusion_fixed.a
+
+all-local: libfusion_fixed.a
+
+libfusion_fixed.a: .libs/libfusion.a
+ rm -f libfusion_fixed.a
+ ${AR} cru libfusion_fixed.a `find . -name "*.o" | grep -v '.libs'`
+ ${RANLIB} libfusion_fixed.a
+ cp -pf libfusion_fixed.a .libs/libfusion.a
+
+.libs/libfusion.a: libfusion.la
+
+else
+
+clean-local:
+
+all-local:
+
+endif
+
+
+include $(top_srcdir)/rules/nmfile.make
diff --git a/Source/DirectFB/lib/fusion/Makefile.in b/Source/DirectFB/lib/fusion/Makefile.in
new file mode 100755
index 0000000..34f267d
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/Makefile.in
@@ -0,0 +1,804 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/build.h.in \
+ $(srcdir)/fusion.pc.in $(top_srcdir)/rules/nmfile.make
+subdir = lib/fusion
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = build.h fusion.pc
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(includedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libfusion_la_DEPENDENCIES = shm/libfusion_shm.la \
+ ../direct/libdirect.la
+am_libfusion_la_OBJECTS = arena.lo call.lo conf.lo fusion.lo hash.lo \
+ lock.lo object.lo property.lo reactor.lo ref.lo shmalloc.lo \
+ vector.lo
+libfusion_la_OBJECTS = $(am_libfusion_la_OBJECTS)
+libfusion_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libfusion_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libfusion_la_SOURCES)
+DIST_SOURCES = $(libfusion_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+pkgconfigDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(pkgconfig_DATA)
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @INCLUDEDIR@/fusion
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = shm
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\"
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = fusion.pc
+include_HEADERS = \
+ arena.h \
+ build.h \
+ call.h \
+ conf.h \
+ fusion.h \
+ fusion_internal.h \
+ hash.h \
+ lock.h \
+ object.h \
+ property.h \
+ protocol.h \
+ reactor.h \
+ ref.h \
+ shmalloc.h \
+ types.h \
+ vector.h
+
+lib_LTLIBRARIES = libfusion.la
+libfusion_la_SOURCES = \
+ arena.c \
+ call.c \
+ conf.c \
+ fusion.c \
+ hash.c \
+ lock.c \
+ object.c \
+ property.c \
+ reactor.c \
+ ref.c \
+ shmalloc.c \
+ vector.c
+
+libfusion_la_LIBADD = \
+ shm/libfusion_shm.la \
+ ../direct/libdirect.la
+
+libfusion_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ $(DFB_LDFLAGS)
+
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@LIBTONM = $(LTLIBRARIES:.la=-$(LT_RELEASE).so.$(LT_BINARY))
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/nmfile.make $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/fusion/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lib/fusion/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+build.h: $(top_builddir)/config.status $(srcdir)/build.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+fusion.pc: $(top_builddir)/config.status $(srcdir)/fusion.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libfusion.la: $(libfusion_la_OBJECTS) $(libfusion_la_DEPENDENCIES)
+ $(libfusion_la_LINK) -rpath $(libdir) $(libfusion_la_OBJECTS) $(libfusion_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arena.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fusion.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/property.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reactor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ref.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shmalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vector.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) all-local
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@BUILD_SHARED_FALSE@install-data-local:
+@ENABLE_TRACE_FALSE@install-data-local:
+clean: clean-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-data-local install-includeHEADERS \
+ install-pkgconfigDATA
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-exec-local install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-pkgconfigDATA
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am all-local check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-local ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-data-local install-dvi install-dvi-am \
+ install-exec install-exec-am install-exec-local install-html \
+ install-html-am install-includeHEADERS install-info \
+ install-info-am install-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-includeHEADERS \
+ uninstall-libLTLIBRARIES uninstall-pkgconfigDATA
+
+
+# If the old location isn't cleared, builds of external modules fail
+install-exec-local:
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/core/fusion
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/fusion
+
+#
+#
+
+@BUILD_STATIC_TRUE@clean-local:
+@BUILD_STATIC_TRUE@ rm -f libfusion_fixed.a
+
+@BUILD_STATIC_TRUE@all-local: libfusion_fixed.a
+
+@BUILD_STATIC_TRUE@libfusion_fixed.a: .libs/libfusion.a
+@BUILD_STATIC_TRUE@ rm -f libfusion_fixed.a
+@BUILD_STATIC_TRUE@ ${AR} cru libfusion_fixed.a `find . -name "*.o" | grep -v '.libs'`
+@BUILD_STATIC_TRUE@ ${RANLIB} libfusion_fixed.a
+@BUILD_STATIC_TRUE@ cp -pf libfusion_fixed.a .libs/libfusion.a
+
+@BUILD_STATIC_TRUE@.libs/libfusion.a: libfusion.la
+
+@BUILD_STATIC_FALSE@clean-local:
+
+@BUILD_STATIC_FALSE@all-local:
+
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@install-data-local:
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ mkdir -p -- "$(DESTDIR)$(libdir)"
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ nm -n ".libs/$(LIBTONM)" > "$(DESTDIR)$(libdir)/nm-n.$(LIBTONM)"
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/lib/fusion/arena.c b/Source/DirectFB/lib/fusion/arena.c
new file mode 100755
index 0000000..9d86dca
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/arena.c
@@ -0,0 +1,566 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <pthread.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+#include <fusion/build.h>
+#include <fusion/types.h>
+#include <fusion/lock.h>
+#include <fusion/hash.h>
+#include <fusion/ref.h>
+#include <fusion/arena.h>
+#include <fusion/shm/shm.h>
+#include <fusion/shmalloc.h>
+
+#include "fusion_internal.h"
+
+
+#if FUSION_BUILD_MULTI
+
+D_DEBUG_DOMAIN( Fusion_Arena, "Fusion/Arena", "Fusion Arena" );
+
+struct __Fusion_FusionArena {
+ DirectLink link;
+
+ int magic;
+
+ FusionWorldShared *shared;
+
+ FusionSkirmish lock;
+ FusionRef ref;
+
+ char *name;
+
+ FusionHash *field_hash;
+};
+
+/**********************************************************************************************************************/
+
+static FusionArena *lock_arena ( FusionWorld *world,
+ const char *name,
+ bool add );
+
+static void unlock_arena( FusionArena *arena );
+
+/**********************************************************************************************************************/
+
+DirectResult
+fusion_arena_enter (FusionWorld *world,
+ const char *name,
+ ArenaEnterFunc initialize,
+ ArenaEnterFunc join,
+ void *ctx,
+ FusionArena **ret_arena,
+ int *ret_error)
+{
+ FusionArena *arena;
+ FusionWorldShared *shared;
+ ArenaEnterFunc func;
+ int error = 0;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_ASSERT( name != NULL );
+ D_ASSERT( initialize != NULL );
+ D_ASSERT( join != NULL );
+ D_ASSERT( ret_arena != NULL );
+
+ D_DEBUG_AT( Fusion_Arena, "%s( '%s' )\n", __FUNCTION__, name );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Lookup arena and lock it. If it doesn't exist create it. */
+ arena = lock_arena( world, name, true );
+ if (!arena)
+ return DR_FAILURE;
+
+ /* Check if we are the first. */
+ if (fusion_ref_zero_trylock( &arena->ref ) == DR_OK) {
+ D_DEBUG ("Fusion/Arena: entering arena '%s' (establishing)\n", name);
+
+ /* Call 'initialize' later. */
+ func = initialize;
+
+ /* Unlock the reference counter. */
+ fusion_ref_unlock( &arena->ref );
+ }
+ else {
+ D_DEBUG ("Fusion/Arena: entering arena '%s' (joining)\n", name);
+
+ fusion_shm_attach_unattached( world );
+
+ /* Call 'join' later. */
+ func = join;
+ }
+
+ /* Increase reference counter. */
+ fusion_ref_up (&arena->ref, false);
+
+ /* Return the arena. */
+ *ret_arena = arena;
+
+ /* Call 'initialize' or 'join'. */
+ error = func (arena, ctx);
+
+ /* Return the return value of the callback. */
+ if (ret_error)
+ *ret_error = error;
+
+ if (error) {
+ fusion_ref_down (&arena->ref, false);
+
+ if (func == initialize) {
+ /* Destroy fields. */
+ fusion_hash_destroy( arena->field_hash );
+
+ /* Destroy reference counter. */
+ fusion_ref_destroy( &arena->ref );
+
+ /* Destroy the arena lock. This has to happen before
+ locking the list. Otherwise a dead lock with lock_arena()
+ below could occur. */
+ fusion_skirmish_destroy( &arena->lock );
+
+ /* Lock the list and remove the arena. */
+ fusion_skirmish_prevail( &shared->arenas_lock );
+ direct_list_remove( &shared->arenas, &arena->link );
+ fusion_skirmish_dismiss( &shared->arenas_lock );
+
+ D_MAGIC_CLEAR( arena );
+
+ /* Free allocated memory. */
+ SHFREE( shared->main_pool, arena->name );
+ SHFREE( shared->main_pool, arena );
+
+ return DR_OK;
+ }
+ }
+
+ /* Unlock the arena. */
+ unlock_arena( arena );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_arena_add_shared_field (FusionArena *arena,
+ const char *name,
+ void *data)
+{
+ DirectResult ret;
+ FusionWorldShared *shared;
+ char *shname;
+
+ D_ASSERT( arena != NULL );
+ D_ASSERT( data != NULL );
+ D_ASSERT( name != NULL );
+
+ D_MAGIC_ASSERT( arena, FusionArena );
+
+ D_DEBUG_AT( Fusion_Arena, "%s( '%s', '%s' -> %p )\n", __FUNCTION__, arena->name, name, data );
+
+ shared = arena->shared;
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Lock the arena. */
+ ret = fusion_skirmish_prevail( &arena->lock );
+ if (ret)
+ return ret;
+
+ /* Give it the requested name. */
+ shname = SHSTRDUP( shared->main_pool, name );
+ if (shname)
+ ret = fusion_hash_replace( arena->field_hash, shname, data, NULL, NULL );
+ else
+ ret = D_OOSHM();
+
+ /* Unlock the arena. */
+ fusion_skirmish_dismiss( &arena->lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_arena_get_shared_field (FusionArena *arena,
+ const char *name,
+ void **data)
+{
+ void *ptr;
+
+ D_ASSERT( arena != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( data != NULL );
+
+ D_MAGIC_ASSERT( arena, FusionArena );
+
+ D_DEBUG_AT( Fusion_Arena, "%s( '%s', '%s' )\n", __FUNCTION__, arena->name, name );
+
+ /* Lock the arena. */
+ if (fusion_skirmish_prevail( &arena->lock ))
+ return DR_FAILURE;
+
+ /* Lookup entry. */
+ ptr = fusion_hash_lookup( arena->field_hash, name );
+
+ D_DEBUG_AT( Fusion_Arena, " -> %p\n", ptr );
+
+ /* Unlock the arena. */
+ fusion_skirmish_dismiss( &arena->lock );
+
+ if (!ptr)
+ return DR_ITEMNOTFOUND;
+
+ *data = ptr;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_arena_exit (FusionArena *arena,
+ ArenaExitFunc shutdown,
+ ArenaExitFunc leave,
+ void *ctx,
+ bool emergency,
+ int *ret_error)
+{
+ int error = 0;
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( arena, FusionArena );
+
+ D_DEBUG_AT( Fusion_Arena, "%s( '%s' )\n", __FUNCTION__, arena->name );
+
+ D_ASSERT( shutdown != NULL );
+
+ shared = arena->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Lock the arena. */
+ if (fusion_skirmish_prevail( &arena->lock ))
+ return DR_FAILURE;
+
+ /* Decrease reference counter. */
+ fusion_ref_down( &arena->ref, false );
+
+ /* If we are the last... */
+ if (fusion_ref_zero_trylock( &arena->ref ) == DR_OK) {
+ /* Deinitialize everything. */
+ error = shutdown( arena, ctx, emergency );
+
+ /* Destroy fields. */
+ fusion_hash_destroy( arena->field_hash );
+
+ /* Destroy reference counter. */
+ fusion_ref_destroy( &arena->ref );
+
+ /* Destroy the arena lock. This has to happen before
+ locking the list. Otherwise a dead lock with lock_arena()
+ below could occur. */
+ fusion_skirmish_destroy( &arena->lock );
+
+ /* Lock the list and remove the arena. */
+ fusion_skirmish_prevail( &shared->arenas_lock );
+ direct_list_remove( &shared->arenas, &arena->link );
+ fusion_skirmish_dismiss( &shared->arenas_lock );
+
+ D_MAGIC_CLEAR( arena );
+
+ /* Free allocated memory. */
+ SHFREE( shared->main_pool, arena->name );
+ SHFREE( shared->main_pool, arena );
+ }
+ else {
+ if (!leave) {
+ fusion_ref_up( &arena->ref, false );
+ fusion_skirmish_dismiss( &arena->lock );
+ return DR_BUSY;
+ }
+
+ /* Simply leave the arena. */
+ error = leave( arena, ctx, emergency );
+
+ /* Unlock the arena. */
+ fusion_skirmish_dismiss( &arena->lock );
+ }
+
+ /* Return the return value of the callback. */
+ if (ret_error)
+ *ret_error = error;
+
+ return DR_OK;
+}
+
+
+/*****************************
+ * File internal functions *
+ *****************************/
+
+static FusionArena *
+create_arena( FusionWorld *world,
+ const char *name )
+{
+ DirectResult ret;
+ char buf[64];
+ FusionArena *arena;
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( name != NULL );
+
+ shared = world->shared;
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ arena = SHCALLOC( shared->main_pool, 1, sizeof(FusionArena) );
+ if (!arena) {
+ D_OOSHM();
+ return NULL;
+ }
+
+ arena->shared = shared;
+
+ snprintf( buf, sizeof(buf), "Arena '%s'", name );
+
+ /* Initialize lock and reference counter. */
+ ret = fusion_skirmish_init( &arena->lock, buf, world );
+ if (ret)
+ goto error;
+
+ ret = fusion_ref_init( &arena->ref, buf, world );
+ if (ret)
+ goto error_ref;
+
+ /* Give it the requested name. */
+ arena->name = SHSTRDUP( shared->main_pool, name );
+ if (!arena->name) {
+ D_OOSHM();
+ goto error_prevail;
+ }
+
+ ret = fusion_hash_create( shared->main_pool, HASH_STRING, HASH_PTR, 7, &arena->field_hash );
+ if (ret)
+ goto error_hash;
+
+ fusion_hash_set_autofree( arena->field_hash, true, false );
+
+ /* Add it to the list. */
+ direct_list_prepend( &shared->arenas, &arena->link );
+
+ /* Lock the newly created arena. */
+ ret = fusion_skirmish_prevail( &arena->lock );
+ if (ret)
+ goto error_prevail;
+
+ D_MAGIC_SET( arena, FusionArena );
+
+ /* Returned locked new arena. */
+ return arena;
+
+
+error_prevail:
+ fusion_hash_destroy( arena->field_hash );
+
+error_hash:
+ if (arena->name)
+ SHFREE( shared->main_pool, arena->name );
+
+ fusion_ref_destroy( &arena->ref );
+
+error_ref:
+ fusion_skirmish_destroy( &arena->lock );
+
+error:
+ SHFREE( shared->main_pool, arena );
+
+ return NULL;
+}
+
+static FusionArena *
+lock_arena( FusionWorld *world,
+ const char *name,
+ bool add )
+{
+ FusionArena *arena;
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( name != NULL );
+
+ shared = world->shared;
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Lock the list. */
+ if (fusion_skirmish_prevail( &shared->arenas_lock ))
+ return NULL;
+
+ /* For each exisiting arena... */
+ direct_list_foreach (arena, shared->arenas) {
+ /* Lock the arena.
+ This would fail if the arena has been
+ destroyed while waiting for the lock. */
+ if (fusion_skirmish_prevail( &arena->lock ))
+ continue;
+
+ D_MAGIC_ASSERT( arena, FusionArena );
+
+ /* Check if the name matches. */
+ if (! strcmp( arena->name, name )) {
+ /* Check for an orphaned arena. */
+ if (fusion_ref_zero_trylock( &arena->ref ) == DR_OK) {
+ D_ERROR( "Fusion/Arena: orphaned arena '%s'!\n", name );
+
+ fusion_ref_unlock( &arena->ref );
+
+// arena = NULL;
+ }
+
+ /* Unlock the list. */
+ fusion_skirmish_dismiss( &shared->arenas_lock );
+
+ /* Return locked arena. */
+ return arena;
+ }
+
+ /* Unlock mismatched arena. */
+ fusion_skirmish_dismiss( &arena->lock );
+ }
+
+ /* If no arena name matched, create a new arena
+ before unlocking the list again. */
+ arena = add ? create_arena( world, name ) : NULL;
+
+ /* Unlock the list. */
+ fusion_skirmish_dismiss( &shared->arenas_lock );
+
+ return arena;
+}
+
+static void
+unlock_arena( FusionArena *arena )
+{
+ D_ASSERT( arena != NULL );
+
+ D_MAGIC_ASSERT( arena, FusionArena );
+
+ /* Unlock the arena. */
+ fusion_skirmish_dismiss( &arena->lock );
+}
+
+#else
+
+DirectResult
+fusion_arena_enter (FusionWorld *world,
+ const char *name,
+ ArenaEnterFunc initialize,
+ ArenaEnterFunc join,
+ void *ctx,
+ FusionArena **ret_arena,
+ int *ret_error)
+{
+ int error;
+
+ D_ASSERT( name != NULL );
+ D_ASSERT( initialize != NULL );
+ D_ASSERT( join != NULL );
+ D_ASSERT( ret_arena != NULL );
+
+ /* Always call 'initialize'. */
+ error = initialize (NULL, ctx);
+
+ /* Return the return value of the callback. */
+ if (ret_error)
+ *ret_error = error;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_arena_add_shared_field (FusionArena *arena,
+ const char *name,
+ void *data)
+{
+ D_ASSERT( data != NULL );
+ D_ASSERT( name != NULL );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_arena_get_shared_field (FusionArena *arena,
+ const char *name,
+ void **data)
+{
+ D_ASSERT( data != NULL );
+ D_ASSERT( name != NULL );
+
+ D_BUG( "should not call this in fake mode" );
+
+ /* No field by that name has been found. */
+ return DR_ITEMNOTFOUND;
+}
+
+DirectResult
+fusion_arena_exit (FusionArena *arena,
+ ArenaExitFunc shutdown,
+ ArenaExitFunc leave,
+ void *ctx,
+ bool emergency,
+ int *ret_error)
+{
+ int error = 0;
+
+ D_ASSERT( shutdown != NULL );
+
+ /* Deinitialize everything. */
+ error = shutdown( arena, ctx, emergency );
+
+ /* Return the return value of the callback. */
+ if (ret_error)
+ *ret_error = error;
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/arena.h b/Source/DirectFB/lib/fusion/arena.h
new file mode 100755
index 0000000..d11d134
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/arena.h
@@ -0,0 +1,62 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__ARENA_H__
+#define __FUSION__ARENA_H__
+
+#include <fusion/types.h>
+
+typedef int (*ArenaEnterFunc) (FusionArena *arena, void *ctx);
+typedef int (*ArenaExitFunc) (FusionArena *arena, void *ctx, bool emergency);
+
+
+DirectResult fusion_arena_enter (FusionWorld *world,
+ const char *name,
+ ArenaEnterFunc initialize,
+ ArenaEnterFunc join,
+ void *ctx,
+ FusionArena **ret_arena,
+ int *ret_error);
+
+DirectResult fusion_arena_add_shared_field (FusionArena *arena,
+ const char *name,
+ void *data);
+
+DirectResult fusion_arena_get_shared_field (FusionArena *arena,
+ const char *name,
+ void **data);
+
+DirectResult fusion_arena_exit (FusionArena *arena,
+ ArenaExitFunc shutdown,
+ ArenaExitFunc leave,
+ void *ctx,
+ bool emergency,
+ int *ret_error);
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/build.h.in b/Source/DirectFB/lib/fusion/build.h.in
new file mode 100755
index 0000000..74b4128
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/build.h.in
@@ -0,0 +1,36 @@
+/*
+ (c) Copyright 2000-2002 convergence integrated media GmbH.
+ (c) Copyright 2002-2004 convergence GmbH.
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org> and
+ Ville Syrjälä <syrjala@sci.fi>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__BUILD_H__
+#define __FUSION__BUILD_H__
+
+#define FUSION_BUILD_MULTI (@FUSION_BUILD_MULTI@)
+#define FUSION_BUILD_KERNEL (@FUSION_BUILD_KERNEL@)
+#define FUSION_MESSAGE_SIZE (@FUSION_MESSAGE_SIZE@)
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/call.c b/Source/DirectFB/lib/fusion/call.c
new file mode 100755
index 0000000..71ce5e5
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/call.c
@@ -0,0 +1,581 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <fusion/build.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+
+#include <fusion/types.h>
+#include <fusion/call.h>
+#include <fusion/conf.h>
+
+#include "fusion_internal.h"
+
+
+D_DEBUG_DOMAIN( Fusion_Call, "Fusion/Call", "Fusion Call" );
+
+
+#if FUSION_BUILD_MULTI
+
+#if FUSION_BUILD_KERNEL
+
+DirectResult
+fusion_call_init (FusionCall *call,
+ FusionCallHandler handler,
+ void *ctx,
+ const FusionWorld *world)
+{
+ FusionCallNew call_new;
+
+ D_DEBUG_AT( Fusion_Call, "%s( %p, %p <%s>, %p, %p )\n", __FUNCTION__, call, handler,
+ direct_trace_lookup_symbol_at( handler ), ctx, world );
+
+ D_ASSERT( call != NULL );
+ D_ASSERT( handler != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+
+ /* Called from others. */
+ call_new.handler = handler;
+ call_new.ctx = ctx;
+
+ while (ioctl( world->fusion_fd, FUSION_CALL_NEW, &call_new )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_CALL_NEW");
+
+ return DR_FAILURE;
+ }
+
+ memset( call, 0, sizeof(FusionCall) );
+
+ /* Store handler, called directly when called by ourself. */
+ call->handler = handler;
+ call->ctx = ctx;
+
+ /* Store call and own fusion id. */
+ call->call_id = call_new.call_id;
+ call->fusion_id = fusion_id( world );
+
+ /* Keep back pointer to shared world data. */
+ call->shared = world->shared;
+
+ D_DEBUG_AT( Fusion_Call, " -> call id %d\n", call->call_id );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_call_execute (FusionCall *call,
+ FusionCallExecFlags flags,
+ int call_arg,
+ void *call_ptr,
+ int *ret_val)
+{
+ D_DEBUG_AT( Fusion_Call, "%s( %p, 0x%x, %d, %p )\n", __FUNCTION__, call, flags, call_arg, call_ptr );
+
+ D_ASSERT( call != NULL );
+
+ if (!call->handler)
+ return DR_DESTROYED;
+
+ D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) );
+
+ if (!(flags & FCEF_NODIRECT) && call->fusion_id == _fusion_id( call->shared )) {
+ int ret;
+ FusionCallHandlerResult result;
+
+ result = call->handler( _fusion_id( call->shared ), call_arg, call_ptr, call->ctx, 0, &ret );
+
+ if (result != FCHR_RETURN)
+ D_WARN( "local call handler returned FCHR_RETAIN, need FCEF_NODIRECT" );
+
+ if (ret_val)
+ *ret_val = ret;
+ }
+ else {
+ FusionCallExecute execute;
+
+ execute.call_id = call->call_id;
+ execute.call_arg = call_arg;
+ execute.call_ptr = call_ptr;
+ execute.flags = flags;
+
+ while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_EXECUTE, &execute )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+// D_ERROR ("Fusion/Call: invalid call\n");
+ return DR_INVARG;
+ case EIDRM:
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_CALL_EXECUTE");
+
+ return DR_FAILURE;
+ }
+
+ if (ret_val)
+ *ret_val = execute.ret_val;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_call_return( FusionCall *call,
+ unsigned int serial,
+ int val )
+{
+ FusionCallReturn call_ret;
+
+ D_DEBUG_AT( Fusion_Call, "%s( %p, %u, %d )\n", __FUNCTION__, call, serial, val );
+
+ D_ASSERT( call != NULL );
+
+ D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) );
+
+ D_ASSUME( serial != 0 );
+ if (!serial)
+ return DR_UNSUPPORTED;
+
+ call_ret.call_id = call->call_id;
+ call_ret.val = val;
+ call_ret.serial = serial;
+
+ while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_RETURN, &call_ret)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EIDRM:
+ D_WARN( "caller withdrawn (signal?)" );
+ return DR_NOCONTEXT;
+ case EINVAL:
+ D_ERROR( "Fusion/Call: invalid call\n" );
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_CALL_RETURN");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_call_destroy (FusionCall *call)
+{
+ D_DEBUG_AT( Fusion_Call, "%s( %p )\n", __FUNCTION__, call );
+
+ D_ASSERT( call != NULL );
+ D_ASSERT( call->handler != NULL );
+
+ D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) );
+
+ while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_DESTROY, &call->call_id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Call: invalid call\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_CALL_DESTROY");
+
+ return DR_FAILURE;
+ }
+
+ call->handler = NULL;
+
+ return DR_OK;
+}
+
+void
+_fusion_call_process( FusionWorld *world, int call_id, FusionCallMessage *msg )
+{
+ FusionCallHandler call_handler;
+ FusionCallReturn call_ret;
+ FusionCallHandlerResult result;
+
+ D_DEBUG_AT( Fusion_Call, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( msg != NULL );
+
+ call_handler = msg->handler;
+
+ D_ASSERT( call_handler != NULL );
+
+ D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call_handler ) );
+
+ call_ret.val = 0;
+
+ result = call_handler( msg->caller, msg->call_arg, msg->call_ptr, msg->ctx, msg->serial, &call_ret.val );
+
+ switch (result) {
+ case FCHR_RETURN:
+ if (msg->serial) {
+ call_ret.serial = msg->serial;
+ call_ret.call_id = call_id;
+
+ while (ioctl (world->fusion_fd, FUSION_CALL_RETURN, &call_ret)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EIDRM:
+ D_WARN( "caller withdrawn (signal?)" );
+ return;
+ case EINVAL:
+ D_ERROR( "Fusion/Call: invalid call\n" );
+ return;
+ default:
+ D_PERROR( "FUSION_CALL_RETURN" );
+ return;
+ }
+ }
+ }
+ break;
+
+ case FCHR_RETAIN:
+ break;
+
+ default:
+ D_BUG( "unknown result %d from call handler", result );
+ }
+}
+
+#else /* FUSION_BUILD_KERNEL */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+
+DirectResult
+fusion_call_init (FusionCall *call,
+ FusionCallHandler handler,
+ void *ctx,
+ const FusionWorld *world)
+{
+ D_ASSERT( call != NULL );
+ D_ASSERT( handler != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+
+ memset( call, 0, sizeof(FusionCall) );
+
+ call->call_id = ++world->shared->call_ids;
+
+ /* Store handler, called directly when called by ourself. */
+ call->handler = handler;
+ call->ctx = ctx;
+
+ /* Store own fusion id. */
+ call->fusion_id = fusion_id( world );
+
+ /* Keep back pointer to shared world data. */
+ call->shared = world->shared;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_call_execute (FusionCall *call,
+ FusionCallExecFlags flags,
+ int call_arg,
+ void *call_ptr,
+ int *ret_val)
+{
+ DirectResult ret = DR_OK;
+ FusionWorld *world;
+ FusionCallMessage msg;
+ struct sockaddr_un addr;
+
+ D_ASSERT( call != NULL );
+
+ if (!call->handler)
+ return DR_DESTROYED;
+
+ if (!(flags & FCEF_NODIRECT) && call->fusion_id == _fusion_id( call->shared )) {
+ int ret;
+ FusionCallHandlerResult result;
+
+ result = call->handler( _fusion_id( call->shared ), call_arg, call_ptr, call->ctx, 0, &ret );
+
+ if (result != FCHR_RETURN)
+ D_WARN( "local call handler returned FCHR_RETAIN, need FCEF_NODIRECT" );
+
+ if (ret_val)
+ *ret_val = ret;
+
+ return DR_OK;
+ }
+
+ world = _fusion_world( call->shared );
+
+ msg.type = FMT_CALL;
+ msg.caller = world->fusion_id;
+ msg.call_id = call->call_id;
+ msg.call_arg = call_arg;
+ msg.call_ptr = call_ptr;
+ msg.handler = call->handler;
+ msg.ctx = call->ctx;
+ msg.flags = flags;
+
+ if (flags & FCEF_ONEWAY) {
+ /* Invalidate serial. */
+ msg.serial = -1;
+
+ /* Send message. */
+ addr.sun_family = AF_UNIX;
+ snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/%lx", call->shared->world_index, call->fusion_id );
+
+ ret = _fusion_send_message( world->fusion_fd, &msg, sizeof(msg), &addr );
+ }
+ else {
+ int fd;
+ socklen_t len;
+ int err;
+
+ fd = socket( PF_LOCAL, SOCK_RAW, 0 );
+ if (fd < 0) {
+ D_PERROR( "Fusion/Call: Error creating local socket!\n" ) ;
+ return DR_IO;
+ }
+
+ /* Set close-on-exec flag. */
+ fcntl( fd, F_SETFD, FD_CLOEXEC );
+
+ addr.sun_family = AF_UNIX;
+ len = snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/call.%x.", fusion_world_index( world ), call->call_id );
+
+ /* Generate call serial (socket address is based on it). */
+ for (msg.serial = 0; msg.serial <= 0xffffff; msg.serial++) {
+ snprintf( addr.sun_path+len, sizeof(addr.sun_path)-len, "%x", msg.serial );
+ err = bind( fd, (struct sockaddr*)&addr, sizeof(addr) );
+ if (err == 0) {
+ chmod( addr.sun_path, 0660 );
+ /* Change group, if requested. */
+ if (fusion_config->shmfile_gid != (gid_t)-1)
+ chown( addr.sun_path, -1, fusion_config->shmfile_gid );
+ break;
+ }
+ }
+
+ if (err < 0) {
+ D_PERROR( "Fusion/Call: Error binding local socket!\n" );
+ close( fd );
+ return DR_IO;
+ }
+
+ /* Send message. */
+ snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/%lx", call->shared->world_index, call->fusion_id );
+
+ ret = _fusion_send_message( fd, &msg, sizeof(msg), &addr );
+ if (ret == DR_OK) {
+ FusionCallReturn callret;
+ /* Wait for reply. */
+ ret = _fusion_recv_message( fd, &callret, sizeof(callret), NULL );
+ if (ret == DR_OK) {
+ if (ret_val)
+ *ret_val = callret.val;
+ }
+ }
+
+ len = sizeof(addr);
+ if (getsockname( fd, (struct sockaddr*)&addr, &len ) == 0)
+ unlink( addr.sun_path );
+ close( fd );
+ }
+
+ return ret;
+}
+
+DirectResult
+fusion_call_return( FusionCall *call,
+ unsigned int serial,
+ int val )
+{
+ struct sockaddr_un addr;
+ FusionCallReturn callret;
+
+ D_ASSERT( call != NULL );
+
+ addr.sun_family = AF_UNIX;
+ snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/call.%x.%x", call->shared->world_index, call->call_id, serial );
+
+ callret.type = FMT_CALLRET;
+ callret.val = val;
+
+ return _fusion_send_message( _fusion_fd( call->shared ), &callret, sizeof(callret), &addr );
+}
+
+DirectResult
+fusion_call_destroy (FusionCall *call)
+{
+ D_ASSERT( call != NULL );
+ D_ASSERT( call->handler != NULL );
+
+ call->handler = NULL;
+
+ return DR_OK;
+}
+
+void
+_fusion_call_process( FusionWorld *world, int call_id, FusionCallMessage *msg )
+{
+ FusionCallHandler call_handler;
+ FusionCallHandlerResult result;
+ FusionCallReturn callret;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( msg != NULL );
+
+ call_handler = msg->handler;
+
+ D_ASSERT( call_handler != NULL );
+
+ callret.type = FMT_CALLRET;
+ callret.val = 0;
+
+ result = call_handler( msg->caller, msg->call_arg, msg->call_ptr, msg->ctx, msg->serial, &callret.val );
+ switch (result) {
+ case FCHR_RETURN:
+ if (!(msg->flags & FCEF_ONEWAY)) {
+ struct sockaddr_un addr;
+
+ addr.sun_family = AF_UNIX;
+ snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/call.%x.%x", fusion_world_index( world ), call_id, msg->serial );
+
+ if (_fusion_send_message( world->fusion_fd, &callret, sizeof(callret), &addr ))
+ D_ERROR( "Fusion/Call: Couldn't send call return (serial: 0x%08x)!\n", msg->serial );
+ }
+ break;
+
+ case FCHR_RETAIN:
+ break;
+
+ default:
+ D_BUG( "unknown result %d from call handler", result );
+ break;
+ }
+}
+
+#endif /* FUSION_BUILD_KERNEL */
+
+#else /* FUSION_BUILD_MULTI */
+
+DirectResult
+fusion_call_init (FusionCall *call,
+ FusionCallHandler handler,
+ void *ctx,
+ const FusionWorld *world)
+{
+ D_ASSERT( call != NULL );
+ D_ASSERT( call->handler == NULL );
+ D_ASSERT( handler != NULL );
+
+ /* Called locally. */
+ call->handler = handler;
+ call->ctx = ctx;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_call_execute (FusionCall *call,
+ FusionCallExecFlags flags,
+ int call_arg,
+ void *call_ptr,
+ int *ret_val)
+{
+ FusionCallHandlerResult ret;
+ int val = 0;
+
+ D_ASSERT( call != NULL );
+
+ if (!call->handler)
+ return DR_DESTROYED;
+
+ ret = call->handler( 1, call_arg, call_ptr, call->ctx, 0, &val );
+ if (ret != FCHR_RETURN)
+ D_WARN( "only FCHR_RETURN supported in single app core at the moment" );
+
+ if (ret_val)
+ *ret_val = val;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_call_return( FusionCall *call,
+ unsigned int serial,
+ int val )
+{
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_call_destroy (FusionCall *call)
+{
+ D_ASSERT( call != NULL );
+ D_ASSERT( call->handler != NULL );
+
+ call->handler = NULL;
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/call.h b/Source/DirectFB/lib/fusion/call.h
new file mode 100755
index 0000000..e513696
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/call.h
@@ -0,0 +1,74 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__CALL_H__
+#define __FUSION__CALL_H__
+
+#include <fusion/types.h>
+
+typedef enum {
+ FCHR_RETURN,
+ FCHR_RETAIN
+} FusionCallHandlerResult;
+
+typedef FusionCallHandlerResult (*FusionCallHandler) (int caller, /* fusion id of the caller */
+ int call_arg, /* optional call parameter */
+ void *call_ptr, /* optional call parameter */
+ void *ctx, /* optional handler context */
+ unsigned int serial,
+ int *ret_val );
+
+typedef struct {
+ FusionWorldShared *shared;
+ int call_id;
+ FusionID fusion_id;
+ FusionCallHandler handler;
+ void *ctx;
+} FusionCall;
+
+
+DirectResult fusion_call_init ( FusionCall *call,
+ FusionCallHandler handler,
+ void *ctx,
+ const FusionWorld *world );
+
+DirectResult fusion_call_execute( FusionCall *call,
+ FusionCallExecFlags flags,
+ int call_arg,
+ void *call_ptr,
+ int *ret_val );
+
+DirectResult fusion_call_return ( FusionCall *call,
+ unsigned int serial,
+ int val );
+
+DirectResult fusion_call_destroy( FusionCall *call );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/conf.c b/Source/DirectFB/lib/fusion/conf.c
new file mode 100755
index 0000000..017364f
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/conf.c
@@ -0,0 +1,113 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stddef.h>
+#include <string.h>
+#include <grp.h>
+
+#include <direct/conf.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+#include <fusion/conf.h>
+
+
+static FusionConfig config = {
+ .tmpfs = NULL,
+ .shmfile_gid = -1,
+};
+
+FusionConfig *fusion_config = &config;
+const char *fusion_config_usage =
+ "libfusion options:\n"
+ " force-slave Always enter as a slave, waiting for the master, if not there\n"
+ " tmpfs=<directory> Location of shared memory file\n"
+ " shmfile-group=<groupname> Group that owns shared memory files\n"
+ " [no-]debugshm Enable shared memory allocation tracking\n"
+ " [no-]madv-remove Enable usage of MADV_REMOVE (default = auto)\n"
+ "\n";
+
+/**********************************************************************************************************************/
+
+DirectResult
+fusion_config_set( const char *name, const char *value )
+{
+ if (strcmp (name, "tmpfs" ) == 0) {
+ if (value) {
+ if (fusion_config->tmpfs)
+ D_FREE( fusion_config->tmpfs );
+ fusion_config->tmpfs = D_STRDUP( value );
+ }
+ else {
+ D_ERROR("Fusion/Config 'tmpfs': No directory specified!\n");
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "shmfile-group" ) == 0) {
+ if (value) {
+ struct group *group_info;
+
+ group_info = getgrnam( value );
+ if (group_info)
+ fusion_config->shmfile_gid = group_info->gr_gid;
+ else
+ D_PERROR("Fusion/Config 'shmfile-group': Group '%s' not found!\n", value);
+ }
+ else {
+ D_ERROR("Fusion/Config 'shmfile-group': No file group name specified!\n");
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "force-slave" ) == 0) {
+ fusion_config->force_slave = true;
+ } else
+ if (strcmp (name, "no-force-slave" ) == 0) {
+ fusion_config->force_slave = false;
+ } else
+ if (strcmp (name, "debugshm" ) == 0) {
+ fusion_config->debugshm = true;
+ } else
+ if (strcmp (name, "no-debugshm" ) == 0) {
+ fusion_config->debugshm = false;
+ } else
+ if (strcmp (name, "madv-remove" ) == 0) {
+ fusion_config->madv_remove = true;
+ fusion_config->madv_remove_force = true;
+ } else
+ if (strcmp (name, "no-madv-remove" ) == 0) {
+ fusion_config->madv_remove = false;
+ fusion_config->madv_remove_force = true;
+ } else
+ if (direct_config_set( name, value ))
+ return DR_UNSUPPORTED;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/fusion/conf.h b/Source/DirectFB/lib/fusion/conf.h
new file mode 100755
index 0000000..0cdf9a2
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/conf.h
@@ -0,0 +1,55 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__CONF_H__
+#define __FUSION__CONF_H__
+
+
+#include <fusion/types.h>
+
+struct __Fusion_FusionConfig {
+ char *tmpfs; /* location of shm file */
+
+ bool debugshm;
+ bool madv_remove;
+ bool madv_remove_force;
+ bool force_slave;
+
+ gid_t shmfile_gid; /* group that owns shm file */
+};
+
+extern FusionConfig *fusion_config;
+
+extern const char *fusion_config_usage;
+
+
+DirectResult fusion_config_set( const char *name, const char *value );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/fusion.c b/Source/DirectFB/lib/fusion/fusion.c
new file mode 100755
index 0000000..2812f20
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/fusion.c
@@ -0,0 +1,2658 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/direct.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/signals.h>
+#include <direct/thread.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+#include <fusion/build.h>
+#include <fusion/conf.h>
+#include <fusion/types.h>
+
+#include "fusion_internal.h"
+
+#include <fusion/shmalloc.h>
+
+#include <fusion/shm/shm.h>
+
+
+#if FUSION_BUILD_MULTI
+
+D_DEBUG_DOMAIN( Fusion_Main, "Fusion/Main", "Fusion - High level IPC" );
+D_DEBUG_DOMAIN( Fusion_Main_Dispatch, "Fusion/Main/Dispatch", "Fusion - High level IPC Dispatch" );
+
+/**********************************************************************************************************************/
+
+static void *fusion_dispatch_loop ( DirectThread *thread,
+ void *arg );
+
+/**********************************************************************************************************************/
+
+static void fusion_fork_handler_prepare( void );
+static void fusion_fork_handler_parent( void );
+static void fusion_fork_handler_child( void );
+
+/**********************************************************************************************************************/
+
+static FusionWorld *fusion_worlds[FUSION_MAX_WORLDS];
+static pthread_mutex_t fusion_worlds_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_once_t fusion_init_once = PTHREAD_ONCE_INIT;
+
+/**********************************************************************************************************************/
+
+int
+_fusion_fd( const FusionWorldShared *shared )
+{
+ int index;
+ FusionWorld *world;
+
+// D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ index = shared->world_index;
+
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < FUSION_MAX_WORLDS );
+
+ world = fusion_worlds[index];
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world->fusion_fd;
+}
+
+FusionID
+_fusion_id( const FusionWorldShared *shared )
+{
+ int index;
+ FusionWorld *world;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ index = shared->world_index;
+
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < FUSION_MAX_WORLDS );
+
+ world = fusion_worlds[index];
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world->fusion_id;
+}
+
+FusionWorld *
+_fusion_world( const FusionWorldShared *shared )
+{
+ int index;
+ FusionWorld *world;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ index = shared->world_index;
+
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < FUSION_MAX_WORLDS );
+
+ world = fusion_worlds[index];
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world;
+}
+
+/**********************************************************************************************************************/
+
+static void
+init_once( void )
+{
+ struct utsname uts;
+ int i, j, k, l;
+
+ pthread_atfork( fusion_fork_handler_prepare, fusion_fork_handler_parent, fusion_fork_handler_child );
+
+ if (uname( &uts ) < 0) {
+ D_PERROR( "Fusion/Init: uname() failed!\n" );
+ return;
+ }
+
+#if !FUSION_BUILD_KERNEL
+ D_INFO( "Fusion/Init: "
+ "Builtin Implementation is still experimental! Crash/Deadlocks might occur!\n" );
+#endif
+
+ if (fusion_config->madv_remove_force) {
+ if (fusion_config->madv_remove)
+ D_INFO( "Fusion/SHM: Using MADV_REMOVE (forced)\n" );
+ else
+ D_INFO( "Fusion/SHM: Not using MADV_REMOVE (forced)!\n" );
+ }
+ else {
+ switch (sscanf( uts.release, "%d.%d.%d.%d", &i, &j, &k, &l )) {
+ case 3:
+ l = 0;
+ case 4:
+ if (((i << 24) | (j << 16) | (k << 8) | l) >= 0x02061302)
+ fusion_config->madv_remove = true;
+ break;
+
+ default:
+ D_WARN( "could not parse kernel version '%s'", uts.release );
+ }
+
+ if (fusion_config->madv_remove)
+ D_INFO( "Fusion/SHM: Using MADV_REMOVE (%d.%d.%d.%d >= 2.6.19.2)\n", i, j, k, l );
+ else
+ D_INFO( "Fusion/SHM: NOT using MADV_REMOVE (%d.%d.%d.%d < 2.6.19.2)! [0x%08x]\n",
+ i, j, k, l, (i << 24) | (j << 16) | (k << 8) | l );
+ }
+}
+
+/**********************************************************************************************************************/
+
+#if FUSION_BUILD_KERNEL
+
+static void
+fusion_world_fork( FusionWorld *world )
+{
+ int fd;
+ char buf1[20];
+ char buf2[20];
+ FusionEnter enter;
+ FusionFork fork;
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ snprintf( buf1, sizeof(buf1), "/dev/fusion%d", shared->world_index );
+ snprintf( buf2, sizeof(buf2), "/dev/fusion/%d", shared->world_index );
+
+ /* Open Fusion Kernel Device. */
+ fd = direct_try_open( buf1, buf2, O_RDWR | O_NONBLOCK, true );
+ if (fd < 0) {
+ D_PERROR( "Fusion/Main: Reopening fusion device (world %d) failed!\n", shared->world_index );
+ raise(5);
+ }
+
+ /* Drop "identity" when running another program. */
+ if (fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0)
+ D_PERROR( "Fusion/Init: Setting FD_CLOEXEC flag failed!\n" );
+
+ /* Fill enter information. */
+ enter.api.major = FUSION_API_MAJOR_REQUIRED;
+ enter.api.minor = FUSION_API_MINOR_REQUIRED;
+ enter.fusion_id = 0; /* Clear for check below. */
+
+ /* Enter the fusion world. */
+ while (ioctl( fd, FUSION_ENTER, &enter )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/Init: Could not reenter world '%d'!\n", shared->world_index );
+ raise(5);
+ }
+ }
+
+ /* Check for valid Fusion ID. */
+ if (!enter.fusion_id) {
+ D_ERROR( "Fusion/Init: Got no ID from FUSION_ENTER! Kernel module might be too old.\n" );
+ raise(5);
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> Fusion ID 0x%08lx\n", enter.fusion_id );
+
+
+ /* Fill fork information. */
+ fork.fusion_id = world->fusion_id;
+
+ /* Fork within the fusion world. */
+ while (ioctl( fd, FUSION_FORK, &fork )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/Main: Could not fork in world '%d'!\n", shared->world_index );
+ raise(5);
+ }
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> Fusion ID 0x%08lx\n", fork.fusion_id );
+
+ /* Get new fusion id back. */
+ world->fusion_id = fork.fusion_id;
+
+ /* Close old file descriptor. */
+ close( world->fusion_fd );
+
+ /* Write back new file descriptor. */
+ world->fusion_fd = fd;
+
+
+ D_DEBUG_AT( Fusion_Main, " -> restarting dispatcher loop...\n" );
+
+ /* Restart the dispatcher thread. FIXME: free old struct */
+ world->dispatch_loop = direct_thread_create( DTT_MESSAGING,
+ fusion_dispatch_loop,
+ world, "Fusion Dispatch" );
+ if (!world->dispatch_loop)
+ raise(5);
+}
+
+static void
+fusion_fork_handler_prepare( void )
+{
+ int i;
+
+ D_DEBUG_AT( Fusion_Main, "%s()\n", __FUNCTION__ );
+
+ for (i=0; i<FUSION_MAX_WORLDS; i++) {
+ FusionWorld *world = fusion_worlds[i];
+
+ if (!world)
+ continue;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ if (world->fork_callback)
+ world->fork_callback( world->fork_action, FFS_PREPARE );
+ }
+}
+
+static void
+fusion_fork_handler_parent( void )
+{
+ int i;
+
+ D_DEBUG_AT( Fusion_Main, "%s()\n", __FUNCTION__ );
+
+ for (i=0; i<FUSION_MAX_WORLDS; i++) {
+ FusionWorld *world = fusion_worlds[i];
+ FusionWorldShared *shared;
+
+ if (!world)
+ continue;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (world->fork_callback)
+ world->fork_callback( world->fork_action, FFS_PARENT );
+
+ if (world->fork_action == FFA_FORK) {
+ /* Increase the shared reference counter. */
+ if (fusion_master( world ))
+ shared->refs++;
+ }
+ }
+}
+
+static void
+fusion_fork_handler_child( void )
+{
+ int i;
+
+ D_DEBUG_AT( Fusion_Main, "%s()\n", __FUNCTION__ );
+
+ for (i=0; i<FUSION_MAX_WORLDS; i++) {
+ FusionWorld *world = fusion_worlds[i];
+
+ if (!world)
+ continue;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ if (world->fork_callback)
+ world->fork_callback( world->fork_action, FFS_CHILD );
+
+ switch (world->fork_action) {
+ default:
+ D_BUG( "unknown fork action %d", world->fork_action );
+
+ case FFA_CLOSE:
+ D_DEBUG_AT( Fusion_Main, " -> closing world %d\n", i );
+
+ /* Remove world from global list. */
+ fusion_worlds[i] = NULL;
+
+ /* Unmap shared area. */
+ munmap( world->shared, sizeof(FusionWorldShared) );
+
+ /* Close Fusion Kernel Device. */
+ close( world->fusion_fd );
+
+ /* Free local world data. */
+ D_MAGIC_CLEAR( world );
+ D_FREE( world );
+
+ break;
+
+ case FFA_FORK:
+ D_DEBUG_AT( Fusion_Main, " -> forking in world %d\n", i );
+
+ fusion_world_fork( world );
+
+ break;
+ }
+ }
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * Enters a fusion world by joining or creating it.
+ *
+ * If <b>world</b> is negative, the next free index is used to create a new world.
+ * Otherwise the world with the specified index is joined or created.
+ */
+DirectResult
+fusion_enter( int world_index,
+ int abi_version,
+ FusionEnterRole role,
+ FusionWorld **ret_world )
+{
+ DirectResult ret = DR_OK;
+ int fd = -1;
+ FusionWorld *world = NULL;
+ FusionWorldShared *shared = NULL;
+ FusionEnter enter;
+ char buf1[20];
+ char buf2[20];
+
+ D_DEBUG_AT( Fusion_Main, "%s( %d, %d, %p )\n", __FUNCTION__, world_index, abi_version, ret_world );
+
+ D_ASSERT( ret_world != NULL );
+
+ if (world_index >= FUSION_MAX_WORLDS) {
+ D_ERROR( "Fusion/Init: World index %d exceeds maximum index %d!\n", world_index, FUSION_MAX_WORLDS - 1 );
+ return DR_INVARG;
+ }
+
+ pthread_once( &fusion_init_once, init_once );
+
+
+ if (fusion_config->force_slave)
+ role = FER_SLAVE;
+
+ direct_initialize();
+
+ pthread_mutex_lock( &fusion_worlds_lock );
+
+
+ if (world_index < 0) {
+ if (role == FER_SLAVE) {
+ D_ERROR( "Fusion/Init: Slave role and a new world (index -1) was requested!\n" );
+ pthread_mutex_unlock( &fusion_worlds_lock );
+ return DR_INVARG;
+ }
+
+ for (world_index=0; world_index<FUSION_MAX_WORLDS; world_index++) {
+ world = fusion_worlds[world_index];
+ if (world)
+ break;
+
+ snprintf( buf1, sizeof(buf1), "/dev/fusion%d", world_index );
+ snprintf( buf2, sizeof(buf2), "/dev/fusion/%d", world_index );
+
+ /* Open Fusion Kernel Device. */
+ fd = direct_try_open( buf1, buf2, O_RDWR | O_NONBLOCK | O_EXCL, false );
+ if (fd < 0) {
+ if (errno != EBUSY)
+ D_PERROR( "Fusion/Init: Error opening '%s' and/or '%s'!\n", buf1, buf2 );
+ }
+ else
+ break;
+ }
+ }
+ else {
+ world = fusion_worlds[world_index];
+ if (!world) {
+ int flags = O_RDWR | O_NONBLOCK;
+
+ snprintf( buf1, sizeof(buf1), "/dev/fusion%d", world_index );
+ snprintf( buf2, sizeof(buf2), "/dev/fusion/%d", world_index );
+
+ if (role == FER_MASTER)
+ flags |= O_EXCL;
+ else if (role == FER_SLAVE)
+ flags |= O_APPEND;
+
+ /* Open Fusion Kernel Device. */
+ fd = direct_try_open( buf1, buf2, flags, true );
+ }
+ }
+
+ /* Enter a world again? */
+ if (world) {
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( world->refs > 0 );
+
+ /* Check the role again. */
+ switch (role) {
+ case FER_MASTER:
+ if (world->fusion_id != FUSION_ID_MASTER) {
+ D_ERROR( "Fusion/Init: Master role requested for a world (%d) "
+ "we're already slave in!\n", world_index );
+ ret = DR_UNSUPPORTED;
+ goto error;
+ }
+ break;
+
+ case FER_SLAVE:
+ if (world->fusion_id == FUSION_ID_MASTER) {
+ D_ERROR( "Fusion/Init: Slave role requested for a world (%d) "
+ "we're already master in!\n", world_index );
+ ret = DR_UNSUPPORTED;
+ goto error;
+ }
+ break;
+
+ case FER_ANY:
+ break;
+ }
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (shared->world_abi != abi_version) {
+ D_ERROR( "Fusion/Init: World ABI (%d) of world '%d' doesn't match own (%d)!\n",
+ shared->world_abi, world_index, abi_version );
+ ret = DR_VERSIONMISMATCH;
+ goto error;
+ }
+
+ world->refs++;
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ D_DEBUG_AT( Fusion_Main, " -> using existing world %p [%d]\n", world, world_index );
+
+ /* Return the world. */
+ *ret_world = world;
+
+ return DR_OK;
+ }
+
+ if (fd < 0) {
+ D_PERROR( "Fusion/Init: Opening fusion device (world %d) as '%s' failed!\n", world_index,
+ role == FER_ANY ? "any" : (role == FER_MASTER ? "master" : "slave") );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ /* Drop "identity" when running another program. */
+ if (fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0)
+ D_PERROR( "Fusion/Init: Setting FD_CLOEXEC flag failed!\n" );
+
+ /* Fill enter information. */
+ enter.api.major = FUSION_API_MAJOR_REQUIRED;
+ enter.api.minor = FUSION_API_MINOR_REQUIRED;
+ enter.fusion_id = 0; /* Clear for check below. */
+
+ /* Enter the fusion world. */
+ while (ioctl( fd, FUSION_ENTER, &enter )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/Init: Could not enter world '%d'!\n", world_index );
+ ret = DR_INIT;
+ goto error;
+ }
+ }
+
+ /* Check for valid Fusion ID. */
+ if (!enter.fusion_id) {
+ D_ERROR( "Fusion/Init: Got no ID from FUSION_ENTER! Kernel module might be too old.\n" );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> Fusion ID 0x%08lx\n", enter.fusion_id );
+
+ /* Check slave role only, master is handled by O_EXCL earlier. */
+ if (role == FER_SLAVE && enter.fusion_id == FUSION_ID_MASTER) {
+ D_PERROR( "Fusion/Init: Entering world '%d' as a slave failed!\n", world_index );
+ ret = DR_UNSUPPORTED;
+ goto error;
+ }
+
+ /* Map shared area. */
+ shared = mmap( (void*) 0x20000000 + 0x2000 * world_index, sizeof(FusionWorldShared),
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0 );
+ if (shared == MAP_FAILED) {
+ D_PERROR( "Fusion/Init: Mapping shared area failed!\n" );
+ goto error;
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> shared area at %p, size %zu\n", shared, sizeof(FusionWorldShared) );
+
+ /* Initialize shared data. */
+ if (enter.fusion_id == FUSION_ID_MASTER) {
+ /* Initialize reference counter. */
+ shared->refs = 1;
+
+ /* Set ABI version. */
+ shared->world_abi = abi_version;
+
+ /* Set the world index. */
+ shared->world_index = world_index;
+
+ /* Set start time of world clock. */
+ direct_monotonic_gettimeofday( &shared->start_time );
+
+ D_MAGIC_SET( shared, FusionWorldShared );
+ }
+ else {
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Check ABI version. */
+ if (shared->world_abi != abi_version) {
+ D_ERROR( "Fusion/Init: World ABI (%d) doesn't match own (%d)!\n",
+ shared->world_abi, abi_version );
+ ret = DR_VERSIONMISMATCH;
+ goto error;
+ }
+ }
+
+ /* Synchronize to world clock. */
+ direct_clock_set_start( &shared->start_time );
+
+
+ /* Allocate local data. */
+ world = D_CALLOC( 1, sizeof(FusionWorld) );
+ if (!world) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ /* Initialize local data. */
+ world->refs = 1;
+ world->shared = shared;
+ world->fusion_fd = fd;
+ world->fusion_id = enter.fusion_id;
+
+ D_MAGIC_SET( world, FusionWorld );
+
+ fusion_worlds[world_index] = world;
+
+
+ /* Initialize shared memory part. */
+ ret = fusion_shm_init( world );
+ if (ret)
+ goto error2;
+
+
+ D_DEBUG_AT( Fusion_Main, " -> initializing other parts...\n" );
+
+ /* Initialize other parts. */
+ if (enter.fusion_id == FUSION_ID_MASTER) {
+ fusion_skirmish_init( &shared->arenas_lock, "Fusion Arenas", world );
+ fusion_skirmish_init( &shared->reactor_globals, "Fusion Reactor Globals", world );
+
+ /* Create the main pool. */
+ ret = fusion_shm_pool_create( world, "Fusion Main Pool", 0x100000,
+ fusion_config->debugshm, &shared->main_pool );
+ if (ret)
+ goto error3;
+ }
+
+
+ D_DEBUG_AT( Fusion_Main, " -> starting dispatcher loop...\n" );
+
+ /* Start the dispatcher thread. */
+ world->dispatch_loop = direct_thread_create( DTT_MESSAGING,
+ fusion_dispatch_loop,
+ world, "Fusion Dispatch" );
+ if (!world->dispatch_loop) {
+ ret = DR_FAILURE;
+ goto error4;
+ }
+
+
+ /* Let others enter the world. */
+ if (enter.fusion_id == FUSION_ID_MASTER) {
+ D_DEBUG_AT( Fusion_Main, " -> unblocking world...\n" );
+
+ while (ioctl( fd, FUSION_UNBLOCK )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/Init: Could not unblock world!\n" );
+ ret = DR_FUSION;
+ goto error4;
+ }
+ }
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> done. (%p)\n", world );
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ /* Return the fusion world. */
+ *ret_world = world;
+
+ return DR_OK;
+
+
+error4:
+ if (world->dispatch_loop)
+ direct_thread_destroy( world->dispatch_loop );
+
+ if (enter.fusion_id == FUSION_ID_MASTER)
+ fusion_shm_pool_destroy( world, shared->main_pool );
+
+error3:
+ if (enter.fusion_id == FUSION_ID_MASTER) {
+ fusion_skirmish_destroy( &shared->arenas_lock );
+ fusion_skirmish_destroy( &shared->reactor_globals );
+ }
+
+ fusion_shm_deinit( world );
+
+
+error2:
+ fusion_worlds[world_index] = world;
+
+ D_MAGIC_CLEAR( world );
+
+ D_FREE( world );
+
+error:
+ if (shared && shared != MAP_FAILED) {
+ if (enter.fusion_id == FUSION_ID_MASTER)
+ D_MAGIC_CLEAR( shared );
+
+ munmap( shared, sizeof(FusionWorldShared) );
+ }
+
+ if (fd != -1)
+ close( fd );
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ direct_shutdown();
+
+ return ret;
+}
+
+DirectResult
+fusion_stop_dispatcher( FusionWorld *world,
+ bool emergency )
+{
+ if (!emergency) {
+ fusion_sync( world );
+
+ direct_thread_lock( world->dispatch_loop );
+ }
+
+ world->dispatch_stop = true;
+
+ if (!emergency) {
+ direct_thread_unlock( world->dispatch_loop );
+
+ fusion_sync( world );
+ }
+
+ return DR_OK;
+}
+
+/*
+ * Exits the fusion world.
+ *
+ * If 'emergency' is true the function won't join but kill the dispatcher thread.
+ */
+DirectResult
+fusion_exit( FusionWorld *world,
+ bool emergency )
+{
+ FusionWorldShared *shared;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %semergency )\n", __FUNCTION__, world, emergency ? "" : "no " );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+
+ pthread_mutex_lock( &fusion_worlds_lock );
+
+ D_ASSERT( world->refs > 0 );
+
+ if (--world->refs) {
+ pthread_mutex_unlock( &fusion_worlds_lock );
+ return DR_OK;
+ }
+
+ if (!emergency) {
+ int foo;
+ FusionSendMessage msg;
+
+ /* Wake up the read loop thread. */
+ msg.fusion_id = world->fusion_id;
+ msg.msg_id = 0;
+ msg.msg_data = &foo;
+ msg.msg_size = sizeof(foo);
+
+ while (ioctl( world->fusion_fd, FUSION_SEND_MESSAGE, &msg ) < 0) {
+ if (errno != EINTR) {
+ D_PERROR( "FUSION_SEND_MESSAGE" );
+ direct_thread_cancel( world->dispatch_loop );
+ break;
+ }
+ }
+
+ /* Wait for its termination. */
+ direct_thread_join( world->dispatch_loop );
+ }
+
+ direct_thread_destroy( world->dispatch_loop );
+
+ /* Master has to deinitialize shared data. */
+ if (fusion_master( world )) {
+ shared->refs--;
+ if (shared->refs == 0) {
+ fusion_skirmish_destroy( &shared->reactor_globals );
+ fusion_skirmish_destroy( &shared->arenas_lock );
+
+ fusion_shm_pool_destroy( world, shared->main_pool );
+
+ /* Deinitialize shared memory. */
+ fusion_shm_deinit( world );
+ }
+ }
+ else {
+ /* Leave shared memory. */
+ fusion_shm_deinit( world );
+ }
+
+ /* Reset local dispatch nodes. */
+ _fusion_reactor_free_all( world );
+
+
+ /* Remove world from global list. */
+ fusion_worlds[shared->world_index] = NULL;
+
+
+ /* Unmap shared area. */
+ if (fusion_master( world ) && shared->refs == 0)
+ D_MAGIC_CLEAR( shared );
+
+ munmap( shared, sizeof(FusionWorldShared) );
+
+
+ /* Close Fusion Kernel Device. */
+ close( world->fusion_fd );
+
+
+ /* Free local world data. */
+ D_MAGIC_CLEAR( world );
+ D_FREE( world );
+
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ direct_shutdown();
+
+ return DR_OK;
+}
+
+/*
+ * Sends a signal to one or more fusionees and optionally waits
+ * for their processes to terminate.
+ *
+ * A fusion_id of zero means all fusionees but the calling one.
+ * A timeout of zero means infinite waiting while a negative value
+ * means no waiting at all.
+ */
+DirectResult
+fusion_kill( FusionWorld *world,
+ FusionID fusion_id,
+ int signal,
+ int timeout_ms )
+{
+ FusionKill param;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ param.fusion_id = fusion_id;
+ param.signal = signal;
+ param.timeout_ms = timeout_ms;
+
+ while (ioctl( world->fusion_fd, FUSION_KILL, &param )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case ETIMEDOUT:
+ return DR_TIMEOUT;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_KILL");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+static void *
+fusion_dispatch_loop( DirectThread *thread, void *arg )
+{
+ int len = 0;
+ int result;
+ char buf[FUSION_MESSAGE_SIZE];
+ fd_set set;
+ FusionWorld *world = arg;
+
+ D_DEBUG_AT( Fusion_Main_Dispatch, "%s() running...\n", __FUNCTION__ );
+
+ while (true) {
+ char *buf_p = buf;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ FD_ZERO( &set );
+ FD_SET( world->fusion_fd, &set );
+
+ result = select( world->fusion_fd + 1, &set, NULL, NULL, NULL );
+ if (result < 0) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ default:
+ D_PERROR( "Fusion/Dispatcher: select() failed!\n" );
+ return NULL;
+ }
+ }
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ if (FD_ISSET( world->fusion_fd, &set )) {
+ len = read( world->fusion_fd, buf, FUSION_MESSAGE_SIZE );
+ if (len < 0)
+ break;
+
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> got %d bytes...\n", len );
+
+ direct_thread_lock( world->dispatch_loop );
+
+ if (world->dispatch_stop) {
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> IGNORING (dispatch_stop!)\n" );
+ }
+ else {
+ while (buf_p < buf + len) {
+ FusionReadMessage *header = (FusionReadMessage*) buf_p;
+ void *data = buf_p + sizeof(FusionReadMessage);
+
+ if (world->dispatch_stop) {
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> ABORTING (dispatch_stop!)\n" );
+ break;
+ }
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( (buf + len - buf_p) >= sizeof(FusionReadMessage) );
+
+ switch (header->msg_type) {
+ case FMT_SEND:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_SEND!\n" );
+ break;
+ case FMT_CALL:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_CALL...\n" );
+ _fusion_call_process( world, header->msg_id, data );
+ break;
+ case FMT_REACTOR:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_REACTOR...\n" );
+ _fusion_reactor_process_message( world, header->msg_id, header->msg_channel, data );
+ break;
+ case FMT_SHMPOOL:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_SHMPOOL...\n" );
+ _fusion_shmpool_process( world, header->msg_id, data );
+ break;
+ default:
+ D_DEBUG( "Fusion/Receiver: discarding message of unknown type '%d'\n",
+ header->msg_type );
+ break;
+ }
+
+ buf_p = data + ((header->msg_size + 3) & ~3);
+ }
+ }
+
+ direct_thread_unlock( world->dispatch_loop );
+
+ if (!world->refs) {
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> good bye!\n" );
+ return NULL;
+ }
+ }
+ }
+
+ D_PERROR( "Fusion/Receiver: reading from fusion device failed!\n" );
+
+ return NULL;
+}
+
+/**********************************************************************************************************************/
+
+#else /* FUSION_BUILD_KERNEL */
+
+#include <dirent.h>
+
+#include <direct/system.h>
+
+typedef struct {
+ DirectLink link;
+
+ FusionRef *ref;
+
+ int count;
+} __FusioneeRef;
+
+typedef struct {
+ DirectLink link;
+
+ FusionID id;
+ pid_t pid;
+
+ DirectLink *refs;
+} __Fusionee;
+
+
+/**********************************************************************************************************************/
+
+static DirectResult
+_fusion_add_fusionee( FusionWorld *world, FusionID fusion_id )
+{
+ DirectResult ret;
+ FusionWorldShared *shared;
+ __Fusionee *fusionee;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %lu )\n", __FUNCTION__, world, fusion_id );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ fusionee = SHCALLOC( shared->main_pool, 1, sizeof(__Fusionee) );
+ if (!fusionee)
+ return D_OOSHM();
+
+ fusionee->id = fusion_id;
+ fusionee->pid = direct_gettid();
+
+ ret = fusion_skirmish_prevail( &shared->fusionees_lock );
+ if (ret) {
+ SHFREE( shared->main_pool, fusionee );
+ return ret;
+ }
+
+ direct_list_append( &shared->fusionees, &fusionee->link );
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+
+ /* Set local pointer. */
+ world->fusionee = fusionee;
+
+ return DR_OK;
+}
+
+void
+_fusion_add_local( FusionWorld *world, FusionRef *ref, int add )
+{
+ FusionWorldShared *shared;
+ __Fusionee *fusionee;
+ __FusioneeRef *fusionee_ref;
+
+ //D_DEBUG_AT( Fusion_Main, "%s( %p, %p, %d )\n", __FUNCTION__, world, ref, add );
+
+ D_ASSERT( ref != NULL );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ fusionee = world->fusionee;
+
+ D_ASSERT( fusionee != NULL );
+
+ direct_list_foreach (fusionee_ref, fusionee->refs) {
+ if (fusionee_ref->ref == ref)
+ break;
+ }
+
+ if (fusionee_ref) {
+ fusionee_ref->count += add;
+
+ //D_DEBUG_AT( Fusion_Main, " -> refs = %d\n", fusionee_ref->count );
+
+ if (fusionee_ref->count == 0) {
+ direct_list_remove( &fusionee->refs, &fusionee_ref->link );
+ SHFREE( shared->main_pool, fusionee_ref );
+ }
+ }
+ else {
+ if (add <= 0) /* called from _fusion_remove_fusionee() */
+ return;
+
+ //D_DEBUG_AT( Fusion_Main, " -> new ref\n" );
+
+ fusionee_ref = SHCALLOC( shared->main_pool, 1, sizeof(__FusioneeRef) );
+ if (!fusionee_ref) {
+ D_OOSHM();
+ return;
+ }
+
+ fusionee_ref->ref = ref;
+ fusionee_ref->count = add;
+
+ direct_list_prepend( &fusionee->refs, &fusionee_ref->link );
+ }
+}
+
+void
+_fusion_check_locals( FusionWorld *world, FusionRef *ref )
+{
+ FusionWorldShared *shared;
+ __Fusionee *fusionee;
+ __FusioneeRef *fusionee_ref, *temp;
+ DirectLink *list = NULL;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %p )\n", __FUNCTION__, world, ref );
+
+ D_ASSERT( ref != NULL );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (fusion_skirmish_prevail( &shared->fusionees_lock ))
+ return;
+
+ direct_list_foreach (fusionee, shared->fusionees) {
+ if (fusionee->id == world->fusion_id)
+ continue;
+
+ direct_list_foreach (fusionee_ref, fusionee->refs) {
+ if (fusionee_ref->ref == ref) {
+ if (kill( fusionee->pid, 0 ) < 0 && errno == ESRCH) {
+ direct_list_remove( &fusionee->refs, &fusionee_ref->link );
+ direct_list_append( &list, &fusionee_ref->link );
+ }
+ break;
+ }
+ }
+ }
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+
+ direct_list_foreach_safe (fusionee_ref, temp, list) {
+ _fusion_ref_change( ref, -fusionee_ref->count, false );
+
+ SHFREE( shared->main_pool, fusionee_ref );
+ }
+}
+
+void
+_fusion_remove_all_locals( FusionWorld *world, const FusionRef *ref )
+{
+ FusionWorldShared *shared;
+ __Fusionee *fusionee;
+ __FusioneeRef *fusionee_ref, *temp;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %p )\n", __FUNCTION__, world, ref );
+
+ D_ASSERT( ref != NULL );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (fusion_skirmish_prevail( &shared->fusionees_lock ))
+ return;
+
+ direct_list_foreach (fusionee, shared->fusionees) {
+ direct_list_foreach_safe (fusionee_ref, temp, fusionee->refs) {
+ if (fusionee_ref->ref == ref) {
+ direct_list_remove( &fusionee->refs, &fusionee_ref->link );
+
+ SHFREE( shared->main_pool, fusionee_ref );
+ }
+ }
+ }
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+}
+
+static void
+_fusion_remove_fusionee( FusionWorld *world, FusionID fusion_id )
+{
+ FusionWorldShared *shared;
+ __Fusionee *fusionee;
+ __FusioneeRef *fusionee_ref, *temp;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %lu )\n", __FUNCTION__, world, fusion_id );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ fusion_skirmish_prevail( &shared->fusionees_lock );
+
+ if (fusion_id == world->fusion_id) {
+ fusionee = world->fusionee;
+ }
+ else {
+ direct_list_foreach (fusionee, shared->fusionees) {
+ if (fusionee->id == fusion_id)
+ break;
+ }
+ }
+
+ if (!fusionee) {
+ D_DEBUG_AT( Fusion_Main, "Fusionee %lu not found!\n", fusion_id );
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+ return;
+ }
+
+ direct_list_remove( &shared->fusionees, &fusionee->link );
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+
+ direct_list_foreach_safe (fusionee_ref, temp, fusionee->refs) {
+ direct_list_remove( &fusionee->refs, &fusionee_ref->link );
+
+ _fusion_ref_change( fusionee_ref->ref, -fusionee_ref->count, false );
+
+ SHFREE( shared->main_pool, fusionee_ref );
+ }
+
+ SHFREE( shared->main_pool, fusionee );
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+_fusion_send_message( int fd,
+ const void *msg,
+ size_t msg_size,
+ struct sockaddr_un *addr )
+{
+ socklen_t len = sizeof(struct sockaddr_un);
+
+ D_ASSERT( msg != NULL );
+
+ if (!addr) {
+ addr = alloca( sizeof(struct sockaddr_un) );
+ getsockname( fd, (struct sockaddr*)addr, &len );
+ }
+
+ while (sendto( fd, msg, msg_size, 0, (struct sockaddr*)addr, len ) < 0) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case ECONNREFUSED:
+ return DR_FUSION;
+ default:
+ break;
+ }
+
+ D_PERROR( "Fusion: sendto()\n" );
+
+ return DR_IO;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+_fusion_recv_message( int fd,
+ void *msg,
+ size_t msg_size,
+ struct sockaddr_un *addr )
+{
+ socklen_t len = addr ? sizeof(struct sockaddr_un) : 0;
+
+ D_ASSERT( msg != NULL );
+
+ while (recvfrom( fd, msg, msg_size, 0, (struct sockaddr*)addr, &len ) < 0) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case ECONNREFUSED:
+ return DR_FUSION;
+ default:
+ break;
+ }
+
+ D_PERROR( "Fusion: recvfrom()\n" );
+
+ return DR_IO;
+ }
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+static void
+fusion_fork_handler_prepare( void )
+{
+ int i;
+
+ D_DEBUG_AT( Fusion_Main, "%s()\n", __FUNCTION__ );
+
+ for (i=0; i<FUSION_MAX_WORLDS; i++) {
+ FusionWorld *world = fusion_worlds[i];
+
+ if (!world)
+ continue;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ if (world->fork_callback)
+ world->fork_callback( world->fork_action, FFS_PREPARE );
+ }
+}
+
+static void
+fusion_fork_handler_parent( void )
+{
+ int i;
+
+ D_DEBUG_AT( Fusion_Main, "%s()\n", __FUNCTION__ );
+
+ for (i=0; i<FUSION_MAX_WORLDS; i++) {
+ FusionWorld *world = fusion_worlds[i];
+ FusionWorldShared *shared;
+
+ if (!world)
+ continue;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (world->fork_callback)
+ world->fork_callback( world->fork_action, FFS_PARENT );
+
+ if (world->fork_action == FFA_FORK) {
+ /* Increase the shared reference counter. */
+ if (fusion_master( world ))
+ shared->refs++;
+
+ /* Cancel the dispatcher to prevent conflicts. */
+ direct_thread_cancel( world->dispatch_loop );
+ }
+ }
+}
+
+static void
+fusion_fork_handler_child( void )
+{
+ int i;
+
+ D_DEBUG_AT( Fusion_Main, "%s()\n", __FUNCTION__ );
+
+ for (i=0; i<FUSION_MAX_WORLDS; i++) {
+ FusionWorld *world = fusion_worlds[i];
+ FusionWorldShared *shared;
+
+ if (!world)
+ continue;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (world->fork_callback)
+ world->fork_callback( world->fork_action, FFS_CHILD );
+
+ switch (world->fork_action) {
+ default:
+ D_BUG( "unknown fork action %d", world->fork_action );
+
+ case FFA_CLOSE:
+ D_DEBUG_AT( Fusion_Main, " -> closing world %d\n", i );
+
+ /* Remove world from global list. */
+ fusion_worlds[i] = NULL;
+
+ /* Unmap shared area. */
+ munmap( world->shared, sizeof(FusionWorldShared) );
+
+ /* Close socket. */
+ close( world->fusion_fd );
+
+ /* Free local world data. */
+ D_MAGIC_CLEAR( world );
+ D_FREE( world );
+
+ break;
+
+ case FFA_FORK: {
+ __Fusionee *fusionee;
+ __FusioneeRef *fusionee_ref;
+
+ D_DEBUG_AT( Fusion_Main, " -> forking in world %d\n", i );
+
+ fusionee = world->fusionee;
+
+ D_DEBUG_AT( Fusion_Main, " -> duplicating fusion id %lu\n", world->fusion_id );
+
+ fusion_skirmish_prevail( &shared->fusionees_lock );
+
+ if (_fusion_add_fusionee( world, world->fusion_id )) {
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+ raise( SIGTRAP );
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> duplicating local refs...\n" );
+
+ direct_list_foreach (fusionee_ref, fusionee->refs) {
+ __FusioneeRef *new_ref;
+
+ new_ref = SHCALLOC( shared->main_pool, 1, sizeof(__FusioneeRef) );
+ if (!new_ref) {
+ D_OOSHM();
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+ raise( SIGTRAP );
+ }
+
+ new_ref->ref = fusionee_ref->ref;
+ new_ref->count = fusionee_ref->count;
+ /* Avoid locking. */
+ new_ref->ref->multi.builtin.local += new_ref->count;
+
+ direct_list_append( &((__Fusionee*)world->fusionee)->refs, &new_ref->link );
+ }
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+
+ D_DEBUG_AT( Fusion_Main, " -> restarting dispatcher loop...\n" );
+
+ /* Restart the dispatcher thread. FIXME: free old struct */
+ world->dispatch_loop = direct_thread_create( DTT_MESSAGING,
+ fusion_dispatch_loop,
+ world, "Fusion Dispatch" );
+ if (!world->dispatch_loop)
+ raise( SIGTRAP );
+
+ } break;
+ }
+ }
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * Enters a fusion world by joining or creating it.
+ *
+ * If <b>world</b> is negative, the next free index is used to create a new world.
+ * Otherwise the world with the specified index is joined or created.
+ */
+DirectResult
+fusion_enter( int world_index,
+ int abi_version,
+ FusionEnterRole role,
+ FusionWorld **ret_world )
+{
+ DirectResult ret = DR_OK;
+ int fd = -1;
+ FusionID id = -1;
+ FusionWorld *world = NULL;
+ FusionWorldShared *shared = MAP_FAILED;
+ struct sockaddr_un addr;
+ char buf[128];
+ int len, err;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %d, %d, %p )\n", __FUNCTION__, world_index, abi_version, ret_world );
+
+ D_ASSERT( ret_world != NULL );
+
+ if (world_index >= FUSION_MAX_WORLDS) {
+ D_ERROR( "Fusion/Init: World index %d exceeds maximum index %d!\n", world_index, FUSION_MAX_WORLDS - 1 );
+ return DR_INVARG;
+ }
+
+ if (fusion_config->force_slave)
+ role = FER_SLAVE;
+
+ pthread_once( &fusion_init_once, init_once );
+
+ direct_initialize();
+
+ fd = socket( PF_LOCAL, SOCK_RAW, 0 );
+ if (fd < 0) {
+ D_PERROR( "Fusion/Init: Error creating local socket!\n" );
+ return DR_IO;
+ }
+
+ /* Set close-on-exec flag. */
+ if (fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0)
+ D_PERROR( "Fusion/Init: Couldn't set close-on-exec flag!\n" );
+
+ pthread_mutex_lock( &fusion_worlds_lock );
+
+ addr.sun_family = AF_UNIX;
+
+ if (world_index < 0) {
+ if (role == FER_SLAVE) {
+ D_ERROR( "Fusion/Init: Slave role and a new world (index -1) was requested!\n" );
+ pthread_mutex_unlock( &fusion_worlds_lock );
+ close( fd );
+ return DR_INVARG;
+ }
+
+ for (world_index=0; world_index<FUSION_MAX_WORLDS; world_index++) {
+ if (fusion_worlds[world_index])
+ continue;
+
+ len = snprintf( addr.sun_path, sizeof(addr.sun_path), "/tmp/.fusion-%d/", world_index );
+ /* Make socket directory if it doesn't exits. */
+ if (mkdir( addr.sun_path, 0775 ) == 0) {
+ chmod( addr.sun_path, 0775 );
+ if (fusion_config->shmfile_gid != (gid_t)-1)
+ chown( addr.sun_path, -1, fusion_config->shmfile_gid );
+ }
+
+ snprintf( addr.sun_path+len, sizeof(addr.sun_path)-len, "%lx", FUSION_ID_MASTER );
+
+ /* Bind to address. */
+ err = bind( fd, (struct sockaddr*)&addr, sizeof(addr) );
+ if (err == 0) {
+ chmod( addr.sun_path, 0660 );
+ /* Change group, if requested. */
+ if (fusion_config->shmfile_gid != (gid_t)-1)
+ chown( addr.sun_path, -1, fusion_config->shmfile_gid );
+ id = FUSION_ID_MASTER;
+ break;
+ }
+ }
+ }
+ else {
+ world = fusion_worlds[world_index];
+ if (!world) {
+ len = snprintf( addr.sun_path, sizeof(addr.sun_path), "/tmp/.fusion-%d/", world_index );
+ /* Make socket directory if it doesn't exits. */
+ if (mkdir( addr.sun_path, 0775 ) == 0) {
+ chmod( addr.sun_path, 0775 );
+ if (fusion_config->shmfile_gid != (gid_t)-1)
+ chown( addr.sun_path, -1, fusion_config->shmfile_gid );
+ }
+
+ /* Check wether we are master. */
+ snprintf( addr.sun_path+len, sizeof(addr.sun_path)-len, "%lx", FUSION_ID_MASTER );
+
+ err = bind( fd, (struct sockaddr*)&addr, sizeof(addr) );
+ if (err < 0) {
+ if (role == FER_MASTER) {
+ D_ERROR( "Fusion/Main: Couldn't start session as master! Remove %s.\n", addr.sun_path );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ /* Auto generate slave id. */
+ for (id = FUSION_ID_MASTER+1; id < (FusionID)-1; id++) {
+ snprintf( addr.sun_path+len, sizeof(addr.sun_path)-len, "%lx", id );
+ err = bind( fd, (struct sockaddr*)&addr, sizeof(addr) );
+ if (err == 0) {
+ chmod( addr.sun_path, 0660 );
+ /* Change group, if requested. */
+ if (fusion_config->shmfile_gid != (gid_t)-1)
+ chown( addr.sun_path, -1, fusion_config->shmfile_gid );
+ break;
+ }
+ }
+ }
+ else if (err == 0 && role != FER_SLAVE) {
+ chmod( addr.sun_path, 0660 );
+ /* Change group, if requested. */
+ if (fusion_config->shmfile_gid != (gid_t)-1)
+ chown( addr.sun_path, -1, fusion_config->shmfile_gid );
+ id = FUSION_ID_MASTER;
+ }
+ }
+ }
+
+ /* Enter a world again? */
+ if (world) {
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( world->refs > 0 );
+
+ /* Check the role again. */
+ switch (role) {
+ case FER_MASTER:
+ if (world->fusion_id != FUSION_ID_MASTER) {
+ D_ERROR( "Fusion/Init: Master role requested for a world (%d) "
+ "we're already slave in!\n", world_index );
+ ret = DR_UNSUPPORTED;
+ goto error;
+ }
+ break;
+
+ case FER_SLAVE:
+ if (world->fusion_id == FUSION_ID_MASTER) {
+ D_ERROR( "Fusion/Init: Slave role requested for a world (%d) "
+ "we're already master in!\n", world_index );
+ ret = DR_UNSUPPORTED;
+ goto error;
+ }
+ break;
+
+ case FER_ANY:
+ break;
+ }
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ if (shared->world_abi != abi_version) {
+ D_ERROR( "Fusion/Init: World ABI (%d) of world '%d' doesn't match own (%d)!\n",
+ shared->world_abi, world_index, abi_version );
+ ret = DR_VERSIONMISMATCH;
+ goto error;
+ }
+
+ world->refs++;
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ D_DEBUG_AT( Fusion_Main, " -> using existing world %p [%d]\n", world, world_index );
+
+ close( fd );
+
+ /* Return the world. */
+ *ret_world = world;
+
+ return DR_OK;
+ }
+
+ if (id == (FusionID)-1) {
+ D_ERROR( "Fusion/Init: Opening fusion socket (world %d) as '%s' failed!\n", world_index,
+ role == FER_ANY ? "any" : (role == FER_MASTER ? "master" : "slave") );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> Fusion ID 0x%08lx\n", id );
+
+ if (id == FUSION_ID_MASTER) {
+ int shared_fd;
+
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.core",
+ fusion_config->tmpfs ? : "/dev/shm", world_index );
+
+ /* Open shared memory file. */
+ shared_fd = open( buf, O_RDWR | O_CREAT | O_TRUNC, 0660 );
+ if (shared_fd < 0) {
+ D_PERROR( "Fusion/Init: Couldn't open shared memory file!\n" );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ if (fusion_config->shmfile_gid != (gid_t)-1) {
+ if (fchown( shared_fd, -1, fusion_config->shmfile_gid ) != 0)
+ D_INFO( "Fusion/Init: Changing owner on %s failed... continuing on.\n", buf );
+ }
+
+ fchmod( shared_fd, 0660 );
+ ftruncate( shared_fd, sizeof(FusionWorldShared) );
+
+ /* Map shared area. */
+ shared = mmap( (void*) 0x20000000 + 0x2000 * world_index, sizeof(FusionWorldShared),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, shared_fd, 0 );
+ if (shared == MAP_FAILED) {
+ D_PERROR( "Fusion/Init: Mapping shared area failed!\n" );
+ close( shared_fd );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ close( shared_fd );
+
+ D_DEBUG_AT( Fusion_Main, " -> shared area at %p, size %zu\n", shared, sizeof(FusionWorldShared) );
+
+ /* Initialize reference counter. */
+ shared->refs = 1;
+
+ /* Set ABI version. */
+ shared->world_abi = abi_version;
+
+ /* Set the world index. */
+ shared->world_index = world_index;
+
+ /* Set pool allocation base/max. */
+ shared->pool_base = (void*)0x20000000 + 0x2000 * FUSION_MAX_WORLDS + 0x8000000 * world_index;
+ shared->pool_max = shared->pool_base + 0x8000000 - 1;
+
+ /* Set start time of world clock. */
+ direct_monotonic_gettimeofday( &shared->start_time );
+
+ D_MAGIC_SET( shared, FusionWorldShared );
+ }
+ else {
+ FusionEnter enter;
+ int shared_fd;
+
+ /* Fill enter information. */
+ enter.type = FMT_ENTER;
+ enter.fusion_id = id;
+
+ snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/%lx", world_index, FUSION_ID_MASTER );
+
+ /* Send enter message (used to sync with the master) */
+ ret = _fusion_send_message( fd, &enter, sizeof(FusionEnter), &addr );
+ if (ret == DR_OK) {
+ ret = _fusion_recv_message( fd, &enter, sizeof(FusionEnter), NULL );
+ if (ret == DR_OK && enter.type != FMT_ENTER) {
+ D_ERROR( "Fusion/Init: Expected message ENTER, got '%d'!\n", enter.type );
+ ret = DR_FUSION;
+ }
+ }
+
+ if (ret) {
+ D_ERROR( "Fusion/Init: Could not enter world '%d'!\n", world_index );
+ goto error;
+ }
+
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.core",
+ fusion_config->tmpfs ? : "/dev/shm", world_index );
+
+ /* Open shared memory file. */
+ shared_fd = open( buf, O_RDWR );
+ if (shared_fd < 0) {
+ D_PERROR( "Fusion/Init: Couldn't open shared memory file!\n" );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ /* Map shared area. */
+ shared = mmap( (void*) 0x20000000 + 0x2000 * world_index, sizeof(FusionWorldShared),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, shared_fd, 0 );
+ if (shared == MAP_FAILED) {
+ D_PERROR( "Fusion/Init: Mapping shared area failed!\n" );
+ close( shared_fd );
+ ret = DR_INIT;
+ goto error;
+ }
+
+ close( shared_fd );
+
+ D_DEBUG_AT( Fusion_Main, " -> shared area at %p, size %zu\n", shared, sizeof(FusionWorldShared) );
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Check ABI version. */
+ if (shared->world_abi != abi_version) {
+ D_ERROR( "Fusion/Init: World ABI (%d) doesn't match own (%d)!\n",
+ shared->world_abi, abi_version );
+ ret = DR_VERSIONMISMATCH;
+ goto error;
+ }
+ }
+
+ /* Synchronize to world clock. */
+ direct_clock_set_start( &shared->start_time );
+
+ /* Allocate local data. */
+ world = D_CALLOC( 1, sizeof(FusionWorld) );
+ if (!world) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ /* Initialize local data. */
+ world->refs = 1;
+ world->shared = shared;
+ world->fusion_fd = fd;
+ world->fusion_id = id;
+
+ D_MAGIC_SET( world, FusionWorld );
+
+ fusion_worlds[world_index] = world;
+
+ /* Initialize shared memory part. */
+ ret = fusion_shm_init( world );
+ if (ret)
+ goto error2;
+
+ D_DEBUG_AT( Fusion_Main, " -> initializing other parts...\n" );
+
+ /* Initialize other parts. */
+ if (world->fusion_id == FUSION_ID_MASTER) {
+ fusion_skirmish_init( &shared->arenas_lock, "Fusion Arenas", world );
+ fusion_skirmish_init( &shared->reactor_globals, "Fusion Reactor Globals", world );
+ fusion_skirmish_init( &shared->fusionees_lock, "Fusionees", world );
+
+ /* Create the main pool. */
+ ret = fusion_shm_pool_create( world, "Fusion Main Pool", 0x100000,
+ fusion_config->debugshm, &shared->main_pool );
+ if (ret)
+ goto error3;
+ }
+
+ /* Add ourselves to the list of fusionees. */
+ ret = _fusion_add_fusionee( world, id );
+ if (ret)
+ goto error4;
+
+ D_DEBUG_AT( Fusion_Main, " -> starting dispatcher loop...\n" );
+
+ /* Start the dispatcher thread. */
+ world->dispatch_loop = direct_thread_create( DTT_MESSAGING,
+ fusion_dispatch_loop,
+ world, "Fusion Dispatch" );
+ if (!world->dispatch_loop) {
+ ret = DR_FAILURE;
+ goto error5;
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> done. (%p)\n", world );
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ /* Return the fusion world. */
+ *ret_world = world;
+
+ return DR_OK;
+
+
+error5:
+ if (world->dispatch_loop)
+ direct_thread_destroy( world->dispatch_loop );
+
+ _fusion_remove_fusionee( world, id );
+
+error4:
+ if (world->fusion_id == FUSION_ID_MASTER)
+ fusion_shm_pool_destroy( world, shared->main_pool );
+
+error3:
+ if (world->fusion_id == FUSION_ID_MASTER) {
+ fusion_skirmish_destroy( &shared->arenas_lock );
+ fusion_skirmish_destroy( &shared->reactor_globals );
+ fusion_skirmish_destroy( &shared->fusionees_lock );
+ }
+
+ fusion_shm_deinit( world );
+
+
+error2:
+ fusion_worlds[world_index] = world;
+
+ D_MAGIC_CLEAR( world );
+
+ D_FREE( world );
+
+error:
+ if (shared != MAP_FAILED) {
+ if (id == FUSION_ID_MASTER)
+ D_MAGIC_CLEAR( shared );
+
+ munmap( shared, sizeof(FusionWorldShared) );
+ }
+
+ if (fd != -1) {
+ /* Unbind. */
+ socklen_t len = sizeof(addr);
+ if (getsockname( fd, (struct sockaddr*)&addr, &len ) == 0)
+ unlink( addr.sun_path );
+
+ close( fd );
+ }
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ direct_shutdown();
+
+ return ret;
+}
+
+DirectResult
+fusion_stop_dispatcher( FusionWorld *world,
+ bool emergency )
+{
+ if (!emergency) {
+ fusion_sync( world );
+
+ direct_thread_lock( world->dispatch_loop );
+ }
+
+ world->dispatch_stop = true;
+
+ if (!emergency) {
+ direct_thread_unlock( world->dispatch_loop );
+
+ fusion_sync( world );
+ }
+
+ return DR_OK;
+}
+
+/*
+ * Exits the fusion world.
+ *
+ * If 'emergency' is true the function won't join but kill the dispatcher thread.
+ */
+DirectResult
+fusion_exit( FusionWorld *world,
+ bool emergency )
+{
+ FusionWorldShared *shared;
+ int world_index;
+ bool clear = false;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %semergency )\n", __FUNCTION__, world, emergency ? "" : "no " );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ world_index = shared->world_index;
+
+ pthread_mutex_lock( &fusion_worlds_lock );
+
+ D_ASSERT( world->refs > 0 );
+
+ if (--world->refs) {
+ pthread_mutex_unlock( &fusion_worlds_lock );
+ return DR_OK;
+ }
+
+ if (!emergency) {
+ FusionMessageType msg = FMT_SEND;
+
+ /* Wakeup dispatcher. */
+ if (_fusion_send_message( world->fusion_fd, &msg, sizeof(msg), NULL ))
+ direct_thread_cancel( world->dispatch_loop );
+
+ /* Wait for its termination. */
+ direct_thread_join( world->dispatch_loop );
+ }
+
+ direct_thread_destroy( world->dispatch_loop );
+
+ /* Remove ourselves from list. */
+ if (!emergency || fusion_master( world )) {
+ _fusion_remove_fusionee( world, world->fusion_id );
+ }
+ else {
+ struct sockaddr_un addr;
+ FusionLeave leave;
+
+ addr.sun_family = AF_UNIX;
+ snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/%lx", world_index, FUSION_ID_MASTER );
+
+ leave.type = FMT_LEAVE;
+ leave.fusion_id = world->fusion_id;
+
+ _fusion_send_message( world->fusion_fd, &leave, sizeof(FusionLeave), &addr );
+ }
+
+ /* Master has to deinitialize shared data. */
+ if (fusion_master( world )) {
+ shared->refs--;
+ if (shared->refs == 0) {
+ fusion_skirmish_destroy( &shared->reactor_globals );
+ fusion_skirmish_destroy( &shared->arenas_lock );
+ fusion_skirmish_destroy( &shared->fusionees_lock );
+
+ fusion_shm_pool_destroy( world, shared->main_pool );
+
+ /* Deinitialize shared memory. */
+ fusion_shm_deinit( world );
+
+ clear = true;
+ }
+ }
+ else {
+ /* Leave shared memory. */
+ fusion_shm_deinit( world );
+ }
+
+ /* Reset local dispatch nodes. */
+ _fusion_reactor_free_all( world );
+
+ /* Remove world from global list. */
+ fusion_worlds[shared->world_index] = NULL;
+
+ /* Unmap shared area. */
+ if (clear)
+ D_MAGIC_CLEAR( shared );
+
+ munmap( shared, sizeof(FusionWorldShared) );
+
+ /* Close socket. */
+ close( world->fusion_fd );
+
+ if (clear) {
+ DIR *dir;
+ char buf[128];
+ int len;
+
+ /* Remove core shmfile. */
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.core",
+ fusion_config->tmpfs ? : "/dev/shm", world_index );
+ D_DEBUG_AT( Fusion_Main, "Removing shmfile %s.\n", buf );
+ unlink( buf );
+
+ /* Cleanup socket directory. */
+ len = snprintf( buf, sizeof(buf), "/tmp/.fusion-%d/", world_index );
+ dir = opendir( buf );
+ if (dir) {
+ struct dirent *entry = NULL;
+ struct dirent tmp;
+
+ while (readdir_r( dir, &tmp, &entry ) == 0 && entry) {
+ if (entry->d_name[0] != '.') {
+ struct stat st;
+
+ direct_snputs( buf+len, entry->d_name, sizeof(buf)-len );
+ if (stat( buf, &st ) == 0 && S_ISSOCK(st.st_mode)) {
+ D_DEBUG_AT( Fusion_Main, "Removing socket %s.\n", buf );
+ unlink( buf );
+ }
+ }
+ }
+
+ closedir( dir );
+ }
+ else {
+ D_PERROR( "Fusion/Main: Couldn't open socket directory %s", buf );
+ }
+ }
+
+ /* Free local world data. */
+ D_MAGIC_CLEAR( world );
+ D_FREE( world );
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p ) done.\n", __FUNCTION__, world );
+
+ pthread_mutex_unlock( &fusion_worlds_lock );
+
+ direct_shutdown();
+
+ return DR_OK;
+}
+
+/*
+ * Sends a signal to one or more fusionees and optionally waits
+ * for their processes to terminate.
+ *
+ * A fusion_id of zero means all fusionees but the calling one.
+ * A timeout of zero means infinite waiting while a negative value
+ * means no waiting at all.
+ */
+DirectResult
+fusion_kill( FusionWorld *world,
+ FusionID fusion_id,
+ int signal,
+ int timeout_ms )
+{
+ FusionWorldShared *shared;
+ __Fusionee *fusionee, *temp;
+ int result;
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p, %lu, %d, %d )\n",
+ __FUNCTION__, world, fusion_id, signal, timeout_ms );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ fusion_skirmish_prevail( &shared->fusionees_lock );
+
+ direct_list_foreach_safe (fusionee, temp, shared->fusionees) {
+ if (fusion_id == 0 && fusionee->id == world->fusion_id)
+ continue;
+
+ if (fusion_id != 0 && fusionee->id != fusion_id)
+ continue;
+
+ D_DEBUG_AT( Fusion_Main, " -> killing fusionee %lu (%d)...\n", fusionee->id, fusionee->pid );
+
+ result = kill( fusionee->pid, signal );
+ if (result == 0 && timeout_ms >= 0) {
+ pid_t pid = fusionee->pid;
+ long long stop = timeout_ms ? (direct_clock_get_micros() + timeout_ms*1000) : 0;
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+
+ while (kill( pid, 0 ) == 0) {
+ usleep( 1000 );
+
+ if (timeout_ms && direct_clock_get_micros() >= stop)
+ break;
+ };
+
+ fusion_skirmish_prevail( &shared->fusionees_lock );
+ }
+ else if (result < 0) {
+ if (errno == ESRCH) {
+ D_DEBUG_AT( Fusion_Main, " ... fusionee %lu exited without removing itself!\n", fusionee->id );
+
+ _fusion_remove_fusionee( world, fusionee->id );
+ }
+ else {
+ D_PERROR( "Fusion/Main: kill(%d, %d)\n", fusionee->pid, signal );
+ }
+ }
+ }
+
+ fusion_skirmish_dismiss( &shared->fusionees_lock );
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+static void *
+fusion_dispatch_loop( DirectThread *self, void *arg )
+{
+ FusionWorld *world = arg;
+ struct sockaddr_un addr;
+ socklen_t addr_len = sizeof(addr);
+ fd_set set;
+ char buf[FUSION_MESSAGE_SIZE];
+
+ D_DEBUG_AT( Fusion_Main_Dispatch, "%s() running...\n", __FUNCTION__ );
+
+ while (true) {
+ int result;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ FD_ZERO( &set );
+ FD_SET( world->fusion_fd, &set );
+
+ result = select( world->fusion_fd + 1, &set, NULL, NULL, NULL );
+ if (result < 0) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ default:
+ D_PERROR( "Fusion/Dispatcher: select() failed!\n" );
+ return NULL;
+ }
+ }
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ if (FD_ISSET( world->fusion_fd, &set ) &&
+ recvfrom( world->fusion_fd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &addr_len ) > 0) {
+ FusionMessage *msg = (FusionMessage*)buf;
+
+ pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL );
+
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> message from '%s'...\n", addr.sun_path );
+
+ direct_thread_lock( world->dispatch_loop );
+
+ if (world->dispatch_stop) {
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> IGNORING (dispatch_stop!)\n" );
+ }
+ else {
+ switch (msg->type) {
+ case FMT_SEND:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_SEND...\n" );
+ break;
+
+ case FMT_ENTER:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_ENTER...\n" );
+ if (!fusion_master( world )) {
+ D_ERROR( "Fusion/Dispatch: Got ENTER request, but I'm not master!\n" );
+ break;
+ }
+ if (msg->enter.fusion_id == world->fusion_id) {
+ D_ERROR( "Fusion/Dispatch: Received ENTER request from myself!\n" );
+ break;
+ }
+ /* Nothing to do here. Send back message. */
+ _fusion_send_message( world->fusion_fd, msg, sizeof(FusionEnter), &addr );
+ break;
+
+ case FMT_LEAVE:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_LEAVE...\n" );
+ if (!fusion_master( world )) {
+ D_ERROR( "Fusion/Dispatch: Got LEAVE request, but I'm not master!\n" );
+ break;
+ }
+ if (msg->leave.fusion_id == world->fusion_id) {
+ D_ERROR( "Fusion/Dispatch: Received LEAVE request from myself!\n" );
+ break;
+ }
+ _fusion_remove_fusionee( world, msg->leave.fusion_id );
+ break;
+
+ case FMT_CALL:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_CALL...\n" );
+ _fusion_call_process( world, msg->call.call_id, &msg->call );
+ break;
+
+ case FMT_REACTOR:
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> FMT_REACTOR...\n" );
+ _fusion_reactor_process_message( world, msg->reactor.id, msg->reactor.channel,
+ &buf[sizeof(FusionReactorMessage)] );
+ if (msg->reactor.ref) {
+ fusion_ref_down( msg->reactor.ref, true );
+ if (fusion_ref_zero_trylock( msg->reactor.ref ) == DR_OK) {
+ fusion_ref_destroy( msg->reactor.ref );
+ SHFREE( world->shared->main_pool, msg->reactor.ref );
+ }
+ }
+ break;
+
+ default:
+ D_BUG( "unexpected message type (%d)", msg->type );
+ break;
+ }
+ }
+
+ direct_thread_unlock( world->dispatch_loop );
+
+ if (!world->refs) {
+ D_DEBUG_AT( Fusion_Main_Dispatch, " -> good bye!\n" );
+ return NULL;
+ }
+
+ D_DEBUG_AT( Fusion_Main_Dispatch, " ...done\n" );
+
+ pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
+ }
+ }
+
+ return NULL;
+}
+
+/**********************************************************************************************************************/
+
+#endif /* FUSION_BUILD_KERNEL */
+
+/*
+ * Wait until all pending messages are processed.
+ */
+DirectResult
+fusion_sync( const FusionWorld *world )
+{
+ int result;
+ fd_set set;
+ struct timeval tv;
+ int loops = 200;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_DEBUG_AT( Fusion_Main, "%s( %p )\n", __FUNCTION__, world );
+
+ D_DEBUG_AT( Fusion_Main, "syncing with fusion device...\n" );
+
+ while (loops--) {
+ FD_ZERO( &set );
+ FD_SET( world->fusion_fd, &set );
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 20000;
+
+ result = select( world->fusion_fd + 1, &set, NULL, NULL, &tv );
+ D_DEBUG_AT( Fusion_Main, " -> select() returned %d...\n", result );
+ switch (result) {
+ case -1:
+ if (errno == EINTR)
+ return DR_OK;
+
+ D_PERROR( "Fusion/Sync: select() failed!\n");
+ return DR_FAILURE;
+
+ default:
+ D_DEBUG_AT( Fusion_Main, " -> FD_ISSET %d...\n", FD_ISSET( world->fusion_fd, &set ) );
+
+ if (FD_ISSET( world->fusion_fd, &set )) {
+ usleep( 20000 );
+ break;
+ }
+
+ case 0:
+ D_DEBUG_AT( Fusion_Main, " -> synced.\n");
+ return DR_OK;
+ }
+ }
+
+ D_DEBUG_AT( Fusion_Main, " -> timeout!\n");
+
+ D_ERROR( "Fusion/Main: Timeout waiting for empty message queue!\n" );
+
+ return DR_TIMEOUT;
+}
+
+/*
+ * Sets the fork() action of the calling Fusionee within the world.
+ */
+void
+fusion_world_set_fork_action( FusionWorld *world,
+ FusionForkAction action )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ world->fork_action = action;
+}
+
+/*
+ * Gets the current fork() action.
+ */
+FusionForkAction
+fusion_world_get_fork_action( FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world->fork_action;
+}
+
+/*
+ * Registers a callback called upon fork().
+ */
+void
+fusion_world_set_fork_callback( FusionWorld *world,
+ FusionForkCallback callback )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ world->fork_callback = callback;
+}
+
+/*
+ * Return the index of the specified world.
+ */
+int
+fusion_world_index( const FusionWorld *world )
+{
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ return shared->world_index;
+}
+
+/*
+ * Return the own Fusion ID within the specified world.
+ */
+FusionID
+fusion_id( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world->fusion_id;
+}
+
+/*
+ * Return if the world is a multi application world.
+ */
+bool
+fusion_is_multi( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return true;
+}
+
+/*
+ * Return the thread ID of the Fusion Dispatcher within the specified world.
+ */
+pid_t
+fusion_dispatcher_tid( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return direct_thread_get_tid( world->dispatch_loop );
+}
+
+/*
+ * Return true if this process is the master.
+ */
+bool
+fusion_master( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world->fusion_id == FUSION_ID_MASTER;
+}
+
+/*
+ * Check if a pointer points to the shared memory.
+ */
+bool
+fusion_is_shared( FusionWorld *world,
+ const void *ptr )
+{
+ int i;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shm = &world->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ if (ptr >= (void*) world->shared && ptr < (void*) world->shared + sizeof(FusionWorldShared))
+ return true;
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return false;
+
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (shared->pools[i].active) {
+ shmalloc_heap *heap;
+ FusionSHMPoolShared *pool = &shared->pools[i];
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ heap = pool->heap;
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ if (ptr >= pool->addr_base && ptr < pool->addr_base + heap->size) {
+ fusion_skirmish_dismiss( &shared->lock );
+ return true;
+ }
+ }
+ }
+
+ fusion_skirmish_dismiss( &shared->lock );
+
+ return false;
+}
+
+#else /* FUSION_BUILD_MULTI */
+
+/*
+ * Enters a fusion world by joining or creating it.
+ *
+ * If <b>world_index</b> is negative, the next free index is used to create a new world.
+ * Otherwise the world with the specified index is joined or created.
+ */
+DirectResult fusion_enter( int world_index,
+ int abi_version,
+ FusionEnterRole role,
+ FusionWorld **ret_world )
+{
+ DirectResult ret;
+ FusionWorld *world = NULL;
+
+ D_ASSERT( ret_world != NULL );
+
+ ret = direct_initialize();
+ if (ret)
+ return ret;
+
+ world = D_CALLOC( 1, sizeof(FusionWorld) );
+ if (!world) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ world->shared = D_CALLOC( 1, sizeof(FusionWorldShared) );
+ if (!world->shared) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ /* Create the main pool. */
+ ret = fusion_shm_pool_create( world, "Fusion Main Pool", 0x100000,
+ fusion_config->debugshm, &world->shared->main_pool );
+ if (ret)
+ goto error;
+
+ D_MAGIC_SET( world, FusionWorld );
+ D_MAGIC_SET( world->shared, FusionWorldShared );
+
+ *ret_world = world;
+
+ return DR_OK;
+
+
+error:
+ if (world) {
+ if (world->shared)
+ D_FREE( world->shared );
+
+ D_FREE( world );
+ }
+
+ direct_shutdown();
+
+ return ret;
+}
+
+DirectResult
+fusion_stop_dispatcher( FusionWorld *world,
+ bool emergency )
+{
+ return DR_OK;
+}
+
+/*
+ * Exits the fusion world.
+ *
+ * If 'emergency' is true the function won't join but kill the dispatcher thread.
+ */
+DirectResult
+fusion_exit( FusionWorld *world,
+ bool emergency )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+
+ fusion_shm_pool_destroy( world, world->shared->main_pool );
+
+ D_MAGIC_CLEAR( world->shared );
+
+ D_FREE( world->shared );
+
+ D_MAGIC_CLEAR( world );
+
+ D_FREE( world );
+
+ direct_shutdown();
+
+ return DR_OK;
+}
+
+/*
+ * Sets the fork() action of the calling Fusionee within the world.
+ */
+void
+fusion_world_set_fork_action( FusionWorld *world,
+ FusionForkAction action )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+}
+
+/*
+ * Gets the current fork() action.
+ */
+FusionForkAction
+fusion_world_get_fork_action( FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return world->fork_action;
+}
+
+/*
+ * Registers a callback called upon fork().
+ */
+void
+fusion_world_set_fork_callback( FusionWorld *world,
+ FusionForkCallback callback )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+}
+
+/*
+ * Return the index of the specified world.
+ */
+int
+fusion_world_index( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return 0;
+}
+
+
+/*
+ * Return true if this process is the master.
+ */
+bool
+fusion_master( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return true;
+}
+
+/*
+ * Sends a signal to one or more fusionees and optionally waits
+ * for their processes to terminate.
+ *
+ * A fusion_id of zero means all fusionees but the calling one.
+ * A timeout of zero means infinite waiting while a negative value
+ * means no waiting at all.
+ */
+DirectResult
+fusion_kill( FusionWorld *world,
+ FusionID fusion_id,
+ int signal,
+ int timeout_ms )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return DR_OK;
+}
+
+/*
+ * Return the own Fusion ID within the specified world.
+ */
+FusionID
+fusion_id( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return 1;
+}
+
+/*
+ * Return if the world is a multi application world.
+ */
+bool
+fusion_is_multi( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return false;
+}
+
+/*
+ * Wait until all pending messages are processed.
+ */
+DirectResult
+fusion_sync( const FusionWorld *world )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return DR_OK;
+}
+
+/* Check if a pointer points to the shared memory. */
+bool
+fusion_is_shared( FusionWorld *world,
+ const void *ptr )
+{
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ return true;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/fusion.h b/Source/DirectFB/lib/fusion/fusion.h
new file mode 100755
index 0000000..bfe3da2
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/fusion.h
@@ -0,0 +1,142 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__FUSION_H__
+#define __FUSION__FUSION_H__
+
+#include <sys/types.h>
+
+#include <fusion/types.h>
+
+typedef enum {
+ FER_ANY,
+ FER_MASTER,
+ FER_SLAVE
+} FusionEnterRole;
+
+typedef enum {
+ FFA_CLOSE,
+ FFA_FORK
+} FusionForkAction;
+
+typedef enum {
+ FFS_PREPARE,
+ FFS_PARENT,
+ FFS_CHILD
+} FusionForkState;
+
+typedef void (*FusionForkCallback) ( FusionForkAction action, FusionForkState state );
+
+/*
+ * Enters a fusion world by joining or creating it.
+ *
+ * If <b>world_index</b> is negative, the next free index is used to create a new world.
+ * Otherwise the world with the specified index is joined or created.
+ */
+DirectResult fusion_enter( int world_index,
+ int abi_version,
+ FusionEnterRole role,
+ FusionWorld **ret_world );
+
+/*
+ * Exits the fusion world.
+ *
+ * If 'emergency' is true the function won't join but kill the dispatcher thread.
+ */
+DirectResult fusion_exit( FusionWorld *world,
+ bool emergency );
+
+DirectResult fusion_stop_dispatcher( FusionWorld *world,
+ bool emergency );
+
+/*
+ * Sets the fork() action of the calling Fusionee within the world.
+ */
+void fusion_world_set_fork_action( FusionWorld *world,
+ FusionForkAction action );
+
+/*
+ * Gets the current fork() action.
+ */
+FusionForkAction fusion_world_get_fork_action( FusionWorld *world );
+
+/*
+ * Registers a callback called upon fork().
+ */
+void fusion_world_set_fork_callback( FusionWorld *world,
+ FusionForkCallback callback );
+
+/*
+ * Return the index of the specified world.
+ */
+int fusion_world_index( const FusionWorld *world );
+
+/*
+ * Return the own Fusion ID within the specified world.
+ */
+FusionID fusion_id( const FusionWorld *world );
+
+/*
+ * Return if the world is a multi application world.
+ */
+bool fusion_is_multi( const FusionWorld *world );
+
+/*
+ * Return the thread ID of the Fusion Dispatcher within the specified world.
+ */
+pid_t fusion_dispatcher_tid( const FusionWorld *world );
+
+/*
+ * Return true if this process is the master.
+ */
+bool fusion_master( const FusionWorld *world );
+
+/*
+ * Wait until all pending messages are processed.
+ */
+DirectResult fusion_sync( const FusionWorld *world );
+
+/*
+ * Sends a signal to one or more fusionees and optionally waits
+ * for their processes to terminate.
+ *
+ * A fusion_id of zero means all fusionees but the calling one.
+ * A timeout of zero means infinite waiting while a negative value
+ * means no waiting at all.
+ */
+DirectResult fusion_kill( FusionWorld *world,
+ FusionID fusion_id,
+ int signal,
+ int timeout_ms );
+
+/* Check if a pointer points to the shared memory. */
+bool fusion_is_shared( FusionWorld *world,
+ const void *ptr );
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/fusion.pc.in b/Source/DirectFB/lib/fusion/fusion.pc.in
new file mode 100755
index 0000000..09cf78c
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/fusion.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Fusion IPC
+Description: High Level IPC Mechanisms
+Version: @VERSION@
+Requires: direct
+Libs: -L${libdir} -lfusion
+Cflags: -I@INCLUDEDIR@
diff --git a/Source/DirectFB/lib/fusion/fusion_internal.h b/Source/DirectFB/lib/fusion/fusion_internal.h
new file mode 100755
index 0000000..5e7c474
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/fusion_internal.h
@@ -0,0 +1,185 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__FUSION_INTERNAL_H__
+#define __FUSION__FUSION_INTERNAL_H__
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <string.h>
+
+#include <direct/list.h>
+
+#include <fusion/build.h>
+#include <fusion/fusion.h>
+#include <fusion/lock.h>
+#include <fusion/ref.h>
+#include <fusion/shm/shm_internal.h>
+
+#if FUSION_BUILD_MULTI
+# if FUSION_BUILD_KERNEL
+# include <sys/ioctl.h>
+# include <linux/fusion.h>
+# else
+# include <fusion/protocol.h>
+# endif
+#endif
+
+#define FUSION_MAX_WORLDS 8
+
+/***************************************
+ * Fusion internal type declarations *
+ ***************************************/
+
+struct __Fusion_FusionWorldShared {
+ int magic;
+
+ int refs; /* Increased by the master on fork(). */
+
+ int world_index;
+
+ int world_abi;
+
+ struct timeval start_time;
+
+ DirectLink *arenas;
+ FusionSkirmish arenas_lock;
+
+ FusionSkirmish reactor_globals;
+
+ FusionSHMShared shm;
+
+ FusionSHMPoolShared *main_pool;
+
+ DirectLink *fusionees; /* Connected fusionees. */
+ FusionSkirmish fusionees_lock;
+
+ unsigned int call_ids; /* Generates call ids. */
+ unsigned int lock_ids; /* Generates locks ids. */
+ unsigned int ref_ids; /* Generates refs ids. */
+ unsigned int reactor_ids; /* Generates reactors ids. */
+ unsigned int pool_ids; /* Generates pools ids. */
+
+ void *pool_base; /* SHM pool allocation base. */
+ void *pool_max; /* SHM pool max address. */
+};
+
+struct __Fusion_FusionWorld {
+ int magic;
+
+ int refs;
+
+ FusionWorldShared *shared;
+
+ int fusion_fd;
+ FusionID fusion_id;
+
+ DirectThread *dispatch_loop;
+ bool dispatch_stop;
+
+ /*
+ * List of reactors with at least one local reaction attached.
+ */
+ DirectLink *reactor_nodes;
+ pthread_mutex_t reactor_nodes_lock;
+
+ FusionSHM shm;
+
+ FusionForkAction fork_action;
+ FusionForkCallback fork_callback;
+
+ void *fusionee;
+};
+
+/*******************************************
+ * Fusion internal function declarations *
+ *******************************************/
+
+int _fusion_fd( const FusionWorldShared *shared );
+FusionID _fusion_id( const FusionWorldShared *shared );
+
+FusionWorld *_fusion_world( const FusionWorldShared *shared );
+
+/*
+ * from reactor.c
+ */
+void _fusion_reactor_free_all ( FusionWorld *world );
+void _fusion_reactor_process_message( FusionWorld *world,
+ int reactor_id,
+ int channel,
+ const void *msg_data );
+
+
+#if FUSION_BUILD_MULTI
+/*
+ * from call.c
+ */
+void _fusion_call_process( FusionWorld *world,
+ int call_id,
+ FusionCallMessage *call );
+
+#if FUSION_BUILD_KERNEL
+/*
+ * from shm.c
+ */
+void _fusion_shmpool_process( FusionWorld *world,
+ int pool_id,
+ FusionSHMPoolMessage *msg );
+#else
+/*
+ * form fusion.c
+ */
+void _fusion_add_local( FusionWorld *world,
+ FusionRef *ref,
+ int add );
+
+void _fusion_check_locals( FusionWorld *world,
+ FusionRef *ref );
+
+void _fusion_remove_all_locals( FusionWorld *world,
+ const FusionRef *ref );
+
+DirectResult _fusion_send_message( int fd,
+ const void *msg,
+ size_t msg_size,
+ struct sockaddr_un *addr );
+DirectResult _fusion_recv_message( int fd,
+ void *msg,
+ size_t msg_size,
+ struct sockaddr_un *addr );
+
+/*
+ * from ref.c
+ */
+DirectResult _fusion_ref_change( FusionRef *ref, int add, bool global );
+
+#endif /* FUSION_BUILD_KERNEL */
+#endif /* FUSION_BUILD_MULTI */
+
+#endif
diff --git a/Source/DirectFB/lib/fusion/hash.c b/Source/DirectFB/lib/fusion/hash.c
new file mode 100755
index 0000000..06723d2
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/hash.c
@@ -0,0 +1,560 @@
+/*
+ GLIB - Library of useful routines for C programming
+ Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi>,
+ Claudio Ciccani <klan@users.sf.net> and
+ Michael Emmel <mike.emmel@gmail.com>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/util.h>
+#include <fusion/object.h>
+#include <fusion/shmalloc.h>
+#include <fusion/hash.h>
+
+
+D_DEBUG_DOMAIN( Fusion_Hash, "Fusion/Hash", "Hash table implementation" );
+
+
+
+
+static const unsigned int primes[] =
+{
+ 11,
+ 19,
+ 37,
+ 73,
+ 109,
+ 163,
+ 251,
+ 367,
+ 557,
+ 823,
+ 1237,
+ 1861,
+ 2777,
+ 4177,
+ 6247,
+ 9371,
+ 14057,
+ 21089,
+ 31627,
+ 47431,
+ 71143,
+ 106721,
+ 160073,
+ 240101,
+ 360163,
+ 540217,
+ 810343,
+ 1215497,
+ 1823231,
+ 2734867,
+ 4102283,
+ 6153409,
+ 9230113,
+ 13845163,
+};
+
+
+static const unsigned int nprimes = D_ARRAY_SIZE( primes );
+
+static DirectResult
+fusion_hash_create_internal(bool type,FusionSHMPoolShared *pool,
+ FusionHashType key_type,
+ FusionHashType value_type,
+ int size, FusionHash **ret_hash );
+
+static void
+fusion_hash_node_destroy (FusionHash *hash,FusionHashNode *node,
+ void **old_key,void **old_value);
+
+static unsigned int
+spaced_primes_closest (unsigned int num)
+{
+ int i;
+ for (i = 0; i < nprimes; i++)
+ if (primes[i] > num)
+ return primes[i];
+ return primes[nprimes - 1];
+}
+
+/**
+ * fusion_hash_create_local:
+ * @key_type: Type of hash key the hash is optimized for strings ints and pointers
+ * @value_type: Type of hash data optimized for strings ints and pointers
+ * @size: Inital size of the hash table
+ * @ret_hash:the new hash table
+ * Creates a new #FusionHash that uses local memory
+ *
+ * Return value: a new #FusionHash.
+ **/
+DirectResult
+fusion_hash_create_local (FusionHashType key_type, FusionHashType value_type,
+ int size, FusionHash **ret_hash )
+{
+ return fusion_hash_create_internal(true,NULL,key_type,value_type,
+ size,ret_hash );
+
+}
+
+/**
+ * fusion_hash_create:
+ * @key_type: Type of hash key the hash is optimized for strings ints and pointers
+ * @value_type: Type of hash data optimized for strings ints and pointers
+ * @size: Inital size of the hash table
+ * @ret_hash:the new hash table
+ * Creates a new #FusionHash with a reference count of 1.
+ *
+ * Return value: a new #FusionHash.
+ **/
+DirectResult
+fusion_hash_create (FusionSHMPoolShared *pool,
+ FusionHashType key_type,
+ FusionHashType value_type,
+ int size, FusionHash **ret_hash )
+{
+ return fusion_hash_create_internal(false,pool,key_type,value_type,
+ size,ret_hash );
+}
+
+static DirectResult
+fusion_hash_create_internal (bool local,FusionSHMPoolShared *pool,
+ FusionHashType key_type,
+ FusionHashType value_type,
+ int size, FusionHash **ret_hash )
+{
+ FusionHash *hash;
+
+ if (!ret_hash)
+ return DR_BUG;
+ if (!local && !pool)
+ return DR_BUG;
+
+ if (size < FUSION_HASH_MIN_SIZE)
+ size = FUSION_HASH_MIN_SIZE;
+
+ if (local)
+ hash = D_CALLOC(1, sizeof (FusionHash) );
+ else
+ hash = SHCALLOC(pool, 1, sizeof (FusionHash) );
+
+ if (!hash)
+ return local ?DR_NOLOCALMEMORY:DR_NOSHAREDMEMORY;
+
+ hash->local = local;
+ hash->pool = pool;
+ hash->key_type = key_type;
+ hash->value_type = value_type;
+ hash->size = size;
+ hash->nnodes = 0;
+ if (local)
+ hash->nodes = D_CALLOC(size,sizeof (FusionHashNode*) );
+ else
+ hash->nodes = SHCALLOC(pool, size, sizeof(FusionHashNode*) );
+
+ if (!hash->nodes) {
+ if (local)
+ D_FREE(hash );
+ else
+ SHFREE(pool, hash );
+ return local?DR_NOLOCALMEMORY:DR_NOSHAREDMEMORY;
+ }
+
+ D_MAGIC_SET(hash, FusionHash );
+
+ *ret_hash = hash;
+
+ return DR_OK;
+}
+
+void
+fusion_hash_destroy( FusionHash *hash )
+{
+ int i;
+ FusionHashNode *node, *next;
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ for (i = 0; i < hash->size; i++) {
+ for (node = hash->nodes[i]; node; node = next) {
+ next = node->next;
+ fusion_hash_node_destroy(hash, node, NULL, NULL);
+ }
+ }
+ if (hash->local)
+ D_FREE(hash->nodes);
+ else
+ SHFREE( hash->pool, hash->nodes );
+ D_MAGIC_CLEAR( hash );
+ if (hash->local)
+ D_FREE(hash);
+ else
+ SHFREE( hash->pool, hash );
+}
+
+void
+fusion_hash_set_autofree( FusionHash *hash, bool free_keys, bool free_values )
+{
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ hash->free_keys = free_keys;
+ hash->free_values = free_values;
+}
+
+/**
+ * fusion_hash_lookup:
+ * @hash: a #FusionHash.
+ * @key: the key to look up.
+ *
+ * Looks up a key in a #FusionHash. Note that this function cannot
+ * distinguish between a key that is not present and one which is present
+ * and has the value %NULL. If you need this distinction, use
+ * hash_lookup_extended().
+ *
+ * Return value: the associated value, or %NULL if the key is not found.
+ **/
+void *
+fusion_hash_lookup (FusionHash *hash, const void * key)
+{
+ FusionHashNode *node;
+ D_MAGIC_ASSERT( hash, FusionHash );
+ node = *fusion_hash_lookup_node (hash, key);
+ return node ? node->value : NULL;
+}
+
+/**
+ * fusion_hash_insert:
+ * @hash: a #FusionHash.
+ * @key: a key to insert.
+ * @value: the value to associate with the key.
+ *
+ * Inserts a new key and value into a #FusionHash.
+ * If the key already exists in the #FusionHash DR_BUG is returned
+ * If you think a key may exist you should call fusion_hash_replace
+ * Generally this is only used on a new FusionHash
+ **/
+DirectResult
+fusion_hash_insert( FusionHash *hash,
+ void *key,
+ void *value )
+{
+ FusionHashNode **node;
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ node = fusion_hash_lookup_node (hash, key);
+
+ if (*node) {
+ D_BUG( "key already exists" );
+ return DR_BUG;
+ }
+ else {
+ if (hash->local)
+ (*node) = D_CALLOC(1,sizeof(FusionHashNode));
+ else
+ (*node) = SHCALLOC(hash->pool, 1, sizeof(FusionHashNode));
+ if ( !(*node) )
+ return hash->local?DR_NOLOCALMEMORY:DR_NOSHAREDMEMORY;
+
+ (*node)->key = key;
+ (*node)->value = value;
+ hash->nnodes++;
+ if ( fusion_hash_should_resize(hash) )
+ fusion_hash_resize(hash);
+ }
+ return DR_OK;
+}
+
+/**
+ * hash_replace:
+ * @hash: a #FusionHash.
+ * @key: a key to insert.
+ * @value: the value to associate with the key.
+ *
+ * Inserts a new key and value into a #FusionHash similar to
+ * hash_insert(). The difference is that if the key already exists
+ * in the #FusionHash, it gets replaced by the new key.
+ * If you supplied a oldkey pointer or oldkey value they are returned
+ * otherwise free is called the key if table type is not type HASH_INT
+ * and free is called on the old value if not supplied
+ **/
+DirectResult
+fusion_hash_replace (FusionHash *hash,
+ void * key,
+ void * value,
+ void **old_key,
+ void **old_value)
+{
+ FusionHashNode **node;
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ node = fusion_hash_lookup_node (hash, key);
+
+ if (*node) {
+ if ( old_key)
+ *old_key = (*node)->key;
+ else if ( hash->key_type != HASH_INT ) {
+ if (hash->free_keys) {
+ if (hash->local)
+ D_FREE((*node)->key);
+ else
+ SHFREE(hash->pool, (*node)->key );
+ }
+ }
+
+ if ( old_value)
+ *old_value = (*node)->value;
+ else if ( hash->value_type != HASH_INT ) {
+ if (hash->free_values) {
+ if (hash->local)
+ D_FREE((*node)->value);
+ else
+ SHFREE(hash->pool, (*node)->value );
+ }
+ }
+ }
+ else {
+ if (hash->local)
+ *node = D_CALLOC(1, sizeof(FusionHashNode));
+ else
+ *node = SHCALLOC(hash->pool, 1, sizeof(FusionHashNode));
+
+ if ( !(*node) )
+ return hash->local?DR_NOLOCALMEMORY:DR_NOSHAREDMEMORY;
+
+ hash->nnodes++;
+ }
+ (*node)->key = (void*)key;
+ (*node)->value = (void*)value;
+
+ return DR_OK;
+}
+
+/**
+ * fusion_hash_remove:
+ * @hash: a #FusionHash.
+ * @key: the key to remove.
+ * @old_key: returned old_key
+ * @old_value: returned old_value
+ * Removes a key and its associated value from a #FusionHash.
+ *
+ * If the #FusionHash was created using hash_new_full(), the
+ * key and value are freed using the supplied destroy functions, otherwise
+ * you have to make sure that any dynamically allocated values are freed
+ * yourself.
+ * If you supplied a oldkey pointer or oldkey value they are returned
+ * otherwise free is called the key if table type is not type HASH_INT
+ * and free is called on the old value if not supplied
+ *
+ **/
+DirectResult
+fusion_hash_remove (FusionHash *hash,
+ const void * key,
+ void **old_key,
+ void **old_value)
+{
+ FusionHashNode **node, *dest;
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ node = fusion_hash_lookup_node (hash, key);
+ if (*node) {
+ dest = *node;
+ (*node) = dest->next;
+ fusion_hash_node_destroy(hash, dest, old_key, old_value);
+ hash->nnodes--;
+ return DR_OK;
+ }
+ return DR_OK;
+}
+
+/**
+ * hash_foreach:
+ * @hash: a #FusionHash.
+ * @func: the function to call for each key/value pair.
+ * @user_data: user data to pass to the function.
+ *
+ * Calls the given function for each of the key/value pairs in the
+ * #FusionHash. The function is passed the key and value of each
+ * pair, and the given @user_data parameter. The hash table may not
+ * be modified while iterating over it (you can't add/remove
+ * items). To remove all items matching a predicate, use
+ * hash_foreach_remove().
+ **/
+void
+fusion_hash_iterate( FusionHash *hash,
+ FusionHashIteratorFunc func,
+ void *ctx )
+{
+ int i;
+ FusionHashNode *node;
+ FusionHashNode *next;
+
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ for (i = 0; i < hash->size; i++) {
+ for (node = hash->nodes[i]; node; node = next) {
+ next = node->next;
+
+ if ( func(hash, node->key, node->value, ctx))
+ return;
+ }
+ }
+}
+
+/**
+ * hash_size:
+ * @hash: a #FusionHash.
+ *
+ * Returns the number of elements contained in the #FusionHash.
+ *
+ * Return value: the number of key/value pairs in the #FusionHash.
+ **/
+unsigned int
+fusion_hash_size (FusionHash *hash)
+{
+ D_MAGIC_ASSERT( hash, FusionHash );
+ return hash->nnodes;
+}
+
+/**
+ * fusion_hash_should_resize:
+ * Call the function after adding or removing several
+ * values it has a decent heurisitc to determine if
+ * the hash has grown to large
+ */
+bool fusion_hash_should_resize ( FusionHash *hash)
+{
+ D_MAGIC_ASSERT( hash, FusionHash );
+ if ((hash->size >= 3 * hash->nnodes &&
+ hash->size > FUSION_HASH_MIN_SIZE) ||
+ (3 * hash->size <= hash->nnodes &&
+ hash->size < FUSION_HASH_MAX_SIZE))
+ return true;
+ return false;
+}
+
+/* Hash Functions
+ * Resize the hash to minumim for this number of entries
+ */
+DirectResult
+fusion_hash_resize (FusionHash *hash)
+{
+ FusionHashNode **new_nodes;
+ FusionHashNode *node;
+ FusionHashNode *next;
+ unsigned int hash_val;
+ int new_size;
+ int i;
+ D_MAGIC_ASSERT( hash, FusionHash );
+
+ new_size = spaced_primes_closest (hash->nnodes);
+ if (new_size > FUSION_HASH_MAX_SIZE )
+ new_size = FUSION_HASH_MAX_SIZE;
+ if (new_size < FUSION_HASH_MIN_SIZE)
+ new_size = FUSION_HASH_MIN_SIZE;
+
+ if (hash->local)
+ new_nodes = D_CALLOC (new_size, sizeof(FusionHashNode*));
+ else
+ new_nodes = SHCALLOC (hash->pool, new_size, sizeof(FusionHashNode*));
+ if (!new_nodes)
+ return hash->local?DR_NOLOCALMEMORY:DR_NOSHAREDMEMORY;
+
+ for (i = 0; i < hash->size; i++)
+ for (node = hash->nodes[i]; node; node = next) {
+ next = node->next;
+ /*TODO We could also optimize pointer hashing*/
+ if (hash->key_type == HASH_STRING ) {
+ unsigned int h;
+ const signed char *p = node->key;
+ HASH_STR(h, p)
+ hash_val = h % new_size;
+ }
+ else
+ hash_val = ((unsigned long)node->key) % new_size;
+
+ node->next = new_nodes[hash_val];
+ new_nodes[hash_val] = node;
+ }
+ if (hash->local)
+ D_FREE(hash->nodes);
+ else
+ SHFREE(hash->pool, hash->nodes);
+ hash->nodes = new_nodes;
+ hash->size = new_size;
+ return true;
+}
+
+
+static void
+fusion_hash_node_destroy (FusionHash *hash,FusionHashNode *node,
+ void **old_key,void **old_value)
+{
+ if (!node )
+ return;
+
+ if ( old_key)
+ *old_key = node->key;
+ else if ( hash->key_type != HASH_INT ) {
+ if (hash->free_keys) {
+ if ( hash->local)
+ D_FREE(node->key );
+ else
+ SHFREE(hash->pool,node->key );
+ }
+ }
+
+ if ( old_value)
+ *old_value = node->value;
+ else if ( hash->value_type != HASH_INT ) {
+ if (hash->free_values) {
+ if ( hash->local)
+ D_FREE(node->value );
+ else
+ SHFREE(hash->pool,node->value );
+ }
+ }
+
+ if ( hash->local)
+ D_FREE(node);
+ else
+ SHFREE(hash->pool,node);
+}
+
diff --git a/Source/DirectFB/lib/fusion/hash.h b/Source/DirectFB/lib/fusion/hash.h
new file mode 100755
index 0000000..8c8b459
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/hash.h
@@ -0,0 +1,179 @@
+/*
+ GLIB - Library of useful routines for C programming
+ Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi>,
+ Claudio Ciccani <klan@users.sf.net> and
+ Michael Emmel <memmel@gmail.com>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __FUSION_HASH_H__
+#define __FUSION_HASH_H__
+
+#include <fusion/types.h>
+#include <fusion/shmalloc.h>
+#include <string.h>
+
+#define FUSION_HASH_MIN_SIZE 11
+#define FUSION_HASH_MAX_SIZE 13845163
+
+#define HASH_STR(h,p) \
+{\
+ h = *p;\
+ if (h)\
+ for (p += 1; *p != '\0'; p++)\
+ h = (h << 5) - h + *p;\
+}\
+
+typedef enum {
+HASH_PTR,
+HASH_STRING,
+HASH_INT
+}
+FusionHashType;
+
+typedef struct _FusionHashNode FusionHashNode;
+
+struct _FusionHashNode
+{
+ void *key;
+ void *value;
+ FusionHashNode *next;
+};
+
+struct __Fusion_FusionHash
+{
+ int magic;
+ bool local;
+ FusionHashType key_type;
+ FusionHashType value_type;
+ int size;
+ int nnodes;
+ FusionHashNode **nodes;
+ FusionSHMPoolShared *pool;
+
+ bool free_keys;
+ bool free_values;
+};
+
+typedef bool (*FusionHashIteratorFunc)( FusionHash *hash,
+ void *key,
+ void *value,
+ void *ctx );
+
+
+DirectResult
+fusion_hash_resize (FusionHash *hash);
+
+DirectResult
+fusion_hash_create (FusionSHMPoolShared *pool,
+ FusionHashType key_type,
+ FusionHashType value_type,
+ int size, FusionHash **ret_hash );
+
+DirectResult
+fusion_hash_create_local (FusionHashType key_type, FusionHashType value_type,
+ int size, FusionHash **ret_hash );
+
+DirectResult
+fusion_hash_remove (FusionHash *hash,
+ const void * key,
+ void **old_key,
+ void **old_value);
+
+DirectResult
+fusion_hash_insert( FusionHash *hash, void *key, void *value );
+
+DirectResult
+fusion_hash_replace (FusionHash *hash,
+ void * key,
+ void * value,
+ void **old_key,
+ void **old_value);
+void
+fusion_hash_destroy( FusionHash *hash );
+
+void
+fusion_hash_set_autofree( FusionHash *hash, bool free_keys, bool free_values );
+
+void *
+fusion_hash_lookup (FusionHash *hash, const void * key);
+
+void
+fusion_hash_iterate( FusionHash *hash,
+ FusionHashIteratorFunc func,
+ void *ctx );
+
+unsigned int
+fusion_hash_size (FusionHash *hash);
+
+bool fusion_hash_should_resize ( FusionHash *hash);
+
+
+static inline FusionHashNode**
+fusion_hash_lookup_node (FusionHash *hash,
+ const void * key)
+{
+ FusionHashNode **node;
+
+ /*TODO We could also optimize pointer hashing*/
+ if (hash->key_type == HASH_STRING )
+ {
+ unsigned int h;
+ const signed char *p = key;
+ HASH_STR(h,p)
+ node = &hash->nodes[h % hash->size];
+ }
+ else
+ node = &hash->nodes[((unsigned long)key) % hash->size];
+
+ /* Hash table lookup needs to be fast.
+ * We therefore remove the extra conditional of testing
+ * whether to call the key_equal_func or not from
+ * the inner loop.
+ */
+ if (hash->key_type == HASH_STRING ) {
+ while(*node && strcmp((const char *)(*node)->key,(const char*)key))
+ node = &(*node)->next;
+ }
+ else
+ while (*node && (*node)->key != key)
+ node = &(*node)->next;
+
+ return node;
+
+}
+
+
+
+#endif /*__FUSION_HASH_H__*/
+
diff --git a/Source/DirectFB/lib/fusion/lock.c b/Source/DirectFB/lib/fusion/lock.c
new file mode 100755
index 0000000..33945c5
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/lock.c
@@ -0,0 +1,687 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/param.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/build.h>
+#include <fusion/types.h>
+#include <fusion/lock.h>
+#include <fusion/shmalloc.h>
+
+#include "fusion_internal.h"
+
+
+#if FUSION_BUILD_MULTI
+
+D_DEBUG_DOMAIN( Fusion_Skirmish, "Fusion/Skirmish", "Fusion's Skirmish (Mutex)" );
+
+
+#if FUSION_BUILD_KERNEL
+
+DirectResult
+fusion_skirmish_init( FusionSkirmish *skirmish,
+ const char *name,
+ const FusionWorld *world )
+{
+ FusionEntryInfo info;
+
+ D_ASSERT( skirmish != NULL );
+ D_ASSERT( name != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_DEBUG_AT( Fusion_Skirmish, "fusion_skirmish_init( %p, '%s' )\n", skirmish, name ? : "" );
+
+ while (ioctl( world->fusion_fd, FUSION_SKIRMISH_NEW, &skirmish->multi.id )) {
+ if (errno == EINTR)
+ continue;
+
+ D_PERROR( "FUSION_SKIRMISH_NEW" );
+ return DR_FUSION;
+ }
+
+ D_DEBUG_AT( Fusion_Skirmish, " -> new skirmish %p [%d]\n", skirmish, skirmish->multi.id );
+
+ info.type = FT_SKIRMISH;
+ info.id = skirmish->multi.id;
+
+ direct_snputs( info.name, name, sizeof(info.name) );
+
+ ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );
+
+ /* Keep back pointer to shared world data. */
+ skirmish->multi.shared = world->shared;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_prevail( FusionSkirmish *skirmish )
+{
+ D_ASSERT( skirmish != NULL );
+
+ while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_PREVAIL, &skirmish->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_PREVAIL");
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_swoop( FusionSkirmish *skirmish )
+{
+ D_ASSERT( skirmish != NULL );
+
+ while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_SWOOP, &skirmish->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EAGAIN:
+ return DR_BUSY;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_SWOOP");
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_lock_count( FusionSkirmish *skirmish, int *lock_count )
+{
+ int data[2];
+
+ D_ASSERT( skirmish != NULL );
+
+ data[0] = skirmish->multi.id;
+ data[1] = 0;
+
+ while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_LOCK_COUNT, data)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_LOCK_COUNT");
+ return DR_FUSION;
+ }
+
+ *lock_count = data[1];
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_dismiss (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_DISMISS, &skirmish->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_DISMISS");
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_destroy (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ D_DEBUG_AT( Fusion_Skirmish, "fusion_skirmish_destroy( %p [%d] )\n", skirmish, skirmish->multi.id );
+
+ while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_DESTROY, &skirmish->multi.id )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_DESTROY");
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_wait( FusionSkirmish *skirmish, unsigned int timeout )
+{
+ FusionSkirmishWait wait;
+
+ D_ASSERT( skirmish != NULL );
+
+ wait.id = skirmish->multi.id;
+ wait.timeout = timeout;
+ wait.lock_count = 0;
+
+ while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_WAIT, &wait)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case ETIMEDOUT:
+ return DR_TIMEOUT;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_WAIT");
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_notify( FusionSkirmish *skirmish )
+{
+ D_ASSERT( skirmish != NULL );
+
+ while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_NOTIFY, &skirmish->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR ("Fusion/Lock: invalid skirmish\n");
+ return DR_DESTROYED;
+ }
+
+ D_PERROR ("FUSION_SKIRMISH_NOTIFY");
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+#else /* FUSION_BUILD_KERNEL */
+
+#include <direct/clock.h>
+#include <direct/list.h>
+#include <direct/system.h>
+
+typedef struct {
+ DirectLink link;
+
+ pid_t pid;
+ bool notified;
+} WaitNode;
+
+
+DirectResult
+fusion_skirmish_init( FusionSkirmish *skirmish,
+ const char *name,
+ const FusionWorld *world )
+{
+ D_ASSERT( skirmish != NULL );
+ //D_ASSERT( name != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_DEBUG_AT( Fusion_Skirmish, "fusion_skirmish_init( %p, '%s' )\n",
+ skirmish, name ? : "" );
+
+ skirmish->multi.id = ++world->shared->lock_ids;
+
+ /* Set state to unlocked. */
+ skirmish->multi.builtin.locked = 0;
+ skirmish->multi.builtin.owner = 0;
+
+ skirmish->multi.builtin.waiting = NULL;
+
+ skirmish->multi.builtin.requested = false;
+ skirmish->multi.builtin.destroyed = false;
+
+ /* Keep back pointer to shared world data. */
+ skirmish->multi.shared = world->shared;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_prevail( FusionSkirmish *skirmish )
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ asm( "" ::: "memory" );
+
+ if (skirmish->multi.builtin.locked &&
+ skirmish->multi.builtin.owner != direct_gettid())
+ {
+ int count = 0;
+
+ while (skirmish->multi.builtin.locked) {
+ /* Check whether owner exited without unlocking. */
+ if (kill( skirmish->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) {
+ skirmish->multi.builtin.locked = 0;
+ skirmish->multi.builtin.requested = false;
+ break;
+ }
+
+ skirmish->multi.builtin.requested = true;
+
+ asm( "" ::: "memory" );
+
+ if (++count > 1000) {
+ usleep( 10000 );
+ count = 0;
+ }
+ else {
+ direct_sched_yield();
+ }
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+ }
+ }
+
+ skirmish->multi.builtin.locked++;
+ skirmish->multi.builtin.owner = direct_gettid();
+
+ asm( "" ::: "memory" );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_swoop( FusionSkirmish *skirmish )
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ asm( "" ::: "memory" );
+
+ if (skirmish->multi.builtin.locked &&
+ skirmish->multi.builtin.owner != direct_gettid()) {
+ /* Check whether owner exited without unlocking. */
+ if (kill( skirmish->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) {
+ skirmish->multi.builtin.locked = 0;
+ skirmish->multi.builtin.requested = false;
+ }
+ else
+ return DR_BUSY;
+ }
+
+ skirmish->multi.builtin.locked++;
+ skirmish->multi.builtin.owner = direct_gettid();
+
+ asm( "" ::: "memory" );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_lock_count( FusionSkirmish *skirmish, int *lock_count )
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (skirmish->multi.builtin.destroyed) {
+ *lock_count = 0;
+ return DR_DESTROYED;
+ }
+
+ *lock_count = skirmish->multi.builtin.locked;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_dismiss (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ asm( "" ::: "memory" );
+
+ if (skirmish->multi.builtin.locked) {
+ if (skirmish->multi.builtin.owner != direct_gettid()) {
+ D_ERROR( "Fusion/Skirmish: "
+ "Tried to dismiss a skirmish not owned by current process!\n" );
+ return DR_ACCESSDENIED;
+ }
+
+ if (--skirmish->multi.builtin.locked == 0) {
+ skirmish->multi.builtin.owner = 0;
+
+ if (skirmish->multi.builtin.requested) {
+ skirmish->multi.builtin.requested = false;
+ direct_sched_yield();
+ }
+ }
+ }
+
+ asm( "" ::: "memory" );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_destroy (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ D_DEBUG_AT( Fusion_Skirmish, "fusion_skirmish_destroy( %p )\n", skirmish );
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ if (skirmish->multi.builtin.waiting)
+ fusion_skirmish_notify( skirmish );
+
+ skirmish->multi.builtin.destroyed = true;
+
+ return DR_OK;
+}
+
+#ifdef SIGRTMAX
+# define SIGRESTART SIGRTMAX
+#else
+# define SIGRESTART SIGCONT
+#endif
+
+static void restart_handler( int s ) {}
+
+DirectResult
+fusion_skirmish_wait( FusionSkirmish *skirmish, unsigned int timeout )
+{
+ WaitNode *node;
+ long long stop;
+ struct sigaction act, oldact;
+ sigset_t mask, set;
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( skirmish != NULL );
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ /* Set timeout. */
+ stop = direct_clock_get_micros() + timeout * 1000ll;
+
+ /* Add ourself to the list of waiting processes. */
+ node = SHMALLOC( skirmish->multi.shared->main_pool, sizeof(WaitNode) );
+ if (!node)
+ return D_OOSHM();
+
+ node->pid = direct_gettid();
+ node->notified = false;
+
+ direct_list_append( &skirmish->multi.builtin.waiting, &node->link );
+
+ /* Install a (fake) signal handler for SIGRESTART. */
+ act.sa_handler = restart_handler;
+ act.sa_flags = SA_RESETHAND | SA_RESTART | SA_NOMASK;
+
+ sigaction( SIGRESTART, &act, &oldact );
+
+ /* Unblock SIGRESTART. */
+ sigprocmask( SIG_SETMASK, NULL, &mask );
+ sigdelset( &mask, SIGRESTART );
+
+ fusion_skirmish_dismiss( skirmish );
+
+ while (!node->notified) {
+ if (timeout) {
+ long long now = direct_clock_get_micros();
+
+ if (now >= stop) {
+ /* Stop notifying us. */
+ node->notified = true;
+ ret = DR_TIMEOUT;
+ break;
+ }
+
+ sigprocmask( SIG_SETMASK, &mask, &set );
+ usleep( stop - now );
+ sigprocmask( SIG_SETMASK, &set, NULL );
+ }
+ else {
+ sigsuspend( &mask );
+ }
+ }
+
+ /* Flush pending signals. */
+ if (!sigpending( &set ) && sigismember( &set, SIGRESTART ) > 0)
+ sigsuspend( &mask );
+
+ if (fusion_skirmish_prevail( skirmish ))
+ ret = DR_DESTROYED;
+
+ direct_list_remove( &skirmish->multi.builtin.waiting, &node->link );
+
+ SHFREE( skirmish->multi.shared->main_pool, node );
+
+ sigaction( SIGRESTART, &oldact, NULL );
+
+ return ret;
+}
+
+DirectResult
+fusion_skirmish_notify( FusionSkirmish *skirmish )
+{
+ WaitNode *node, *temp;
+
+ D_ASSERT( skirmish != NULL );
+
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ direct_list_foreach_safe (node, temp, skirmish->multi.builtin.waiting) {
+ if (node->notified)
+ continue;
+
+ node->notified = true;
+
+ if (kill( node->pid, SIGRESTART ) < 0) {
+ if (errno == ESRCH) {
+ /* Remove dead process. */
+ direct_list_remove( &skirmish->multi.builtin.waiting, &node->link );
+ SHFREE( skirmish->multi.shared->main_pool, node );
+ }
+ else {
+ D_PERROR( "Fusion/Skirmish: Couldn't send notification signal!\n" );
+ }
+ }
+ }
+
+ return DR_OK;
+}
+
+#endif /* FUSION_BUILD_KERNEL */
+
+#else /* FUSION_BUILD_MULTI */
+
+DirectResult
+fusion_skirmish_init( FusionSkirmish *skirmish,
+ const char *name,
+ const FusionWorld *world )
+{
+ D_ASSERT( skirmish != NULL );
+
+ direct_util_recursive_pthread_mutex_init( &skirmish->single.lock );
+ pthread_cond_init( &skirmish->single.cond, NULL );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_prevail (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (pthread_mutex_lock( &skirmish->single.lock ))
+ return errno2result( errno );
+
+ skirmish->single.count++;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_swoop (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (pthread_mutex_trylock( &skirmish->single.lock ))
+ return errno2result( errno );
+
+ skirmish->single.count++;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_lock_count( FusionSkirmish *skirmish, int *lock_count )
+{
+ D_ASSERT( skirmish != NULL );
+ D_ASSERT( lock_count != NULL );
+
+ if (pthread_mutex_trylock( &skirmish->single.lock )) {
+ *lock_count = 0;
+ return errno2result( errno );
+ }
+
+ *lock_count = skirmish->single.count;
+
+ pthread_mutex_unlock( &skirmish->single.lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_dismiss (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ skirmish->single.count--;
+
+ if (pthread_mutex_unlock( &skirmish->single.lock ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_skirmish_destroy (FusionSkirmish *skirmish)
+{
+ D_ASSERT( skirmish != NULL );
+
+ pthread_cond_broadcast( &skirmish->single.cond );
+ pthread_cond_destroy( &skirmish->single.cond );
+
+ return pthread_mutex_destroy( &skirmish->single.lock );
+}
+
+DirectResult
+fusion_skirmish_wait( FusionSkirmish *skirmish, unsigned int timeout )
+{
+ D_ASSERT( skirmish != NULL );
+
+ if (timeout) {
+ struct timespec ts;
+ struct timeval tv;
+ int ret;
+
+ gettimeofday( &tv, NULL );
+
+ ts.tv_nsec = tv.tv_usec*1000 + (timeout%1000)*1000000;
+ ts.tv_sec = tv.tv_sec + timeout/1000 + ts.tv_nsec/1000000000;
+ ts.tv_nsec = ts.tv_nsec % 1000000000;
+
+ ret = pthread_cond_timedwait( &skirmish->single.cond,
+ &skirmish->single.lock, &ts );
+
+ return (ret == ETIMEDOUT) ? DR_TIMEOUT : DR_OK;
+ }
+
+ return pthread_cond_wait( &skirmish->single.cond, &skirmish->single.lock );
+}
+
+DirectResult
+fusion_skirmish_notify( FusionSkirmish *skirmish )
+{
+ D_ASSERT( skirmish != NULL );
+
+ pthread_cond_broadcast( &skirmish->single.cond );
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/lock.h b/Source/DirectFB/lib/fusion/lock.h
new file mode 100755
index 0000000..d5071bb
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/lock.h
@@ -0,0 +1,122 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__LOCK_H__
+#define __FUSION__LOCK_H__
+
+#include <pthread.h>
+
+#include <fusion/types.h>
+
+#include <direct/messages.h>
+#include <direct/util.h>
+
+
+typedef union {
+ /* multi app */
+ struct {
+ int id;
+ const FusionWorldShared *shared;
+ /* builtin impl */
+ struct {
+ unsigned int locked;
+ pid_t owner;
+ DirectLink *waiting;
+ bool requested;
+ bool destroyed;
+ } builtin;
+ } multi;
+
+ /* single app */
+ struct {
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ int count;
+ } single;
+} FusionSkirmish;
+
+/*
+ * Initialize.
+ */
+DirectResult fusion_skirmish_init ( FusionSkirmish *skirmish,
+ const char *name,
+ const FusionWorld *world );
+
+/*
+ * Lock.
+ */
+DirectResult fusion_skirmish_prevail( FusionSkirmish *skirmish );
+
+/*
+ * Try lock.
+ */
+DirectResult fusion_skirmish_swoop ( FusionSkirmish *skirmish );
+
+/*
+ * Find out how many times current thread has acquired lock.
+ */
+DirectResult fusion_skirmish_lock_count( FusionSkirmish *skirmish, int *lock_count );
+
+/*
+ * Unlock.
+ */
+DirectResult fusion_skirmish_dismiss( FusionSkirmish *skirmish );
+
+/*
+ * Deinitialize.
+ */
+DirectResult fusion_skirmish_destroy( FusionSkirmish *skirmish );
+
+/*
+ * Wait & Notify.
+ *
+ * Must be locked!
+ */
+DirectResult fusion_skirmish_wait ( FusionSkirmish *skirmish,
+ unsigned int timeout );
+DirectResult fusion_skirmish_notify ( FusionSkirmish *skirmish );
+
+
+#if D_DEBUG_ENABLED
+#define FUSION_SKIRMISH_ASSERT(skirmish) \
+ do { \
+ int lock_count; \
+ \
+ D_ASSERT( skirmish != NULL ); \
+ \
+ D_ASSERT( fusion_skirmish_lock_count( skirmish, &lock_count ) == DR_OK ); \
+ D_ASSERT( lock_count > 0 ); \
+ } while (0)
+#else
+#define FUSION_SKIRMISH_ASSERT(skirmish) \
+ do { \
+ } while (0)
+#endif
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/object.c b/Source/DirectFB/lib/fusion/object.c
new file mode 100755
index 0000000..9138889
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/object.c
@@ -0,0 +1,640 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <sys/param.h>
+
+#include <pthread.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+
+#include <fusion/build.h>
+#include <fusion/object.h>
+#include <fusion/hash.h>
+#include <fusion/shmalloc.h>
+
+#include "fusion_internal.h"
+
+D_DEBUG_DOMAIN( Fusion_Object, "Fusion/Object", "Fusion Objects and Pools" );
+
+struct __Fusion_FusionObjectPool {
+ int magic;
+
+ FusionWorldShared *shared;
+
+ FusionSkirmish lock;
+ DirectLink *objects;
+ FusionObjectID id_pool;
+
+ char *name;
+ int object_size;
+ int message_size;
+ FusionObjectDestructor destructor;
+ void *ctx;
+
+ FusionCall call;
+};
+
+static FusionCallHandlerResult
+object_reference_watcher( int caller, int call_arg, void *call_ptr, void *ctx, unsigned int serial, int *ret_val )
+{
+ FusionObject *object;
+ FusionObjectPool *pool = ctx;
+
+ D_DEBUG_AT( Fusion_Object, "%s( %d, %d, %p, %p, %u, %p )\n",
+ __FUNCTION__, caller, call_arg, call_ptr, ctx, serial, ret_val );
+
+#if FUSION_BUILD_KERNEL
+ if (caller) {
+ D_BUG( "Call not from Fusion/Kernel (caller %d)", caller );
+ return FCHR_RETURN;
+ }
+#endif
+
+ D_MAGIC_ASSERT( pool, FusionObjectPool );
+
+ /* Lock the pool. */
+ if (fusion_skirmish_prevail( &pool->lock ))
+ return FCHR_RETURN;
+
+ /* Lookup the object. */
+ direct_list_foreach (object, pool->objects) {
+ if (object->id != call_arg)
+ continue;
+
+ D_MAGIC_ASSERT( object, FusionObject );
+
+ switch (fusion_ref_zero_trylock( &object->ref )) {
+ case DR_OK:
+ break;
+
+ case DR_DESTROYED:
+ D_BUG( "already destroyed %p [%ld] in '%s'", object, object->id, pool->name );
+
+ direct_list_remove( &pool->objects, &object->link );
+ fusion_skirmish_dismiss( &pool->lock );
+ return FCHR_RETURN;
+
+
+ default:
+ D_ERROR( "Fusion/ObjectPool: Error locking ref of %p [%ld] in '%s'\n",
+ object, object->id, pool->name );
+ /* fall through */
+
+ case DR_BUSY:
+ fusion_skirmish_dismiss( &pool->lock );
+ return FCHR_RETURN;
+ }
+
+ D_DEBUG_AT( Fusion_Object, "== %s ==\n", pool->name );
+ D_DEBUG_AT( Fusion_Object, " -> dead object %p [%ld]\n", object, object->id );
+
+ if (object->state == FOS_INIT) {
+ D_BUG( "== %s == incomplete object: %d (%p)", pool->name, call_arg, object );
+ D_WARN( "won't destroy incomplete object, leaking some memory" );
+ direct_list_remove( &pool->objects, &object->link );
+ fusion_skirmish_dismiss( &pool->lock );
+ return FCHR_RETURN;
+ }
+
+ /* Set "deinitializing" state. */
+ object->state = FOS_DEINIT;
+
+ /* Remove the object from the pool. */
+ object->pool = NULL;
+ direct_list_remove( &pool->objects, &object->link );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+
+ D_DEBUG_AT( Fusion_Object, " -> calling destructor...\n" );
+
+ /* Call the destructor. */
+ pool->destructor( object, false, pool->ctx );
+
+ D_DEBUG_AT( Fusion_Object, " -> destructor done.\n" );
+
+ return FCHR_RETURN;
+ }
+
+ D_BUG( "unknown object [%d] in '%s'", call_arg, pool->name );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return FCHR_RETURN;
+}
+
+FusionObjectPool *
+fusion_object_pool_create( const char *name,
+ int object_size,
+ int message_size,
+ FusionObjectDestructor destructor,
+ void *ctx,
+ const FusionWorld *world )
+{
+ FusionObjectPool *pool;
+ FusionWorldShared *shared;
+
+ D_ASSERT( name != NULL );
+ D_ASSERT( object_size >= sizeof(FusionObject) );
+ D_ASSERT( message_size > 0 );
+ D_ASSERT( destructor != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ /* Allocate shared memory for the pool. */
+ pool = SHCALLOC( shared->main_pool, 1, sizeof(FusionObjectPool) );
+ if (!pool) {
+ D_OOSHM();
+ return NULL;
+ }
+
+ /* Initialize the pool lock. */
+ fusion_skirmish_init( &pool->lock, name, world );
+
+ /* Fill information. */
+ pool->shared = shared;
+ pool->name = SHSTRDUP( shared->main_pool, name );
+ pool->object_size = object_size;
+ pool->message_size = message_size;
+ pool->destructor = destructor;
+ pool->ctx = ctx;
+
+ /* Destruction call from Fusion. */
+ fusion_call_init( &pool->call, object_reference_watcher, pool, world );
+
+ D_MAGIC_SET( pool, FusionObjectPool );
+
+ return pool;
+}
+
+DirectResult
+fusion_object_pool_destroy( FusionObjectPool *pool,
+ const FusionWorld *world )
+{
+ DirectResult ret;
+ DirectLink *n;
+ FusionObject *object;
+ FusionWorldShared *shared;
+
+ D_ASSERT( pool != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+ D_ASSERT( shared == pool->shared );
+
+ D_DEBUG_AT( Fusion_Object, "== %s ==\n", pool->name );
+ D_DEBUG_AT( Fusion_Object, " -> destroying pool...\n" );
+
+ D_DEBUG_AT( Fusion_Object, " -> syncing...\n" );
+
+ /* Wait for processing of pending messages. */
+ if (pool->objects)
+ fusion_sync( world );
+
+ D_DEBUG_AT( Fusion_Object, " -> locking...\n" );
+
+ /* Lock the pool. */
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret)
+ return ret;
+
+ /* Destroy the call. */
+ fusion_call_destroy( &pool->call );
+
+ if (pool->objects)
+ D_WARN( "still objects in '%s'", pool->name );
+
+ /* Destroy zombies */
+ direct_list_foreach_safe (object, n, pool->objects) {
+ int refs;
+
+ fusion_ref_stat( &object->ref, &refs );
+
+ D_DEBUG_AT( Fusion_Object, "== %s ==\n", pool->name );
+ D_DEBUG_AT( Fusion_Object, " -> zombie %p [%ld], refs %d\n", object, object->id, refs );
+
+ /* Set "deinitializing" state. */
+ object->state = FOS_DEINIT;
+
+ /* Remove the object from the pool. */
+ //direct_list_remove( &pool->objects, &object->link );
+ //object->pool = NULL;
+
+ D_DEBUG_AT( Fusion_Object, " -> calling destructor...\n" );
+
+ /* Call the destructor. */
+ pool->destructor( object, refs > 0, pool->ctx );
+
+ D_DEBUG_AT( Fusion_Object, " -> destructor done.\n" );
+
+ D_ASSERT( ! direct_list_contains_element_EXPENSIVE( pool->objects, (DirectLink*) object ) );
+ }
+
+ pool->objects = NULL;
+
+ /* Destroy the pool lock. */
+ fusion_skirmish_destroy( &pool->lock );
+
+ D_DEBUG_AT( Fusion_Object, " -> pool destroyed (%s)\n", pool->name );
+
+ D_MAGIC_CLEAR( pool );
+
+ /* Deallocate shared memory. */
+ SHFREE( shared->main_pool, pool->name );
+ SHFREE( shared->main_pool, pool );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_object_pool_enum( FusionObjectPool *pool,
+ FusionObjectCallback callback,
+ void *ctx )
+{
+ FusionObject *object;
+
+ D_MAGIC_ASSERT( pool, FusionObjectPool );
+ D_ASSERT( callback != NULL );
+
+ /* Lock the pool. */
+ if (fusion_skirmish_prevail( &pool->lock ))
+ return DR_FUSION;
+
+ direct_list_foreach (object, pool->objects) {
+ D_MAGIC_ASSERT( object, FusionObject );
+
+ if (!callback( pool, object, ctx ))
+ break;
+ }
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return DR_OK;
+}
+
+FusionObject *
+fusion_object_create( FusionObjectPool *pool,
+ const FusionWorld *world )
+{
+ FusionObject *object;
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( pool, FusionObjectPool );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+ D_ASSERT( shared == pool->shared );
+
+ /* Lock the pool. */
+ if (fusion_skirmish_prevail( &pool->lock ))
+ return NULL;
+
+ /* Allocate shared memory for the object. */
+ object = SHCALLOC( shared->main_pool, 1, pool->object_size );
+ if (!object) {
+ D_OOSHM();
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Set "initializing" state. */
+ object->state = FOS_INIT;
+
+ /* Set object id. */
+ object->id = ++pool->id_pool;
+
+ /* Initialize the reference counter. */
+ if (fusion_ref_init( &object->ref, pool->name, world )) {
+ SHFREE( shared->main_pool, object );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Increase the object's reference counter. */
+ fusion_ref_up( &object->ref, false );
+
+ /* Install handler for automatic destruction. */
+ if (fusion_ref_watch( &object->ref, &pool->call, object->id )) {
+ fusion_ref_destroy( &object->ref );
+ SHFREE( shared->main_pool, object );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Create a reactor for message dispatching. */
+ object->reactor = fusion_reactor_new( pool->message_size, pool->name, world );
+ if (!object->reactor) {
+ fusion_ref_destroy( &object->ref );
+ SHFREE( shared->main_pool, object );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ fusion_reactor_set_lock( object->reactor, &pool->lock );
+
+ /* Set pool/world back pointer. */
+ object->pool = pool;
+ object->shared = shared;
+
+ /* Add the object to the pool. */
+ direct_list_prepend( &pool->objects, &object->link );
+
+ D_DEBUG_AT( Fusion_Object, "== %s ==\n", pool->name );
+
+#if FUSION_BUILD_MULTI
+ D_DEBUG_AT( Fusion_Object, " -> added %p with ref [0x%x]\n", object, object->ref.multi.id );
+#else
+ D_DEBUG_AT( Fusion_Object, " -> added %p\n", object );
+#endif
+
+ D_MAGIC_SET( object, FusionObject );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return object;
+}
+
+DirectResult
+fusion_object_get( FusionObjectPool *pool,
+ FusionObjectID object_id,
+ FusionObject **ret_object )
+{
+ DirectResult ret = DR_IDNOTFOUND;
+ FusionObject *object;
+
+ D_MAGIC_ASSERT( pool, FusionObjectPool );
+ D_ASSERT( ret_object != NULL );
+
+ /* Lock the pool. */
+ if (fusion_skirmish_prevail( &pool->lock ))
+ return DR_FUSION;
+
+ direct_list_foreach (object, pool->objects) {
+ D_MAGIC_ASSERT( object, FusionObject );
+
+ if (object->id == object_id) {
+ ret = fusion_object_ref( object );
+ break;
+ }
+ }
+
+ if (ret == DR_OK)
+ *ret_object = object;
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_object_set_lock( FusionObject *object,
+ FusionSkirmish *lock )
+{
+ D_MAGIC_ASSERT( object, FusionObject );
+
+ D_ASSERT( lock != NULL );
+
+ D_ASSUME( object->state == FOS_INIT );
+
+ return fusion_reactor_set_lock_only( object->reactor, lock );
+}
+
+DirectResult
+fusion_object_activate( FusionObject *object )
+{
+ D_MAGIC_ASSERT( object, FusionObject );
+
+ /* Set "active" state. */
+ object->state = FOS_ACTIVE;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_object_destroy( FusionObject *object )
+{
+ FusionObjectPool *pool;
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( object, FusionObject );
+ D_ASSERT( object->state != FOS_ACTIVE );
+
+ shared = object->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ pool = object->pool;
+
+// D_ASSUME( pool != NULL );
+
+ /* Set "deinitializing" state. */
+ object->state = FOS_DEINIT;
+
+ /* Remove the object from the pool. */
+ if (pool) {
+ D_MAGIC_ASSERT( pool, FusionObjectPool );
+
+ /* Lock the pool. */
+ if (fusion_skirmish_prevail( &pool->lock ))
+ return DR_FAILURE;
+
+ D_MAGIC_ASSERT( pool, FusionObjectPool );
+
+ D_ASSUME( object->pool != NULL );
+
+ /* Remove the object from the pool. */
+ if (object->pool) {
+ D_ASSERT( object->pool == pool );
+
+ object->pool = NULL;
+
+ direct_list_remove( &pool->objects, &object->link );
+ }
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+ }
+
+ fusion_ref_destroy( &object->ref );
+
+ fusion_reactor_free( object->reactor );
+
+ if ( object->properties )
+ fusion_hash_destroy(object->properties);
+
+ D_MAGIC_CLEAR( object );
+ SHFREE( shared->main_pool, object );
+ return DR_OK;
+}
+
+/*
+ * Sets a value for a key.
+ * If the key currently has a value the old value is returned
+ * in old_value.
+ * If old_value is null the object is freed with SHFREE.
+ * If this is not the correct semantics for your data, if for example
+ * its reference counted you must pass in a old_value.
+ */
+DirectResult
+fusion_object_set_property( FusionObject *object,
+ const char *key,
+ void *value,
+ void **old_value )
+{
+ DirectResult ret;
+ char *sharedkey;
+
+ D_MAGIC_ASSERT( object, FusionObject );
+ D_ASSERT( object->shared != NULL );
+ D_ASSERT( key != NULL );
+ D_ASSERT( value != NULL );
+
+ /* Create property hash on demand. */
+ if (!object->properties) {
+ ret = fusion_hash_create( object->shared->main_pool,
+ HASH_STRING, HASH_PTR,
+ FUSION_HASH_MIN_SIZE,
+ &object->properties );
+ if (ret)
+ return ret;
+ }
+
+ /* Create a shared copy of the key. */
+ sharedkey = SHSTRDUP( object->shared->main_pool, key );
+ if (!sharedkey)
+ return D_OOSHM();
+
+ /* Put it into the hash. */
+ ret = fusion_hash_replace( object->properties, sharedkey,
+ value, NULL, old_value );
+ if (ret)
+ SHFREE( object->shared->main_pool, sharedkey );
+
+ return ret;
+}
+
+/*
+ * Helper function for int values
+ */
+DirectResult
+fusion_object_set_int_property( FusionObject *object,
+ const char *key,
+ int value )
+{
+ DirectResult ret;
+ int *iptr;
+
+ D_MAGIC_ASSERT( object, FusionObject );
+ D_ASSERT( key != NULL );
+
+ iptr = SHMALLOC( object->shared->main_pool, sizeof(int) );
+ if (!iptr)
+ return D_OOSHM();
+
+ *iptr = value;
+
+ ret = fusion_object_set_property( object, key, iptr, NULL );
+ if (ret)
+ SHFREE( object->shared->main_pool, iptr );
+
+ return ret;
+}
+
+/*
+ * Helper function for char* values use if the string
+ * is not in shared memory
+ * Assumes that the old value was a string and frees it.
+ */
+DirectResult
+fusion_object_set_string_property( FusionObject *object,
+ const char *key,
+ char *value )
+{
+ DirectResult ret;
+ char *copy;
+
+ D_MAGIC_ASSERT( object, FusionObject );
+ D_ASSERT( key != NULL );
+ D_ASSERT( value != NULL );
+
+ copy = SHSTRDUP( object->shared->main_pool, value );
+ if (!copy)
+ return D_OOSHM();
+
+ ret = fusion_object_set_property( object, key, copy, NULL );
+ if (ret)
+ SHFREE( object->shared->main_pool, copy );
+
+ return ret;
+}
+
+void *
+fusion_object_get_property( FusionObject *object, const char *key )
+{
+ D_MAGIC_ASSERT( object, FusionObject );
+ D_ASSERT( key != NULL );
+
+ if (!object->properties)
+ return NULL;
+
+ return fusion_hash_lookup( object->properties, key );
+}
+
+void
+fusion_object_remove_property( FusionObject *object,
+ const char *key,
+ void **old_value)
+{
+ D_MAGIC_ASSERT( object, FusionObject );
+ D_ASSERT( key != NULL );
+
+ if (!object->properties)
+ return;
+
+ fusion_hash_remove( object->properties, key, NULL, old_value );
+
+ if (fusion_hash_should_resize( object->properties ))
+ fusion_hash_resize( object->properties );
+}
+
diff --git a/Source/DirectFB/lib/fusion/object.h b/Source/DirectFB/lib/fusion/object.h
new file mode 100755
index 0000000..ae75374
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/object.h
@@ -0,0 +1,279 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__OBJECT_H__
+#define __FUSION__OBJECT_H__
+
+#include <fusion/types.h>
+
+#include <fusion/lock.h>
+#include <direct/list.h>
+#include <fusion/ref.h>
+#include <fusion/reactor.h>
+#include <direct/debug.h>
+
+typedef void (*FusionObjectDestructor)( FusionObject *object, bool zombie, void *ctx );
+
+typedef bool (*FusionPropIterator)( char *key, void *value, void *ctx);
+
+
+
+
+typedef unsigned long FusionObjectID;
+
+
+typedef enum {
+ FOS_INIT,
+ FOS_ACTIVE,
+ FOS_DEINIT
+} FusionObjectState;
+
+struct __Fusion_FusionObject {
+ DirectLink link;
+ FusionObjectPool *pool;
+
+ int magic;
+
+ FusionObjectID id;
+
+ FusionObjectState state;
+
+ FusionRef ref;
+ FusionReactor *reactor;
+
+ FusionWorldShared *shared;
+ FusionHash *properties;
+};
+
+
+typedef bool (*FusionObjectCallback)( FusionObjectPool *pool,
+ FusionObject *object,
+ void *ctx );
+
+
+FusionObjectPool *fusion_object_pool_create ( const char *name,
+ int object_size,
+ int message_size,
+ FusionObjectDestructor destructor,
+ void *ctx,
+ const FusionWorld *world );
+
+DirectResult fusion_object_pool_destroy( FusionObjectPool *pool,
+ const FusionWorld *world );
+
+
+DirectResult fusion_object_pool_enum ( FusionObjectPool *pool,
+ FusionObjectCallback callback,
+ void *ctx );
+
+
+FusionObject *fusion_object_create ( FusionObjectPool *pool,
+ const FusionWorld *world );
+
+DirectResult fusion_object_get ( FusionObjectPool *pool,
+ FusionObjectID object_id,
+ FusionObject **ret_object );
+
+DirectResult fusion_object_set_lock( FusionObject *object,
+ FusionSkirmish *lock );
+
+DirectResult fusion_object_activate( FusionObject *object );
+
+DirectResult fusion_object_destroy ( FusionObject *object );
+
+DirectResult fusion_object_set_property( FusionObject *object ,
+ const char *key, void *value, void **old_value);
+
+DirectResult fusion_object_set_int_property( FusionObject *object ,
+ const char *key,int value);
+
+DirectResult fusion_object_set_string_property( FusionObject *object ,
+ const char *key,char *value);
+
+void *fusion_object_get_property( FusionObject *object ,const char *key);
+void fusion_object_remove_property( FusionObject *object ,const char *key,void **ret_val);
+
+#define FUSION_OBJECT_METHODS(type, prefix) \
+ \
+static inline DirectResult \
+prefix##_attach( type *object, \
+ ReactionFunc func, \
+ void *ctx, \
+ Reaction *ret_reaction ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_attach( ((FusionObject*)object)->reactor, \
+ func, ctx, ret_reaction ); \
+} \
+ \
+static inline DirectResult \
+prefix##_attach_channel( type *object, \
+ int channel, \
+ ReactionFunc func, \
+ void *ctx, \
+ Reaction *ret_reaction ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_attach_channel( ((FusionObject*)object)->reactor, \
+ channel, func, ctx, ret_reaction ); \
+} \
+ \
+static inline DirectResult \
+prefix##_detach( type *object, \
+ Reaction *reaction ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_detach( ((FusionObject*)object)->reactor, \
+ reaction ); \
+} \
+ \
+static inline DirectResult \
+prefix##_attach_global( type *object, \
+ int index, \
+ void *ctx, \
+ GlobalReaction *reaction ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_attach_global( ((FusionObject*)object)->reactor, \
+ index, ctx, reaction ); \
+} \
+ \
+static inline DirectResult \
+prefix##_detach_global( type *object, \
+ GlobalReaction *reaction ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_detach_global( ((FusionObject*)object)->reactor, \
+ reaction ); \
+} \
+ \
+static inline DirectResult \
+prefix##_dispatch( type *object, \
+ void *message, \
+ const ReactionFunc *globals ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_dispatch( ((FusionObject*)object)->reactor, \
+ message, true, globals ); \
+} \
+ \
+static inline DirectResult \
+prefix##_dispatch_channel( type *object, \
+ int channel, \
+ void *message, \
+ int size, \
+ const ReactionFunc *globals ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_reactor_dispatch_channel( ((FusionObject*)object)->reactor, \
+ channel, message, size, true, globals ); \
+} \
+ \
+static inline DirectResult \
+prefix##_ref( type *object ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_ref_up( &((FusionObject*)object)->ref, false ); \
+} \
+ \
+static inline DirectResult \
+prefix##_unref( type *object ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_ref_down( &((FusionObject*)object)->ref, false ); \
+} \
+ \
+static inline DirectResult \
+prefix##_ref_stat( type *object, int *refs ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ return fusion_ref_stat ( &((FusionObject*)object)->ref, refs ); \
+} \
+ \
+static inline DirectResult \
+prefix##_link( type **link, \
+ type *object ) \
+{ \
+ DirectResult ret; \
+ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ \
+ ret = fusion_ref_up( &((FusionObject*)object)->ref, true ); \
+ if (ret) \
+ return ret; \
+ \
+ *link = object; \
+ \
+ return DR_OK; \
+} \
+ \
+static inline DirectResult \
+prefix##_unlink( type **link ) \
+{ \
+ type *object = *link; \
+ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ \
+ *link = NULL; \
+ \
+ return fusion_ref_down( &((FusionObject*)object)->ref, true ); \
+} \
+ \
+static inline DirectResult \
+prefix##_inherit( type *object, \
+ void *from ) \
+{ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ D_MAGIC_ASSERT( (FusionObject*) from, FusionObject ); \
+ \
+ return fusion_ref_inherit( &((FusionObject*)object)->ref, \
+ &((FusionObject*)from)->ref ); \
+} \
+ \
+static inline DirectResult \
+prefix##_globalize( type *object ) \
+{ \
+ DirectResult ret; \
+ \
+ D_MAGIC_ASSERT( (FusionObject*) object, FusionObject ); \
+ \
+ ret = fusion_ref_up( &((FusionObject*)object)->ref, true ); \
+ if (ret) \
+ return ret; \
+ \
+ ret = fusion_ref_down( &((FusionObject*)object)->ref, false ); \
+ if (ret) \
+ fusion_ref_down( &((FusionObject*)object)->ref, true ); \
+ \
+ return ret; \
+}
+
+FUSION_OBJECT_METHODS( void, fusion_object )
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/property.c b/Source/DirectFB/lib/fusion/property.c
new file mode 100755
index 0000000..640f572
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/property.c
@@ -0,0 +1,530 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <fusion/build.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/types.h>
+#include <fusion/property.h>
+
+#include "fusion_internal.h"
+
+
+#if FUSION_BUILD_MULTI
+
+#if FUSION_BUILD_KERNEL
+
+DirectResult
+fusion_property_init (FusionProperty *property, const FusionWorld *world)
+{
+ D_ASSERT( property != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ while (ioctl (world->fusion_fd, FUSION_PROPERTY_NEW, &property->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_PROPERTY_NEW");
+
+ return DR_FAILURE;
+ }
+
+ /* Keep back pointer to shared world data. */
+ property->multi.shared = world->shared;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_lease (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ while (ioctl (_fusion_fd( property->multi.shared ), FUSION_PROPERTY_LEASE, &property->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EAGAIN:
+ return DR_BUSY;
+ case EINVAL:
+ D_ERROR ("Fusion/Property: invalid property\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_PROPERTY_LEASE");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_purchase (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ while (ioctl (_fusion_fd( property->multi.shared ), FUSION_PROPERTY_PURCHASE, &property->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EAGAIN:
+ return DR_BUSY;
+ case EINVAL:
+ D_ERROR ("Fusion/Property: invalid property\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_PROPERTY_PURCHASE");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_cede (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ while (ioctl (_fusion_fd( property->multi.shared ), FUSION_PROPERTY_CEDE, &property->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Property: invalid property\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_PROPERTY_CEDE");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_holdup (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ while (ioctl (_fusion_fd( property->multi.shared ), FUSION_PROPERTY_HOLDUP, &property->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Property: invalid property\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_PROPERTY_HOLDUP");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_destroy (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ while (ioctl (_fusion_fd( property->multi.shared ), FUSION_PROPERTY_DESTROY, &property->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Property: invalid property\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_PROPERTY_DESTROY");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+#else /* FUSION_BUILD_KERNEL */
+
+#include <direct/system.h>
+
+DirectResult
+fusion_property_init (FusionProperty *property, const FusionWorld *world)
+{
+ D_ASSERT( property != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ /* Set state to available. */
+ property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE;
+ property->multi.builtin.owner = 0;
+
+ property->multi.builtin.requested = false;
+ property->multi.builtin.destroyed = false;
+
+ /* Keep back pointer to shared world data. */
+ property->multi.shared = world->shared;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_lease (FusionProperty *property)
+{
+ int count = 0;
+
+ D_ASSERT( property != NULL );
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ D_ASSUME( property->multi.builtin.owner != direct_gettid() );
+
+ asm( "" ::: "memory" );
+
+ while (property->multi.builtin.state == FUSION_PROPERTY_LEASED) {
+ /* Check whether owner exited without releasing. */
+ if (kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) {
+ property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE;
+ property->multi.builtin.requested = false;
+ break;
+ }
+
+ property->multi.builtin.requested = true;
+
+ asm( "" ::: "memory" );
+
+ if (++count > 1000) {
+ usleep( 10000 );
+ count = 0;
+ }
+ else {
+ direct_sched_yield();
+ }
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+ }
+
+ if (property->multi.builtin.state == FUSION_PROPERTY_PURCHASED) {
+ /* Check whether owner exited without releasing. */
+ if (!(kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH))
+ return DR_BUSY;
+ }
+
+ property->multi.builtin.state = FUSION_PROPERTY_LEASED;
+ property->multi.builtin.owner = direct_gettid();
+
+ asm( "" ::: "memory" );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_purchase (FusionProperty *property)
+{
+ int count = 0;
+
+ D_ASSERT( property != NULL );
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ D_ASSUME( property->multi.builtin.owner != direct_gettid() );
+
+ asm( "" ::: "memory" );
+
+ while (property->multi.builtin.state == FUSION_PROPERTY_LEASED) {
+ /* Check whether owner exited without releasing. */
+ if (kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) {
+ property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE;
+ property->multi.builtin.requested = false;
+ break;
+ }
+
+ property->multi.builtin.requested = true;
+
+ asm( "" ::: "memory" );
+
+ if (++count > 1000) {
+ usleep( 10000 );
+ count = 0;
+ }
+ else {
+ direct_sched_yield();
+ }
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+ }
+
+ if (property->multi.builtin.state == FUSION_PROPERTY_PURCHASED) {
+ /* Check whether owner exited without releasing. */
+ if (!(kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH))
+ return DR_BUSY;
+ }
+
+ property->multi.builtin.state = FUSION_PROPERTY_PURCHASED;
+ property->multi.builtin.owner = direct_gettid();
+
+ asm( "" ::: "memory" );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_cede (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ D_ASSUME( property->multi.builtin.state != FUSION_PROPERTY_AVAILABLE );
+ D_ASSUME( property->multi.builtin.owner == direct_gettid() );
+
+ property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE;
+ property->multi.builtin.owner = 0;
+
+ asm( "" ::: "memory" );
+
+ if (property->multi.builtin.requested) {
+ property->multi.builtin.requested = false;
+ asm( "" ::: "memory" );
+ direct_sched_yield();
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_holdup (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ if (property->multi.builtin.state == FUSION_PROPERTY_PURCHASED &&
+ property->multi.builtin.owner != direct_gettid()) {
+ pid_t pid = property->multi.builtin.owner;
+
+ if (kill( pid, SIGKILL ) < 0 && errno != ESRCH)
+ return DR_UNSUPPORTED;
+
+ /* Wait process termination. */
+ while (kill( pid, 0 ) == 0) {
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ direct_sched_yield();
+ }
+
+ property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE;
+ property->multi.builtin.owner = 0;
+ property->multi.builtin.requested = false;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_property_destroy (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ if (property->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ property->multi.builtin.destroyed = true;
+
+ return DR_OK;
+}
+
+#endif /* FUSION_BUILD_KERNEL */
+
+#else /* FUSION_BUILD_MULTI */
+
+#include <pthread.h>
+
+/*
+ * Initializes the property
+ */
+DirectResult
+fusion_property_init (FusionProperty *property, const FusionWorld *world)
+{
+ D_ASSERT( property != NULL );
+
+ direct_util_recursive_pthread_mutex_init (&property->single.lock);
+ pthread_cond_init (&property->single.cond, NULL);
+
+ property->single.state = FUSION_PROPERTY_AVAILABLE;
+
+ return DR_OK;
+}
+
+/*
+ * Lease the property causing others to wait before leasing or purchasing.
+ */
+DirectResult
+fusion_property_lease (FusionProperty *property)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( property != NULL );
+
+ pthread_mutex_lock (&property->single.lock);
+
+ /* Wait as long as the property is leased by another party. */
+ while (property->single.state == FUSION_PROPERTY_LEASED)
+ pthread_cond_wait (&property->single.cond, &property->single.lock);
+
+ /* Fail if purchased by another party, otherwise succeed. */
+ if (property->single.state == FUSION_PROPERTY_PURCHASED)
+ ret = DR_BUSY;
+ else
+ property->single.state = FUSION_PROPERTY_LEASED;
+
+ pthread_mutex_unlock (&property->single.lock);
+
+ return ret;
+}
+
+/*
+ * Purchase the property disallowing others to lease or purchase it.
+ */
+DirectResult
+fusion_property_purchase (FusionProperty *property)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( property != NULL );
+
+ pthread_mutex_lock (&property->single.lock);
+
+ /* Wait as long as the property is leased by another party. */
+ while (property->single.state == FUSION_PROPERTY_LEASED)
+ pthread_cond_wait (&property->single.cond, &property->single.lock);
+
+ /* Fail if purchased by another party, otherwise succeed. */
+ if (property->single.state == FUSION_PROPERTY_PURCHASED)
+ ret = DR_BUSY;
+ else {
+ property->single.state = FUSION_PROPERTY_PURCHASED;
+
+ /* Wake up any other waiting party. */
+ pthread_cond_broadcast (&property->single.cond);
+ }
+
+ pthread_mutex_unlock (&property->single.lock);
+
+ return ret;
+}
+
+/*
+ * Cede the property allowing others to lease or purchase it.
+ */
+DirectResult
+fusion_property_cede (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ pthread_mutex_lock (&property->single.lock);
+
+ /* Simple error checking, maybe we should also check the owner. */
+ D_ASSERT( property->single.state != FUSION_PROPERTY_AVAILABLE );
+
+ /* Put back into 'available' state. */
+ property->single.state = FUSION_PROPERTY_AVAILABLE;
+
+ /* Wake up one waiting party if there are any. */
+ pthread_cond_signal (&property->single.cond);
+
+ pthread_mutex_unlock (&property->single.lock);
+
+ return DR_OK;
+}
+
+/*
+ * Does nothing to avoid killing ourself.
+ */
+DirectResult
+fusion_property_holdup (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ return DR_OK;
+}
+
+/*
+ * Destroys the property
+ */
+DirectResult
+fusion_property_destroy (FusionProperty *property)
+{
+ D_ASSERT( property != NULL );
+
+ pthread_cond_destroy (&property->single.cond);
+ pthread_mutex_destroy (&property->single.lock);
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/property.h b/Source/DirectFB/lib/fusion/property.h
new file mode 100755
index 0000000..74e3d1f
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/property.h
@@ -0,0 +1,114 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__PROPERTY_H__
+#define __FUSION__PROPERTY_H__
+
+#include <pthread.h>
+
+#include <fusion/types.h>
+
+typedef enum {
+ FUSION_PROPERTY_AVAILABLE,
+ FUSION_PROPERTY_LEASED,
+ FUSION_PROPERTY_PURCHASED
+} FusionPropertyState;
+
+
+typedef union {
+ /* multi app */
+ struct {
+ int id;
+ const FusionWorldShared *shared;
+ /* builtin impl */
+ struct {
+ FusionPropertyState state;
+ pid_t owner;
+ bool requested;
+ bool destroyed;
+ } builtin;
+ } multi;
+
+ /* single app */
+ struct {
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ FusionPropertyState state;
+ } single;
+} FusionProperty;
+
+/*
+ * Initializes the property
+ */
+DirectResult fusion_property_init (FusionProperty *property,
+ const FusionWorld *world);
+
+/*
+ * Lease the property causing others to wait before leasing or purchasing.
+ *
+ * Waits as long as property is leased by another party.
+ * Returns DR_BUSY if property is/gets purchased by another party.
+ *
+ * Succeeds if property is available,
+ * puts the property into 'leased' state.
+ */
+DirectResult fusion_property_lease (FusionProperty *property);
+
+/*
+ * Purchase the property disallowing others to lease or purchase it.
+ *
+ * Waits as long as property is leased by another party.
+ * Returns DR_BUSY if property is/gets purchased by another party.
+ *
+ * Succeeds if property is available,
+ * puts the property into 'purchased' state and wakes up any waiting party.
+ */
+DirectResult fusion_property_purchase (FusionProperty *property);
+
+/*
+ * Cede the property allowing others to lease or purchase it.
+ *
+ * Puts the property into 'available' state and wakes up one waiting party.
+ */
+DirectResult fusion_property_cede (FusionProperty *property);
+
+/*
+ * Kills the owner of the property.
+ *
+ * Tries to make a purchased property available again by killing
+ * the process that purchased it.
+ */
+DirectResult fusion_property_holdup (FusionProperty *property);
+
+/*
+ * Destroys the property
+ */
+DirectResult fusion_property_destroy (FusionProperty *property);
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/protocol.h b/Source/DirectFB/lib/fusion/protocol.h
new file mode 100755
index 0000000..8670b1d
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/protocol.h
@@ -0,0 +1,119 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION_PROTOCOL_H__
+#define __FUSION_PROTOCOL_H__
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <direct/types.h>
+
+
+typedef enum {
+ FMT_SEND,
+ FMT_ENTER,
+ FMT_LEAVE,
+ FMT_CALL,
+ FMT_CALLRET,
+ FMT_REACTOR
+} FusionMessageType;
+
+/*
+ * Enter world (slave).
+ */
+typedef struct {
+ FusionMessageType type;
+
+ FusionID fusion_id;
+} FusionEnter;
+
+/*
+ * Leave the world (slave).
+ */
+typedef struct {
+ FusionMessageType type;
+
+ FusionID fusion_id;
+} FusionLeave;
+
+/*
+ * Execute a call.
+ */
+typedef struct {
+ FusionMessageType type;
+
+ unsigned int serial;
+
+ FusionID caller;
+ int call_id;
+ int call_arg;
+ void *call_ptr;
+
+ void *handler;
+ void *ctx;
+
+ FusionCallExecFlags flags;
+} FusionCallMessage, FusionCallExecute;
+
+/*
+ * Send call return.
+ */
+typedef struct {
+ FusionMessageType type;
+
+ int val;
+} FusionCallReturn;
+
+/*
+ * Send reactor message.
+ */
+typedef struct {
+ FusionMessageType type;
+
+ int id;
+ int channel;
+
+ FusionRef *ref;
+} FusionReactorMessage;
+
+
+typedef union {
+ FusionMessageType type;
+
+ FusionEnter enter;
+ FusionLeave leave;
+ FusionCallMessage call;
+ FusionCallReturn callret;
+ FusionReactorMessage reactor;
+} FusionMessage;
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/reactor.c b/Source/DirectFB/lib/fusion/reactor.c
new file mode 100755
index 0000000..7e1feae
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/reactor.c
@@ -0,0 +1,1868 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/param.h>
+
+#include <pthread.h>
+
+#include <fusion/build.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+#include <fusion/types.h>
+#include <fusion/lock.h>
+#include <fusion/shmalloc.h>
+#include <fusion/reactor.h>
+
+#include "fusion_internal.h"
+
+
+#if FUSION_BUILD_MULTI
+
+D_DEBUG_DOMAIN( Fusion_Reactor, "Fusion/Reactor", "Fusion's Reactor" );
+
+struct __Fusion_FusionReactor {
+ int magic;
+
+ int id; /* reactor id */
+ int msg_size; /* size of each message */
+ bool direct;
+ bool destroyed;
+
+ DirectLink *globals;
+ FusionSkirmish *globals_lock;
+
+ FusionWorldShared *shared;
+
+#if !FUSION_BUILD_KERNEL
+ DirectLink *listeners; /* list of attached listeners */
+ FusionSkirmish listeners_lock;
+
+ FusionCall *call;
+#endif
+};
+
+typedef struct {
+ DirectLink link;
+
+ int magic;
+
+ pthread_rwlock_t lock;
+
+ int reactor_id;
+ FusionReactor *reactor;
+
+ DirectLink *links; /* reactor listeners attached to node */
+} ReactorNode;
+
+typedef struct {
+ DirectLink link;
+
+ int magic;
+
+ Reaction *reaction;
+ int channel;
+} NodeLink;
+
+/**************************************************************************************************/
+
+static ReactorNode *lock_node ( int reactor_id,
+ bool add_it,
+ bool wlock,
+ FusionReactor *reactor, /* one of reactor and world must not be NULL */
+ FusionWorld *world );
+
+static void unlock_node ( ReactorNode *node );
+
+static void process_globals( FusionReactor *reactor,
+ const void *msg_data,
+ const ReactionFunc *globals );
+
+/**************************************************************************************************/
+
+#if FUSION_BUILD_KERNEL
+
+FusionReactor *
+fusion_reactor_new( int msg_size,
+ const char *name,
+ const FusionWorld *world )
+{
+ FusionEntryInfo info;
+ FusionReactor *reactor;
+ FusionWorldShared *shared;
+
+// D_ASSERT( msg_size > 0 );
+ D_ASSERT( name != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_new( '%s', size %d )\n", name ? : "", msg_size );
+
+ /* allocate shared reactor data */
+ reactor = SHCALLOC( shared->main_pool, 1, sizeof (FusionReactor) );
+ if (!reactor) {
+ D_OOSHM();
+ return NULL;
+ }
+
+ /* create a new reactor */
+ while (ioctl( world->fusion_fd, FUSION_REACTOR_NEW, &reactor->id )) {
+ if (errno == EINTR)
+ continue;
+
+ D_PERROR( "FUSION_REACTOR_NEW" );
+ SHFREE( shared->main_pool, reactor );
+ return NULL;
+ }
+
+ /* set the static message size, should we make dynamic? (TODO?) */
+ reactor->msg_size = msg_size;
+
+ /* Set default lock for global reactions. */
+ reactor->globals_lock = &shared->reactor_globals;
+
+ D_DEBUG_AT( Fusion_Reactor, " -> new reactor %p [%d] with lock %p [%d]\n",
+ reactor, reactor->id, reactor->globals_lock, reactor->globals_lock->multi.id );
+
+ reactor->shared = shared;
+ reactor->direct = true;
+
+ D_MAGIC_SET( reactor, FusionReactor );
+
+
+ info.type = FT_REACTOR;
+ info.id = reactor->id;
+
+ direct_snputs( info.name, name, sizeof(info.name) );
+
+ ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );
+
+ return reactor;
+}
+
+DirectResult
+fusion_reactor_destroy( FusionReactor *reactor )
+{
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ shared = reactor->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_destroy( %p [%d] )\n", reactor, reactor->id );
+
+ D_ASSUME( !reactor->destroyed );
+
+ if (reactor->destroyed)
+ return DR_DESTROYED;
+
+ while (ioctl( _fusion_fd( shared ), FUSION_REACTOR_DESTROY, &reactor->id )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor\n" );
+ return DR_DESTROYED;
+ }
+
+ D_PERROR( "FUSION_REACTOR_DESTROY" );
+ return DR_FUSION;
+ }
+
+ reactor->destroyed = true;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_free( FusionReactor *reactor )
+{
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ shared = reactor->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_free( %p [%d] )\n", reactor, reactor->id );
+
+ D_MAGIC_CLEAR( reactor );
+
+// D_ASSUME( reactor->destroyed );
+
+ if (!reactor->destroyed)
+ while (ioctl( _fusion_fd( shared ), FUSION_REACTOR_DESTROY, &reactor->id ) && errno == EINTR);
+
+ /* free shared reactor data */
+ SHFREE( shared->main_pool, reactor );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_attach_channel( FusionReactor *reactor,
+ int channel,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction )
+{
+ ReactorNode *node;
+ NodeLink *link;
+ FusionReactorAttach attach;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( func != NULL );
+ D_ASSERT( reaction != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_attach( %p [%d], func %p, ctx %p, reaction %p )\n",
+ reactor, reactor->id, func, ctx, reaction );
+
+ link = D_CALLOC( 1, sizeof(NodeLink) );
+ if (!link)
+ return D_OOM();
+
+ node = lock_node( reactor->id, true, true, reactor, NULL );
+ if (!node) {
+ D_FREE( link );
+ return DR_FUSION;
+ }
+
+ attach.reactor_id = reactor->id;
+ attach.channel = channel;
+
+ while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_ATTACH, &attach )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor\n" );
+ unlock_node( node );
+ D_FREE( link );
+ return DR_DESTROYED;
+ }
+
+ D_PERROR( "FUSION_REACTOR_ATTACH" );
+ unlock_node( node );
+ D_FREE( link );
+ return DR_FUSION;
+ }
+
+ /* fill out callback information */
+ reaction->func = func;
+ reaction->ctx = ctx;
+ reaction->node_link = link;
+
+ link->reaction = reaction;
+ link->channel = channel;
+
+ D_MAGIC_SET( link, NodeLink );
+
+ /* prepend the reaction to the local reaction list */
+ direct_list_prepend( &node->links, &link->link );
+
+ unlock_node( node );
+
+ return DR_OK;
+}
+
+static void
+remove_node_link( ReactorNode *node,
+ NodeLink *link )
+{
+ D_MAGIC_ASSERT( node, ReactorNode );
+ D_MAGIC_ASSERT( link, NodeLink );
+
+ D_ASSUME( link->reaction == NULL );
+
+ direct_list_remove( &node->links, &link->link );
+
+ D_MAGIC_CLEAR( link );
+
+ D_FREE( link );
+}
+
+DirectResult
+fusion_reactor_detach( FusionReactor *reactor,
+ Reaction *reaction )
+{
+ ReactorNode *node;
+ NodeLink *link;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( reaction != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_detach( %p [%d], reaction %p ) <- func %p, ctx %p\n",
+ reactor, reactor->id, reaction, reaction->func, reaction->ctx );
+
+ node = lock_node( reactor->id, false, true, reactor, NULL );
+ if (!node) {
+ D_BUG( "node not found" );
+ return DR_BUG;
+ }
+
+ link = reaction->node_link;
+ D_ASSUME( link != NULL );
+
+ if (link) {
+ FusionReactorDetach detach;
+
+ D_ASSERT( link->reaction == reaction );
+
+ detach.reactor_id = reactor->id;
+ detach.channel = link->channel;
+
+ reaction->node_link = NULL;
+
+ link->reaction = NULL;
+
+ remove_node_link( node, link );
+
+ while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_DETACH, &detach )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor\n" );
+ unlock_node( node );
+ return DR_DESTROYED;
+ }
+
+ D_PERROR( "FUSION_REACTOR_DETACH" );
+ unlock_node( node );
+ return DR_FUSION;
+ }
+ }
+
+ unlock_node( node );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_dispatch_channel( FusionReactor *reactor,
+ int channel,
+ const void *msg_data,
+ int msg_size,
+ bool self,
+ const ReactionFunc *globals )
+{
+ FusionReactorDispatch dispatch;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ D_ASSERT( msg_data != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_dispatch( %p [%d], msg_data %p, self %s, globals %p)\n",
+ reactor, reactor->id, msg_data, self ? "true" : "false", globals );
+
+ /* Handle global reactions first. */
+ if (reactor->globals) {
+ if (globals)
+ process_globals( reactor, msg_data, globals );
+ else
+ D_ERROR( "Fusion/Reactor: global reactions exist but no "
+ "globals have been passed to dispatch()\n" );
+ }
+
+ /* Handle local reactions. */
+ if (self && reactor->direct) {
+ _fusion_reactor_process_message( _fusion_world(reactor->shared), reactor->id, channel, msg_data );
+ self = false;
+ }
+
+ /* Initialize dispatch data. */
+ dispatch.reactor_id = reactor->id;
+ dispatch.channel = channel;
+ dispatch.self = self;
+ dispatch.msg_size = msg_size;
+ dispatch.msg_data = msg_data;
+
+ /* Dispatch the message to handle foreign reactions. */
+ while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_DISPATCH, &dispatch )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor\n" );
+ return DR_DESTROYED;
+ }
+
+ D_PERROR( "FUSION_REACTOR_DISPATCH" );
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_set_dispatch_callback( FusionReactor *reactor,
+ FusionCall *call,
+ void *call_ptr )
+{
+ FusionReactorSetCallback callback;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( call != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_set_dispatch_callback( %p [%d], call %p [%d], ptr %p)\n",
+ reactor, reactor->id, call, call->call_id, call_ptr );
+
+ /* Fill callback info. */
+ callback.reactor_id = reactor->id;
+ callback.call_id = call->call_id;
+ callback.call_ptr = call_ptr;
+
+ /* Set the dispatch callback. */
+ while (ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_SET_DISPATCH_CALLBACK, &callback )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor\n" );
+ return DR_DESTROYED;
+ }
+
+ D_PERROR( "FUSION_REACTOR_SET_DISPATCH_CALLBACK" );
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_set_name( FusionReactor *reactor,
+ const char *name )
+{
+ FusionEntryInfo info;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( name != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor, "%s( %p, '%s' )\n", __FUNCTION__, reactor, name );
+
+ /* Initialize reactor info. */
+ info.type = FT_REACTOR;
+ info.id = reactor->id;
+
+ /* Put reactor name into info. */
+ direct_snputs( info.name, name, sizeof(info.name) );
+
+ /* Set the reactor info. */
+ while (ioctl( _fusion_fd( reactor->shared ), FUSION_ENTRY_SET_INFO, &info )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor\n" );
+ return DR_IDNOTFOUND;
+ }
+
+ D_PERROR( "FUSION_ENTRY_SET_INFO( reactor 0x%08x, '%s' )\n", reactor->id, name );
+ return DR_FUSION;
+ }
+
+ return DR_OK;
+}
+
+void
+_fusion_reactor_process_message( FusionWorld *world,
+ int reactor_id,
+ int channel,
+ const void *msg_data )
+{
+ ReactorNode *node;
+ NodeLink *link;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( msg_data != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ " _fusion_reactor_process_message( [%d], msg_data %p )\n", reactor_id, msg_data );
+
+ /* Find the local counter part of the reactor. */
+ node = lock_node( reactor_id, false, false, NULL, world );
+ if (!node)
+ return;
+
+ D_DEBUG_AT( Fusion_Reactor, " -> node %p, reactor %p\n", node, node->reactor );
+
+ D_ASSUME( node->links != NULL );
+
+ if (!node->links) {
+ D_DEBUG_AT( Fusion_Reactor, " -> no local reactions!?!\n" );
+ unlock_node( node );
+ return;
+ }
+
+ direct_list_foreach (link, node->links) {
+ Reaction *reaction;
+
+ D_MAGIC_ASSERT( link, NodeLink );
+
+ if (link->channel != channel)
+ continue;
+
+ reaction = link->reaction;
+ if (!reaction)
+ continue;
+
+ if (reaction->func( msg_data, reaction->ctx ) == RS_REMOVE) {
+ FusionReactorDetach detach;
+
+ detach.reactor_id = reactor_id;
+ detach.channel = channel;
+
+ D_DEBUG_AT( Fusion_Reactor, " -> removing %p, func %p, ctx %p\n",
+ reaction, reaction->func, reaction->ctx );
+
+ link->reaction = NULL;
+
+ /* We can't remove the link as we only have read lock, to avoid dead locks. */
+
+ while (ioctl( world->fusion_fd, FUSION_REACTOR_DETACH, &detach )) {
+ switch (errno) {
+ case EINTR:
+ continue;
+
+ case EINVAL:
+ D_ERROR( "Fusion/Reactor: invalid reactor (DETACH)\n" );
+ break;
+
+ default:
+ D_PERROR( "FUSION_REACTOR_DETACH" );
+ break;
+ }
+
+ break;
+ }
+ }
+ }
+
+ unlock_node( node );
+}
+
+#else /* FUSION_BUILD_KERNEL */
+
+typedef struct {
+ DirectLink link;
+
+ unsigned int refs;
+
+ FusionID fusion_id;
+ int channel;
+} __Listener;
+
+
+FusionReactor *
+fusion_reactor_new( int msg_size,
+ const char *name,
+ const FusionWorld *world )
+{
+ FusionReactor *reactor;
+ FusionWorldShared *shared;
+
+ D_ASSERT( msg_size > 0 );
+ D_ASSERT( name != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_new( '%s', size %d )\n", name ? : "", msg_size );
+
+ /* allocate shared reactor data */
+ reactor = SHCALLOC( shared->main_pool, 1, sizeof (FusionReactor) );
+ if (!reactor) {
+ D_OOSHM();
+ return NULL;
+ }
+
+ /* Generate the reactor id */
+ reactor->id = ++shared->reactor_ids;
+
+ /* Set the static message size, should we make dynamic? (TODO?) */
+ reactor->msg_size = msg_size;
+
+ /* Set default lock for global reactions. */
+ reactor->globals_lock = &shared->reactor_globals;
+
+ fusion_skirmish_init( &reactor->listeners_lock, "Reactor Listeners", world );
+
+ D_DEBUG_AT( Fusion_Reactor, " -> new reactor %p [%d] with lock %p [%d]\n",
+ reactor, reactor->id, reactor->globals_lock, reactor->globals_lock->multi.id );
+
+ reactor->shared = shared;
+ reactor->direct = true;
+
+ D_MAGIC_SET( reactor, FusionReactor );
+
+ return reactor;
+}
+
+DirectResult
+fusion_reactor_destroy( FusionReactor *reactor )
+{
+ FusionWorldShared *shared;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ shared = reactor->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_destroy( %p [%d] )\n", reactor, reactor->id );
+
+ D_ASSUME( !reactor->destroyed );
+
+ if (reactor->destroyed)
+ return DR_DESTROYED;
+
+ fusion_skirmish_destroy( &reactor->listeners_lock );
+
+ reactor->destroyed = true;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_free( FusionReactor *reactor )
+{
+ FusionWorldShared *shared;
+ __Listener *listener, *temp;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ shared = reactor->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_free( %p [%d] )\n", reactor, reactor->id );
+
+ D_MAGIC_CLEAR( reactor );
+
+// D_ASSUME( reactor->destroyed );
+
+ direct_list_foreach_safe (listener, temp, reactor->listeners) {
+ direct_list_remove( &reactor->listeners, &listener->link );
+ SHFREE( shared->main_pool, listener );
+ }
+
+ /* free shared reactor data */
+ SHFREE( shared->main_pool, reactor );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_attach_channel( FusionReactor *reactor,
+ int channel,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction )
+{
+ FusionWorldShared *shared;
+ ReactorNode *node;
+ NodeLink *link;
+ FusionID fusion_id;
+ __Listener *listener;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( func != NULL );
+ D_ASSERT( reaction != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_attach( %p [%d], func %p, ctx %p, reaction %p )\n",
+ reactor, reactor->id, func, ctx, reaction );
+
+ if (reactor->destroyed)
+ return DR_DESTROYED;
+
+ shared = reactor->shared;
+
+ link = D_CALLOC( 1, sizeof(NodeLink) );
+ if (!link)
+ return D_OOM();
+
+ node = lock_node( reactor->id, true, true, reactor, NULL );
+ if (!node) {
+ D_FREE( link );
+ return DR_FUSION;
+ }
+
+ fusion_id = _fusion_id( shared );
+
+ fusion_skirmish_prevail( &reactor->listeners_lock );
+
+ direct_list_foreach (listener, reactor->listeners) {
+ if (listener->fusion_id == fusion_id && listener->channel == channel) {
+ listener->refs++;
+ break;
+ }
+ }
+
+ if (!listener) {
+ listener = SHCALLOC( shared->main_pool, 1, sizeof(__Listener) );
+ if (!listener) {
+ D_OOSHM();
+ fusion_skirmish_dismiss( &reactor->listeners_lock );
+ unlock_node( node );
+ D_FREE( link );
+ return DR_NOSHAREDMEMORY;
+ }
+
+ listener->refs = 1;
+ listener->fusion_id = fusion_id;
+ listener->channel = channel;
+
+ direct_list_append( &reactor->listeners, &listener->link );
+ }
+
+ fusion_skirmish_dismiss( &reactor->listeners_lock );
+
+ /* fill out callback information */
+ reaction->func = func;
+ reaction->ctx = ctx;
+ reaction->node_link = link;
+
+ link->reaction = reaction;
+ link->channel = channel;
+
+ D_MAGIC_SET( link, NodeLink );
+
+ /* prepend the reaction to the local reaction list */
+ direct_list_prepend( &node->links, &link->link );
+
+ unlock_node( node );
+
+ return DR_OK;
+}
+
+static void
+remove_node_link( ReactorNode *node,
+ NodeLink *link )
+{
+ D_MAGIC_ASSERT( node, ReactorNode );
+ D_MAGIC_ASSERT( link, NodeLink );
+
+ D_ASSUME( link->reaction == NULL );
+
+ direct_list_remove( &node->links, &link->link );
+
+ D_MAGIC_CLEAR( link );
+
+ D_FREE( link );
+}
+
+DirectResult
+fusion_reactor_detach( FusionReactor *reactor,
+ Reaction *reaction )
+{
+ FusionWorldShared *shared;
+ ReactorNode *node;
+ NodeLink *link;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( reaction != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_detach( %p [%d], reaction %p ) <- func %p, ctx %p\n",
+ reactor, reactor->id, reaction, reaction->func, reaction->ctx );
+
+ if (reactor->destroyed)
+ return DR_DESTROYED;
+
+ shared = reactor->shared;
+
+ node = lock_node( reactor->id, false, true, reactor, NULL );
+ if (!node) {
+ D_BUG( "node not found" );
+ return DR_BUG;
+ }
+
+ link = reaction->node_link;
+ D_ASSUME( link != NULL );
+
+ if (link) {
+ __Listener *listener;
+ FusionID fusion_id = _fusion_id( shared );
+
+ D_ASSERT( link->reaction == reaction );
+
+ reaction->node_link = NULL;
+
+ link->reaction = NULL;
+
+ remove_node_link( node, link );
+
+ fusion_skirmish_prevail( &reactor->listeners_lock );
+
+ direct_list_foreach (listener, reactor->listeners) {
+ if (listener->fusion_id == fusion_id && listener->channel == link->channel) {
+ if (--listener->refs == 0) {
+ direct_list_remove( &reactor->listeners, &listener->link );
+ SHFREE( shared->main_pool, listener );
+ }
+ break;
+ }
+ }
+
+ fusion_skirmish_dismiss( &reactor->listeners_lock );
+
+ if (!listener)
+ D_ERROR( "Fusion/Reactor: Couldn't detach listener!\n" );
+ }
+
+ unlock_node( node );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_dispatch_channel( FusionReactor *reactor,
+ int channel,
+ const void *msg_data,
+ int msg_size,
+ bool self,
+ const ReactionFunc *globals )
+{
+ FusionWorld *world;
+ __Listener *listener, *temp;
+ FusionRef *ref = NULL;
+ FusionReactorMessage *msg;
+ struct sockaddr_un addr;
+ int len;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ D_ASSERT( msg_data != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_dispatch( %p [%d], msg_data %p, self %s, globals %p)\n",
+ reactor, reactor->id, msg_data, self ? "true" : "false", globals );
+
+ if (reactor->destroyed)
+ return DR_DESTROYED;
+
+ if (msg_size > FUSION_MESSAGE_SIZE-sizeof(FusionReactorMessage)) {
+ D_ERROR( "Fusion/Reactor: Message too large (%d)!\n", msg_size );
+ return DR_UNSUPPORTED;
+ }
+
+ world = _fusion_world( reactor->shared );
+
+ if (reactor->call) {
+ ref = SHMALLOC( world->shared->main_pool, sizeof(FusionRef) );
+ if (!ref)
+ return D_OOSHM();
+
+ fusion_ref_init( ref, "Dispatch Ref", world );
+ fusion_ref_up( ref, true );
+ fusion_ref_watch( ref, reactor->call, 0 );
+ }
+
+ /* Handle global reactions first. */
+ if (reactor->globals) {
+ if (globals)
+ process_globals( reactor, msg_data, globals );
+ else
+ D_ERROR( "Fusion/Reactor: global reactions exist but no "
+ "globals have been passed to dispatch()\n" );
+ }
+
+ /* Handle local reactions. */
+ if (self && reactor->direct) {
+ _fusion_reactor_process_message( _fusion_world(reactor->shared), reactor->id, channel, msg_data );
+ self = false;
+ }
+
+ msg = alloca( sizeof(FusionReactorMessage) + msg_size );
+
+ msg->type = FMT_REACTOR;
+ msg->id = reactor->id;
+ msg->channel = channel;
+ msg->ref = ref;
+
+ memcpy( (void*)msg + sizeof(FusionReactorMessage), msg_data, msg_size );
+
+ addr.sun_family = AF_UNIX;
+ len = snprintf( addr.sun_path, sizeof(addr.sun_path),
+ "/tmp/.fusion-%d/", fusion_world_index( world ) );
+
+ fusion_skirmish_prevail( &reactor->listeners_lock );
+
+ direct_list_foreach_safe (listener, temp, reactor->listeners) {
+ if (listener->channel == channel) {
+ DirectResult ret;
+
+ if (!self && listener->fusion_id == world->fusion_id)
+ continue;
+
+ if (ref)
+ fusion_ref_up( ref, true );
+
+ snprintf( addr.sun_path+len, sizeof(addr.sun_path)-len, "%lx", listener->fusion_id );
+
+ D_DEBUG_AT( Fusion_Reactor, " -> sending to '%s'\n", addr.sun_path );
+
+ ret = _fusion_send_message( world->fusion_fd, msg, sizeof(FusionReactorMessage)+msg_size, &addr );
+ if (ret == DR_FUSION) {
+ D_DEBUG_AT( Fusion_Reactor, " -> removing dead listener %lu\n", listener->fusion_id );
+
+ if (ref)
+ fusion_ref_down( ref, true );
+
+ direct_list_remove( &reactor->listeners, &listener->link );
+
+ SHFREE( reactor->shared->main_pool, listener );
+ }
+ }
+ }
+
+ fusion_skirmish_dismiss( &reactor->listeners_lock );
+
+ if (ref) {
+ fusion_ref_down( ref, true );
+ if (fusion_ref_zero_trylock( ref ) == DR_OK) {
+ fusion_ref_destroy( ref );
+ SHFREE( world->shared->main_pool, ref );
+ }
+ }
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_dispatch( %p ) done.\n", reactor );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_set_dispatch_callback( FusionReactor *reactor,
+ FusionCall *call,
+ void *call_ptr )
+{
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( call != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_set_dispatch_callback( %p [%d], call %p [%d], ptr %p)\n",
+ reactor, reactor->id, call, call->call_id, call_ptr );
+
+ if (reactor->destroyed)
+ return DR_DESTROYED;
+
+ if (call_ptr)
+ return DR_UNIMPLEMENTED;
+
+ reactor->call = call;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_set_name( FusionReactor *reactor,
+ const char *name )
+{
+ D_UNIMPLEMENTED();
+
+ return DR_UNIMPLEMENTED;
+}
+
+void
+_fusion_reactor_process_message( FusionWorld *world,
+ int reactor_id,
+ int channel,
+ const void *msg_data )
+{
+ ReactorNode *node;
+ NodeLink *link;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_ASSERT( msg_data != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ " _fusion_reactor_process_message( [%d], msg_data %p )\n", reactor_id, msg_data );
+
+ /* Find the local counter part of the reactor. */
+ node = lock_node( reactor_id, false, false, NULL, world );
+ if (!node)
+ return;
+
+ D_DEBUG_AT( Fusion_Reactor, " -> node %p, reactor %p\n", node, node->reactor );
+
+ D_ASSUME( node->links != NULL );
+
+ if (!node->links) {
+ D_DEBUG_AT( Fusion_Reactor, " -> no local reactions!?!\n" );
+ unlock_node( node );
+ return;
+ }
+
+ direct_list_foreach (link, node->links) {
+ Reaction *reaction;
+
+ D_MAGIC_ASSERT( link, NodeLink );
+
+ if (link->channel != channel)
+ continue;
+
+ reaction = link->reaction;
+ if (!reaction)
+ continue;
+
+ if (reaction->func( msg_data, reaction->ctx ) == RS_REMOVE) {
+ FusionReactor *reactor = node->reactor;
+ __Listener *listener;
+
+ D_DEBUG_AT( Fusion_Reactor, " -> removing %p, func %p, ctx %p\n",
+ reaction, reaction->func, reaction->ctx );
+
+ fusion_skirmish_prevail( &reactor->listeners_lock );
+
+ direct_list_foreach (listener, reactor->listeners) {
+ if (listener->fusion_id == world->fusion_id && listener->channel == channel) {
+ if (--listener->refs == 0) {
+ direct_list_remove( &reactor->listeners, &listener->link );
+ SHFREE( world->shared->main_pool, listener );
+ }
+ break;
+ }
+ }
+
+ fusion_skirmish_dismiss( &reactor->listeners_lock );
+ }
+ }
+
+ unlock_node( node );
+}
+
+#endif /* FUSION_BUILD_KERNEL */
+
+
+DirectResult
+fusion_reactor_set_lock( FusionReactor *reactor,
+ FusionSkirmish *lock )
+{
+ DirectResult ret;
+ FusionSkirmish *old;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ old = reactor->globals_lock;
+
+ D_ASSERT( lock != NULL );
+ D_ASSERT( old != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_set_lock( %p [%d], lock %p [%d] ) <- old %p [%d]\n",
+ reactor, reactor->id, lock, lock->multi.id, old, old->multi.id );
+
+ /*
+ * Acquire the old lock to make sure that changing the lock doesn't
+ * result in mismatching lock/unlock pairs in other functions.
+ */
+ ret = fusion_skirmish_prevail( old );
+ if (ret)
+ return ret;
+
+ D_ASSUME( reactor->globals_lock != lock );
+
+ /* Set the lock replacement. */
+ reactor->globals_lock = lock;
+
+ /* Release the old lock which is obsolete now. */
+ fusion_skirmish_dismiss( old );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_set_lock_only( FusionReactor *reactor,
+ FusionSkirmish *lock )
+{
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( lock != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor, "fusion_reactor_set_lock_only( %p [%d], lock %p [%d] ) <- old %p [%d]\n",
+ reactor, reactor->id, lock, lock->multi.id, reactor->globals_lock, reactor->globals_lock->multi.id );
+
+ D_ASSUME( reactor->globals_lock != lock );
+
+ /* Set the lock replacement. */
+ reactor->globals_lock = lock;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_attach (FusionReactor *reactor,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction)
+{
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+ D_ASSERT( func != NULL );
+ D_ASSERT( reaction != NULL );
+
+ return fusion_reactor_attach_channel( reactor, 0, func, ctx, reaction );
+}
+
+DirectResult
+fusion_reactor_attach_global( FusionReactor *reactor,
+ int index,
+ void *ctx,
+ GlobalReaction *reaction )
+{
+ DirectResult ret;
+ FusionSkirmish *lock;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ D_ASSERT( index >= 0 );
+ D_ASSERT( reaction != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_attach_global( %p [%d], index %d, ctx %p, reaction %p )\n",
+ reactor, reactor->id, index, ctx, reaction );
+
+ /* Initialize reaction data. */
+ reaction->index = index;
+ reaction->ctx = ctx;
+ reaction->attached = true;
+
+ /* Remember for safety. */
+ lock = reactor->globals_lock;
+
+ D_ASSERT( lock != NULL );
+
+ /* Lock the list of global reactions. */
+ ret = fusion_skirmish_prevail( lock );
+ if (ret)
+ return ret;
+
+ /* FIXME: Might have changed while waiting for the lock. */
+ if (lock != reactor->globals_lock)
+ D_WARN( "using old lock once more" );
+
+ /* Prepend the reaction to the list. */
+ direct_list_prepend( &reactor->globals, &reaction->link );
+
+ /* Unlock the list of global reactions. */
+ fusion_skirmish_dismiss( lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_detach_global( FusionReactor *reactor,
+ GlobalReaction *reaction )
+{
+ DirectResult ret;
+ FusionSkirmish *lock;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ D_ASSERT( reaction != NULL );
+
+ D_DEBUG_AT( Fusion_Reactor,
+ "fusion_reactor_detach_global( %p [%d], reaction %p ) <- index %d, ctx %p\n",
+ reactor, reactor->id, reaction, reaction->index, reaction->ctx );
+
+ /* Remember for safety. */
+ lock = reactor->globals_lock;
+
+ D_ASSERT( lock != NULL );
+
+ /* Lock the list of global reactions. */
+ ret = fusion_skirmish_prevail( lock );
+ if (ret)
+ return ret;
+
+ /* FIXME: Might have changed while waiting for the lock. */
+ if (lock != reactor->globals_lock)
+ D_WARN( "using old lock once more" );
+
+ D_ASSUME( reaction->attached );
+
+ /* Check against multiple detach. */
+ if (reaction->attached) {
+ /* Mark as detached. */
+ reaction->attached = false;
+
+ /* Remove the reaction from the list. */
+ direct_list_remove( &reactor->globals, &reaction->link );
+ }
+
+ /* Unlock the list of global reactions. */
+ fusion_skirmish_dismiss( lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_dispatch( FusionReactor *reactor,
+ const void *msg_data,
+ bool self,
+ const ReactionFunc *globals )
+{
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ return fusion_reactor_dispatch_channel( reactor, 0, msg_data, reactor->msg_size, self, globals );
+}
+
+DirectResult
+fusion_reactor_sized_dispatch( FusionReactor *reactor,
+ const void *msg_data,
+ int msg_size,
+ bool self,
+ const ReactionFunc *globals )
+{
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ return fusion_reactor_dispatch_channel( reactor, 0, msg_data, msg_size, self, globals );
+}
+
+DirectResult
+fusion_reactor_direct( FusionReactor *reactor, bool direct )
+{
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ reactor->direct = direct;
+
+ return DR_OK;
+}
+
+
+void
+_fusion_reactor_free_all( FusionWorld *world )
+{
+ ReactorNode *node, *node_temp;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_DEBUG_AT( Fusion_Reactor, "_fusion_reactor_free_all() <- nodes %p\n", world->reactor_nodes );
+
+
+ pthread_mutex_lock( &world->reactor_nodes_lock );
+
+ direct_list_foreach_safe (node, node_temp, world->reactor_nodes) {
+ NodeLink *link, *link_temp;
+
+ D_MAGIC_ASSERT( node, ReactorNode );
+
+ pthread_rwlock_wrlock( &node->lock );
+
+ direct_list_foreach_safe (link, link_temp, node->links) {
+ D_MAGIC_ASSERT( link, NodeLink );
+
+ D_MAGIC_CLEAR( link );
+
+ D_FREE( link );
+ }
+
+ pthread_rwlock_unlock( &node->lock );
+ pthread_rwlock_destroy( &node->lock );
+
+ D_MAGIC_CLEAR( node );
+
+ D_FREE( node );
+ }
+
+ world->reactor_nodes = NULL;
+
+ pthread_mutex_unlock( &world->reactor_nodes_lock );
+}
+
+static void
+process_globals( FusionReactor *reactor,
+ const void *msg_data,
+ const ReactionFunc *globals )
+{
+ DirectLink *n;
+ GlobalReaction *global;
+ FusionSkirmish *lock;
+ int max_index = -1;
+
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ D_ASSERT( msg_data != NULL );
+ D_ASSERT( globals != NULL );
+
+/* D_DEBUG_AT( Fusion_Reactor, " process_globals( %p [%d], msg_data %p, globals %p )\n",
+ reactor, reactor->id, msg_data, globals );*/
+
+ /* Find maximum reaction index. */
+ while (globals[max_index+1])
+ max_index++;
+
+ if (max_index < 0)
+ return;
+
+ /* Remember for safety. */
+ lock = reactor->globals_lock;
+
+ D_ASSERT( lock != NULL );
+
+ /* Lock the list of global reactions. */
+ if (fusion_skirmish_prevail( lock ))
+ return;
+
+ /* FIXME: Might have changed while waiting for the lock. */
+ if (lock != reactor->globals_lock)
+ D_WARN( "using old lock once more" );
+
+ /* Loop through all global reactions. */
+ direct_list_foreach_safe (global, n, reactor->globals) {
+ int index = global->index;
+
+ /* Check if the index is valid. */
+ if (index < 0 || index > max_index) {
+ D_WARN( "index out of bounds (%d/%d)", global->index, max_index );
+ continue;
+ }
+
+ /* Call reaction and remove it if requested. */
+ if (globals[global->index]( msg_data, global->ctx ) == RS_REMOVE) {
+ /*D_DEBUG_AT( Fusion_Reactor, " -> removing %p, index %d, ctx %p\n",
+ global, global->index, global->ctx );*/
+
+ direct_list_remove( &reactor->globals, &global->link );
+ }
+ }
+
+ /* Unlock the list of global reactions. */
+ fusion_skirmish_dismiss( lock );
+}
+
+
+
+/*****************************
+ * File internal functions *
+ *****************************/
+
+static ReactorNode *
+lock_node( int reactor_id, bool add_it, bool wlock, FusionReactor *reactor, FusionWorld *world )
+{
+ DirectLink *n;
+ ReactorNode *node;
+ FusionWorldShared *shared;
+
+ D_DEBUG_AT( Fusion_Reactor, " lock_node( [%d], add %s, reactor %p )\n",
+ reactor_id, add_it ? "true" : "false", reactor );
+
+ D_ASSERT( reactor != NULL || (!add_it && world != NULL) );
+
+ if (reactor) {
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ shared = reactor->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+
+ world = _fusion_world( shared );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ }
+ else {
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shared = world->shared;
+
+ D_MAGIC_ASSERT( shared, FusionWorldShared );
+ }
+
+
+ pthread_mutex_lock( &world->reactor_nodes_lock );
+
+ direct_list_foreach_safe (node, n, world->reactor_nodes) {
+ D_MAGIC_ASSERT( node, ReactorNode );
+
+ if (node->reactor_id == reactor_id) {
+ if (wlock) {
+ DirectLink *n;
+ NodeLink *link;
+
+ pthread_rwlock_wrlock( &node->lock );
+
+ /* FIXME: don't cleanup asynchronously */
+ direct_list_foreach_safe (link, n, node->links) {
+ D_MAGIC_ASSERT( link, NodeLink );
+
+ if (!link->reaction) {
+ D_DEBUG_AT( Fusion_Reactor, " -> cleaning up %p\n", link );
+
+ remove_node_link( node, link );
+ }
+ else
+ D_ASSERT( link->reaction->node_link == link );
+ }
+ }
+ else
+ pthread_rwlock_rdlock( &node->lock );
+
+ /* FIXME: Don't cleanup asynchronously. */
+ if (!node->links && !add_it) {
+// D_DEBUG_AT( Fusion_Reactor, " -> cleaning up mine %p\n", node );
+
+ direct_list_remove( &world->reactor_nodes, &node->link );
+
+ pthread_rwlock_unlock( &node->lock );
+ pthread_rwlock_destroy( &node->lock );
+
+ D_MAGIC_CLEAR( node );
+
+ D_FREE( node );
+
+ node = NULL;
+ }
+ else {
+/* D_DEBUG_AT( Fusion_Reactor, " -> found %p (%d reactions)\n",
+ node, direct_list_count_elements_EXPENSIVE( node->reactions ) );*/
+
+ D_ASSERT( node->reactor == reactor || reactor == NULL );
+
+ direct_list_move_to_front( &world->reactor_nodes, &node->link );
+ }
+
+ pthread_mutex_unlock( &world->reactor_nodes_lock );
+
+ return node;
+ }
+
+ /* FIXME: Don't cleanup asynchronously. */
+ if (!pthread_rwlock_trywrlock( &node->lock )) {
+ if (!node->links) {
+// D_DEBUG_AT( Fusion_Reactor, " -> cleaning up other %p\n", node );
+
+ direct_list_remove( &world->reactor_nodes, &node->link );
+
+ pthread_rwlock_unlock( &node->lock );
+ pthread_rwlock_destroy( &node->lock );
+
+ D_MAGIC_CLEAR( node );
+
+ D_FREE( node );
+ }
+ else {
+ /*D_DEBUG_AT( Fusion_Reactor, " -> keeping other %p (%d reactions)\n",
+ node, direct_list_count_elements_EXPENSIVE( node->reactions ) );*/
+
+ pthread_rwlock_unlock( &node->lock );
+ }
+ }
+ }
+
+// D_DEBUG_AT( Fusion_Reactor, " -> not found%s adding\n", add_it ? ", but" : " and not" );
+
+ if (add_it) {
+ D_MAGIC_ASSERT( reactor, FusionReactor );
+
+ node = D_CALLOC( 1, sizeof(ReactorNode) );
+ if (!node) {
+ D_OOM();
+ return NULL;
+ }
+
+ //direct_util_recursive_pthread_mutex_init( &node->lock );
+ pthread_rwlock_init( &node->lock, NULL );
+
+
+ if (wlock)
+ pthread_rwlock_wrlock( &node->lock );
+ else
+ pthread_rwlock_rdlock( &node->lock );
+
+ node->reactor_id = reactor_id;
+ node->reactor = reactor;
+
+ D_MAGIC_SET( node, ReactorNode );
+
+ direct_list_prepend( &world->reactor_nodes, &node->link );
+
+ pthread_mutex_unlock( &world->reactor_nodes_lock );
+
+ return node;
+ }
+
+ pthread_mutex_unlock( &world->reactor_nodes_lock );
+
+ return NULL;
+}
+
+static void
+unlock_node( ReactorNode *node )
+{
+ D_ASSERT( node != NULL );
+
+// D_MAGIC_ASSERT( node->reactor, FusionReactor );
+
+/* D_DEBUG_AT( Fusion_Reactor, " unlock_node( %p, reactor %p [%d] )\n",
+ node, node->reactor, node->reactor->id );*/
+
+ pthread_rwlock_unlock( &node->lock );
+}
+
+#else /* FUSION_BUILD_MULTI */
+
+/***************************
+ * Internal declarations *
+ ***************************/
+
+/*
+ *
+ */
+struct __Fusion_FusionReactor {
+ DirectLink *reactions; /* reactor listeners attached to node */
+ pthread_mutex_t reactions_lock;
+
+ DirectLink *globals; /* global reactions attached to node */
+ pthread_mutex_t globals_lock;
+
+ bool destroyed;
+};
+
+static void
+process_globals( FusionReactor *reactor,
+ const void *msg_data,
+ const ReactionFunc *globals );
+
+/****************
+ * Public API *
+ ****************/
+
+FusionReactor *
+fusion_reactor_new( int msg_size,
+ const char *name,
+ const FusionWorld *world )
+{
+ FusionReactor *reactor;
+
+ D_ASSERT( msg_size > 0 );
+
+ reactor = D_CALLOC( 1, sizeof(FusionReactor) );
+ if (!reactor)
+ return NULL;
+
+ direct_util_recursive_pthread_mutex_init( &reactor->reactions_lock );
+ direct_util_recursive_pthread_mutex_init( &reactor->globals_lock );
+
+ return reactor;
+}
+
+DirectResult
+fusion_reactor_set_lock( FusionReactor *reactor,
+ FusionSkirmish *lock )
+{
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( lock != NULL );
+
+// D_UNIMPLEMENTED();
+
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_reactor_set_lock_only( FusionReactor *reactor,
+ FusionSkirmish *lock )
+{
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( lock != NULL );
+
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_reactor_attach (FusionReactor *reactor,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction)
+{
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( func != NULL );
+ D_ASSERT( reaction != NULL );
+
+ reaction->func = func;
+ reaction->ctx = ctx;
+
+ pthread_mutex_lock( &reactor->reactions_lock );
+
+ direct_list_prepend( &reactor->reactions, &reaction->link );
+
+ pthread_mutex_unlock( &reactor->reactions_lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_detach (FusionReactor *reactor,
+ Reaction *reaction)
+{
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( reaction != NULL );
+
+ pthread_mutex_lock( &reactor->reactions_lock );
+
+ direct_list_remove( &reactor->reactions, &reaction->link );
+
+ pthread_mutex_unlock( &reactor->reactions_lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_attach_global (FusionReactor *reactor,
+ int index,
+ void *ctx,
+ GlobalReaction *reaction)
+{
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( reaction != NULL );
+
+ reaction->index = index;
+ reaction->ctx = ctx;
+
+ pthread_mutex_lock( &reactor->globals_lock );
+
+ direct_list_prepend( &reactor->globals, &reaction->link );
+
+ pthread_mutex_unlock( &reactor->globals_lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_detach_global (FusionReactor *reactor,
+ GlobalReaction *reaction)
+{
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( reaction != NULL );
+
+ pthread_mutex_lock( &reactor->globals_lock );
+
+ direct_list_remove( &reactor->globals, &reaction->link );
+
+ pthread_mutex_unlock( &reactor->globals_lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_attach_channel( FusionReactor *reactor,
+ int channel,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction )
+{
+ D_UNIMPLEMENTED();
+
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_reactor_dispatch_channel( FusionReactor *reactor,
+ int channel,
+ const void *msg_data,
+ int msg_size,
+ bool self,
+ const ReactionFunc *globals )
+{
+ D_UNIMPLEMENTED();
+
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_reactor_set_dispatch_callback( FusionReactor *reactor,
+ FusionCall *call,
+ void *call_ptr )
+{
+ D_UNIMPLEMENTED();
+
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_reactor_set_name( FusionReactor *reactor,
+ const char *name )
+{
+ D_UNIMPLEMENTED();
+
+ return DR_UNIMPLEMENTED;
+}
+
+DirectResult
+fusion_reactor_dispatch (FusionReactor *reactor,
+ const void *msg_data,
+ bool self,
+ const ReactionFunc *globals)
+{
+ DirectLink *l;
+
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( msg_data != NULL );
+
+ if (reactor->globals) {
+ if (globals)
+ process_globals( reactor, msg_data, globals );
+ else
+ D_ERROR( "Fusion/Reactor: global reactions exist but no "
+ "globals have been passed to dispatch()\n" );
+ }
+
+ if (!self)
+ return DR_OK;
+
+ pthread_mutex_lock( &reactor->reactions_lock );
+
+ l = reactor->reactions;
+ while (l) {
+ DirectLink *next = l->next;
+ Reaction *reaction = (Reaction*) l;
+
+ switch (reaction->func( msg_data, reaction->ctx )) {
+ case RS_REMOVE:
+ direct_list_remove( &reactor->reactions, l );
+ break;
+
+ case RS_DROP:
+ pthread_mutex_unlock( &reactor->reactions_lock );
+ return DR_OK;
+
+ default:
+ break;
+ }
+
+ l = next;
+ }
+
+ pthread_mutex_unlock( &reactor->reactions_lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_direct( FusionReactor *reactor, bool direct )
+{
+ D_ASSERT( reactor != NULL );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_destroy (FusionReactor *reactor)
+{
+ D_ASSERT( reactor != NULL );
+
+ D_ASSUME( !reactor->destroyed );
+
+ reactor->destroyed = true;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_reactor_free (FusionReactor *reactor)
+{
+ D_ASSERT( reactor != NULL );
+
+// D_ASSUME( reactor->destroyed );
+
+ reactor->reactions = NULL;
+
+ pthread_mutex_destroy( &reactor->reactions_lock );
+
+ D_FREE( reactor );
+
+ return DR_OK;
+}
+
+/******************************************************************************/
+
+static void
+process_globals( FusionReactor *reactor,
+ const void *msg_data,
+ const ReactionFunc *globals )
+{
+ DirectLink *n;
+ GlobalReaction *global;
+ int max_index = -1;
+
+ D_ASSERT( reactor != NULL );
+ D_ASSERT( msg_data != NULL );
+ D_ASSERT( globals != NULL );
+
+ while (globals[max_index+1])
+ max_index++;
+
+ if (max_index < 0)
+ return;
+
+ pthread_mutex_lock( &reactor->globals_lock );
+
+ direct_list_foreach_safe (global, n, reactor->globals) {
+ if (global->index < 0 || global->index > max_index) {
+ D_WARN( "global reaction index out of bounds (%d/%d)", global->index, max_index );
+ }
+ else {
+ if (globals[ global->index ]( msg_data, global->ctx ) == RS_REMOVE)
+ direct_list_remove( &reactor->globals, &global->link );
+ }
+ }
+
+ pthread_mutex_unlock( &reactor->globals_lock );
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/reactor.h b/Source/DirectFB/lib/fusion/reactor.h
new file mode 100755
index 0000000..3466c5a
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/reactor.h
@@ -0,0 +1,197 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__REACTOR_H__
+#define __FUSION__REACTOR_H__
+
+#include <direct/list.h>
+
+#include <fusion/types.h>
+#include <fusion/call.h>
+#include <fusion/lock.h>
+
+typedef enum {
+ RS_OK,
+ RS_REMOVE,
+ RS_DROP
+} ReactionResult;
+
+typedef ReactionResult (*ReactionFunc)( const void *msg_data,
+ void *ctx );
+
+typedef struct {
+ DirectLink link;
+ ReactionFunc func;
+ void *ctx;
+ void *node_link;
+} Reaction;
+
+typedef struct {
+ DirectLink link;
+ int index;
+ void *ctx;
+ bool attached;
+} GlobalReaction;
+
+
+/*
+ * Create a new reactor configured for the specified message data size.
+ */
+FusionReactor *fusion_reactor_new ( int msg_size,
+ const char *name,
+ const FusionWorld *world );
+
+/*
+ * Destroy the reactor.
+ */
+DirectResult fusion_reactor_destroy ( FusionReactor *reactor );
+
+/*
+ * Free the reactor.
+ */
+DirectResult fusion_reactor_free ( FusionReactor *reactor );
+
+
+/*
+ * Makes the reactor use the specified lock for managing global reactions.
+ *
+ * After creating the reactor a global default lock is set which is created
+ * by Fusion once during initialization.
+ *
+ * To avoid dead locks caused by alternating lock orders of the global reaction
+ * lock and another lock, the default lock is replaced by the other lock.
+ */
+DirectResult fusion_reactor_set_lock ( FusionReactor *reactor,
+ FusionSkirmish *skirmish );
+
+DirectResult fusion_reactor_set_lock_only( FusionReactor *reactor,
+ FusionSkirmish *lock );
+
+/*
+ * Attach a local reaction to the reactor (channel 0).
+ */
+DirectResult fusion_reactor_attach ( FusionReactor *reactor,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction );
+
+/*
+ * Attach a local reaction to a specific reactor channel (0-1023).
+ */
+DirectResult fusion_reactor_attach_channel( FusionReactor *reactor,
+ int channel,
+ ReactionFunc func,
+ void *ctx,
+ Reaction *reaction );
+
+/*
+ * Detach an attached local reaction from the reactor.
+ */
+DirectResult fusion_reactor_detach ( FusionReactor *reactor,
+ Reaction *reaction );
+
+
+/*
+ * Attach a global reaction to the reactor.
+ *
+ * It's always called directly, no matter which Fusionee calls fusion_reactor_dispatch().
+ * Any data referenced by the reaction function has to be in shared memory, unless it uses a
+ * mechanism to lookup a local counter part or representative, based on shared information.
+ *
+ * A global reaction is not defined directly as a function pointer, because that's always a
+ * local address. Instead, it's specified by an index into a built in function table that
+ * must be passed to fusion_reactor_dispatch() each time it is called.
+ */
+DirectResult fusion_reactor_attach_global( FusionReactor *reactor,
+ int index,
+ void *ctx,
+ GlobalReaction *reaction );
+
+/*
+ * Detach an attached global reaction from the reactor.
+ */
+DirectResult fusion_reactor_detach_global( FusionReactor *reactor,
+ GlobalReaction *reaction );
+
+/*
+ * Dispatch a message to any attached reaction (channel 0).
+ *
+ * Setting 'self' to false excludes the caller's local reactions.
+ */
+DirectResult fusion_reactor_dispatch ( FusionReactor *reactor,
+ const void *msg_data,
+ bool self,
+ const ReactionFunc *globals );
+
+/*
+ * Dispatch a message to any attached reaction with a given size. Instead of
+ * using the size defined by the reactor, the caller can specify the size of
+ * the data.
+ *
+ * Setting 'self' to false excludes the caller's local reactions.
+ */
+DirectResult fusion_reactor_sized_dispatch( FusionReactor *reactor,
+ const void *msg_data,
+ int msg_size,
+ bool self,
+ const ReactionFunc *globals );
+
+/*
+ * Dispatch a message via a specific channel (0-1023).
+ *
+ * Setting 'self' to false excludes the caller's local reactions.
+ */
+DirectResult fusion_reactor_dispatch_channel( FusionReactor *reactor,
+ int channel,
+ const void *msg_data,
+ int msg_size,
+ bool self,
+ const ReactionFunc *globals );
+
+
+/*
+ * Have the call executed when a dispatched message has been processed by all recipients.
+ */
+DirectResult fusion_reactor_set_dispatch_callback( FusionReactor *reactor,
+ FusionCall *call,
+ void *call_ptr );
+
+/*
+ * Change the name of the reactor (debug).
+ */
+DirectResult fusion_reactor_set_name ( FusionReactor *reactor,
+ const char *name );
+
+/*
+ * Specify whether local message handlers (reactions) should be called directly.
+ */
+DirectResult fusion_reactor_direct ( FusionReactor *reactor,
+ bool direct );
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/ref.c b/Source/DirectFB/lib/fusion/ref.c
new file mode 100755
index 0000000..6c278e6
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/ref.c
@@ -0,0 +1,849 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <fusion/build.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/types.h>
+#include <fusion/ref.h>
+
+#include "fusion_internal.h"
+
+#include <signal.h>
+
+
+#if FUSION_BUILD_MULTI
+
+D_DEBUG_DOMAIN( Fusion_Ref, "Fusion/Ref", "Fusion's Reference Counter" );
+
+
+#if FUSION_BUILD_KERNEL
+
+DirectResult
+fusion_ref_init (FusionRef *ref,
+ const char *name,
+ const FusionWorld *world)
+{
+ FusionEntryInfo info;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( name != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_DEBUG_AT( Fusion_Ref, "fusion_ref_init( %p, '%s' )\n", ref, name ? : "" );
+
+ while (ioctl( world->fusion_fd, FUSION_REF_NEW, &ref->multi.id )) {
+ if (errno == EINTR)
+ continue;
+
+ D_PERROR( "FUSION_REF_NEW" );
+ return DR_FUSION;
+ }
+
+ D_DEBUG_AT( Fusion_Ref, " -> new ref %p [%d]\n", ref, ref->multi.id );
+
+ info.type = FT_REF;
+ info.id = ref->multi.id;
+
+ direct_snputs( info.name, name, sizeof(info.name) );
+
+ ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );
+
+ /* Keep back pointer to shared world data. */
+ ref->multi.shared = world->shared;
+ ref->multi.creator = fusion_id( world );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_set_name (FusionRef *ref,
+ const char *name)
+{
+ FusionEntryInfo info;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( name != NULL );
+
+ info.type = FT_REF;
+ info.id = ref->multi.id;
+
+ direct_snputs( info.name, name, sizeof(info.name) );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_ENTRY_SET_INFO, &info)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EAGAIN:
+ return DR_LOCKED;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_ENTRY_SET_NAME");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_up (FusionRef *ref, bool global)
+{
+ D_ASSERT( ref != NULL );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), global ?
+ FUSION_REF_UP_GLOBAL : FUSION_REF_UP, &ref->multi.id))
+ {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EAGAIN:
+ return DR_LOCKED;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ if (global)
+ D_PERROR ("FUSION_REF_UP_GLOBAL");
+ else
+ D_PERROR ("FUSION_REF_UP");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_down (FusionRef *ref, bool global)
+{
+ D_ASSERT( ref != NULL );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), global ?
+ FUSION_REF_DOWN_GLOBAL : FUSION_REF_DOWN, &ref->multi.id))
+ {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ if (global)
+ D_PERROR ("FUSION_REF_DOWN_GLOBAL");
+ else
+ D_PERROR ("FUSION_REF_DOWN");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_stat (FusionRef *ref, int *refs)
+{
+ int val;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( refs != NULL );
+
+ while ((val = ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_STAT, &ref->multi.id)) < 0) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_STAT");
+
+ return DR_FAILURE;
+ }
+
+ *refs = val;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_zero_lock (FusionRef *ref)
+{
+ D_ASSERT( ref != NULL );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_ZERO_LOCK, &ref->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_ZERO_LOCK");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_zero_trylock (FusionRef *ref)
+{
+ D_ASSERT( ref != NULL );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_ZERO_TRYLOCK, &ref->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case ETOOMANYREFS:
+ return DR_BUSY;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_ZERO_TRYLOCK");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_unlock (FusionRef *ref)
+{
+ D_ASSERT( ref != NULL );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_UNLOCK, &ref->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_UNLOCK");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_watch (FusionRef *ref, FusionCall *call, int call_arg)
+{
+ FusionRefWatch watch;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( call != NULL );
+
+ watch.id = ref->multi.id;
+ watch.call_id = call->call_id;
+ watch.call_arg = call_arg;
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_WATCH, &watch)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_WATCH");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_inherit (FusionRef *ref, FusionRef *from)
+{
+ FusionRefInherit inherit;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( from != NULL );
+
+ inherit.id = ref->multi.id;
+ inherit.from = from->multi.id;
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_INHERIT, &inherit)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_INHERIT");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_destroy (FusionRef *ref)
+{
+ D_ASSERT( ref != NULL );
+
+ D_DEBUG_AT( Fusion_Ref, "fusion_ref_destroy( %p [%d] )\n", ref, ref->multi.id );
+
+ while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_DESTROY, &ref->multi.id)) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ case EINVAL:
+ D_ERROR ("Fusion/Reference: invalid reference\n");
+ return DR_DESTROYED;
+ default:
+ break;
+ }
+
+ D_PERROR ("FUSION_REF_DESTROY");
+
+ return DR_FAILURE;
+ }
+
+ return DR_OK;
+}
+
+#else /* FUSION_BUILD_KERNEL */
+
+DirectResult
+fusion_ref_init (FusionRef *ref,
+ const char *name,
+ const FusionWorld *world)
+{
+ D_ASSERT( ref != NULL );
+ D_ASSERT( name != NULL );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_DEBUG_AT( Fusion_Ref, "fusion_ref_init( %p, '%s' )\n", ref, name ? : "" );
+
+ ref->multi.id = ++world->shared->ref_ids;
+
+ ref->multi.builtin.local = 0;
+ ref->multi.builtin.global = 0;
+
+ fusion_skirmish_init( &ref->multi.builtin.lock, name, world );
+
+ ref->multi.builtin.call = NULL;
+
+ /* Keep back pointer to shared world data. */
+ ref->multi.shared = world->shared;
+ ref->multi.creator = fusion_id( world );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_set_name (FusionRef *ref,
+ const char *name)
+{
+ return DR_OK;
+}
+
+DirectResult
+_fusion_ref_change (FusionRef *ref, int add, bool global)
+{
+ DirectResult ret;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( add != 0 );
+
+ ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );
+ if (ret)
+ return ret;
+
+ if (global) {
+ if (ref->multi.builtin.global+add < 0) {
+ D_BUG( "ref has no global references" );
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+ return DR_BUG;
+ }
+
+ ref->multi.builtin.global += add;
+ }
+ else {
+ if (ref->multi.builtin.local+add < 0) {
+ D_BUG( "ref has no local references" );
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+ return DR_BUG;
+ }
+
+ ref->multi.builtin.local += add;
+
+ _fusion_add_local( _fusion_world(ref->multi.shared), ref, add );
+ }
+
+ if (ref->multi.builtin.local+ref->multi.builtin.global == 0) {
+ fusion_skirmish_notify( &ref->multi.builtin.lock );
+
+ if (ref->multi.builtin.call) {
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+ return fusion_call_execute( ref->multi.builtin.call, FCEF_ONEWAY,
+ ref->multi.builtin.call_arg, NULL, NULL );
+ }
+ }
+
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_up (FusionRef *ref, bool global)
+{
+ return _fusion_ref_change( ref, +1, global );
+}
+
+DirectResult
+fusion_ref_down (FusionRef *ref, bool global)
+{
+ return _fusion_ref_change( ref, -1, global );
+}
+
+DirectResult
+fusion_ref_stat (FusionRef *ref, int *refs)
+{
+ D_ASSERT( ref != NULL );
+ D_ASSERT( refs != NULL );
+
+ *refs = ref->multi.builtin.local + ref->multi.builtin.global;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_zero_lock (FusionRef *ref)
+{
+ DirectResult ret;
+
+ D_ASSERT( ref != NULL );
+
+ ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );
+ if (ret)
+ return ret;
+
+ if (ref->multi.builtin.call) {
+ ret = DR_ACCESSDENIED;
+ }
+ else {
+ if (ref->multi.builtin.local)
+ _fusion_check_locals( _fusion_world(ref->multi.shared), ref );
+
+ while (ref->multi.builtin.local+ref->multi.builtin.global) {
+ ret = fusion_skirmish_wait( &ref->multi.builtin.lock, 1000 ); /* 1 second */
+ if (ret && ret != DR_TIMEOUT);
+ return ret;
+
+ if (ref->multi.builtin.call) {
+ ret = DR_ACCESSDENIED;
+ break;
+ }
+
+ if (ref->multi.builtin.local)
+ _fusion_check_locals( _fusion_world(ref->multi.shared), ref );
+ }
+ }
+
+ if (ret)
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_zero_trylock (FusionRef *ref)
+{
+ DirectResult ret;
+
+ D_ASSERT( ref != NULL );
+
+ ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );
+ if (ret)
+ return ret;
+
+ if (ref->multi.builtin.local)
+ _fusion_check_locals( _fusion_world(ref->multi.shared), ref );
+
+ if (ref->multi.builtin.local+ref->multi.builtin.global)
+ ret = DR_BUSY;
+
+ if (ret)
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_unlock (FusionRef *ref)
+{
+ D_ASSERT( ref != NULL );
+
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_watch (FusionRef *ref, FusionCall *call, int call_arg)
+{
+ DirectResult ret;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( call != NULL );
+
+ ret = fusion_skirmish_prevail( &ref->multi.builtin.lock );
+ if (ret)
+ return ret;
+
+ if (ref->multi.builtin.local+ref->multi.builtin.global == 0) {
+ D_BUG( "ref has no references" );
+ ret = DR_BUG;
+ }
+ else if (ref->multi.builtin.call) {
+ ret = DR_BUSY;
+ }
+ else {
+ ref->multi.builtin.call = call;
+ ref->multi.builtin.call_arg = call_arg;
+ fusion_skirmish_notify( &ref->multi.builtin.lock );
+ }
+
+ fusion_skirmish_dismiss( &ref->multi.builtin.lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_inherit (FusionRef *ref, FusionRef *from)
+{
+ D_ASSERT( ref != NULL );
+ D_ASSERT( from != NULL );
+
+ D_UNIMPLEMENTED();
+
+ return fusion_ref_up( ref, true );
+}
+
+DirectResult
+fusion_ref_destroy (FusionRef *ref)
+{
+ FusionSkirmish *skirmish;
+
+ D_ASSERT( ref != NULL );
+
+ D_DEBUG_AT( Fusion_Ref, "fusion_ref_destroy( %p )\n", ref );
+
+ skirmish = &ref->multi.builtin.lock;
+ if (skirmish->multi.builtin.destroyed)
+ return DR_DESTROYED;
+
+ _fusion_remove_all_locals( _fusion_world(ref->multi.shared), ref );
+
+ fusion_skirmish_destroy( skirmish );
+
+ return DR_OK;
+}
+
+#endif /* FUSION_BUILD_KERNEL */
+
+#else /* FUSION_BUILD_MULTI */
+
+DirectResult
+fusion_ref_init (FusionRef *ref,
+ const char *name,
+ const FusionWorld *world)
+{
+ D_ASSERT( ref != NULL );
+ D_ASSERT( name != NULL );
+
+ direct_util_recursive_pthread_mutex_init (&ref->single.lock);
+ pthread_cond_init (&ref->single.cond, NULL);
+
+ ref->single.refs = 0;
+ ref->single.destroyed = false;
+ ref->single.locked = 0;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_set_name (FusionRef *ref,
+ const char *name)
+{
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_up (FusionRef *ref, bool global)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( ref != NULL );
+
+ pthread_mutex_lock (&ref->single.lock);
+
+ if (ref->single.destroyed)
+ ret = DR_DESTROYED;
+ else if (ref->single.locked)
+ ret = DR_LOCKED;
+ else
+ ref->single.refs++;
+
+ pthread_mutex_unlock (&ref->single.lock);
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_down (FusionRef *ref, bool global)
+{
+ D_ASSERT( ref != NULL );
+
+ pthread_mutex_lock (&ref->single.lock);
+
+ if (!ref->single.refs) {
+ D_BUG( "no more references" );
+ pthread_mutex_unlock (&ref->single.lock);
+ return DR_BUG;
+ }
+
+ if (ref->single.destroyed) {
+ pthread_mutex_unlock (&ref->single.lock);
+ return DR_DESTROYED;
+ }
+
+ if (! --ref->single.refs) {
+ if (ref->single.call) {
+ FusionCall *call = ref->single.call;
+
+ if (call->handler) {
+ int ret;
+ pthread_mutex_unlock (&ref->single.lock);
+ call->handler( 0, ref->single.call_arg, NULL, call->ctx, 0, &ret );
+ return DR_OK;
+ }
+ }
+ else
+ pthread_cond_broadcast (&ref->single.cond);
+ }
+
+ pthread_mutex_unlock (&ref->single.lock);
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_stat (FusionRef *ref, int *refs)
+{
+ D_ASSERT( ref != NULL );
+ D_ASSERT( refs != NULL );
+
+ if (ref->single.destroyed)
+ return DR_DESTROYED;
+
+ *refs = ref->single.refs;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_ref_zero_lock (FusionRef *ref)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( ref != NULL );
+
+ pthread_mutex_lock (&ref->single.lock);
+
+ do {
+ if (ref->single.destroyed)
+ ret = DR_DESTROYED;
+ else if (ref->single.locked)
+ ret = DR_LOCKED;
+ else if (ref->single.refs)
+ pthread_cond_wait (&ref->single.cond, &ref->single.lock);
+ else {
+ ref->single.locked = direct_gettid();
+ break;
+ }
+ } while (ret == DR_OK);
+
+ pthread_mutex_unlock (&ref->single.lock);
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_zero_trylock (FusionRef *ref)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( ref != NULL );
+
+ pthread_mutex_lock (&ref->single.lock);
+
+ if (ref->single.destroyed)
+ ret = DR_DESTROYED;
+ else if (ref->single.locked)
+ ret = DR_LOCKED;
+ else if (ref->single.refs)
+ ret = DR_BUSY;
+ else
+ ref->single.locked = direct_gettid();
+
+ pthread_mutex_unlock (&ref->single.lock);
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_unlock (FusionRef *ref)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( ref != NULL );
+
+ pthread_mutex_lock (&ref->single.lock);
+
+ if (ref->single.locked == direct_gettid()) {
+ ref->single.locked = 0;
+
+ pthread_cond_broadcast (&ref->single.cond);
+ }
+ else
+ ret = DR_ACCESSDENIED;
+
+ pthread_mutex_unlock (&ref->single.lock);
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_watch (FusionRef *ref, FusionCall *call, int call_arg)
+{
+ DirectResult ret = DR_OK;
+
+ D_ASSERT( ref != NULL );
+ D_ASSERT( call != NULL );
+
+ pthread_mutex_lock (&ref->single.lock);
+
+ if (ref->single.destroyed)
+ ret = DR_DESTROYED;
+ else if (!ref->single.refs)
+ ret = DR_BUG;
+ else if (ref->single.call)
+ ret = DR_BUSY;
+ else {
+ ref->single.call = call;
+ ref->single.call_arg = call_arg;
+ }
+
+ pthread_mutex_unlock (&ref->single.lock);
+
+ return ret;
+}
+
+DirectResult
+fusion_ref_inherit (FusionRef *ref, FusionRef *from)
+{
+ D_ASSERT( ref != NULL );
+ D_ASSERT( from != NULL );
+
+ D_UNIMPLEMENTED();
+
+ /* FIXME */
+ return fusion_ref_up( ref, true );
+}
+
+DirectResult
+fusion_ref_destroy (FusionRef *ref)
+{
+ D_ASSERT( ref != NULL );
+
+ ref->single.destroyed = true;
+
+ pthread_cond_broadcast (&ref->single.cond);
+
+ pthread_mutex_destroy (&ref->single.lock);
+ pthread_cond_destroy (&ref->single.cond);
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/ref.h b/Source/DirectFB/lib/fusion/ref.h
new file mode 100755
index 0000000..b9beda7
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/ref.h
@@ -0,0 +1,134 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__REF_H__
+#define __FUSION__REF_H__
+
+#include <pthread.h>
+
+#include <fusion/types.h>
+#include <fusion/call.h>
+#include <fusion/lock.h>
+
+typedef union {
+ /* multi app */
+ struct {
+ int id;
+ const FusionWorldShared *shared;
+ FusionID creator;
+ /* builtin impl */
+ struct {
+ int local;
+ int global;
+ FusionSkirmish lock;
+
+ FusionCall *call;
+ int call_arg;
+ } builtin;
+ } multi;
+
+ /* single app */
+ struct {
+ int refs;
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+ bool destroyed;
+ int locked;
+
+ FusionCall *call;
+ int call_arg;
+ } single;
+} FusionRef;
+
+/*
+ * Initialize.
+ */
+DirectResult fusion_ref_init (FusionRef *ref,
+ const char *name,
+ const FusionWorld *world);
+
+DirectResult fusion_ref_set_name (FusionRef *ref,
+ const char *name);
+
+/*
+ * Lock, increase, unlock.
+ */
+DirectResult fusion_ref_up (FusionRef *ref, bool global);
+
+/*
+ * Lock, decrease, unlock.
+ */
+DirectResult fusion_ref_down (FusionRef *ref, bool global);
+
+/*
+ * Get the current reference count. Meant for debugging only.
+ * This value is not reliable, because no locking will be performed
+ * and the value may change after or even while returning it.
+ */
+DirectResult fusion_ref_stat (FusionRef *ref, int *refs);
+
+/*
+ * Wait for zero and lock.
+ */
+DirectResult fusion_ref_zero_lock (FusionRef *ref);
+
+/*
+ * Check for zero and lock if true.
+ */
+DirectResult fusion_ref_zero_trylock (FusionRef *ref);
+
+/*
+ * Unlock the counter.
+ * Only to be called after successful zero_lock or zero_trylock.
+ */
+DirectResult fusion_ref_unlock (FusionRef *ref);
+
+/*
+ * Have the call executed when reference counter reaches zero.
+ */
+DirectResult fusion_ref_watch (FusionRef *ref,
+ FusionCall *call,
+ int call_arg);
+
+/*
+ * Inherit local reference count from another reference.
+ *
+ * The local count of the other reference (and its inherited references) is added to this reference.
+ */
+DirectResult fusion_ref_inherit (FusionRef *ref,
+ FusionRef *from);
+
+/*
+ * Deinitialize.
+ * Can be called after successful zero_lock or zero_trylock
+ * so that waiting fusion_ref_up calls return with DR_DESTROYED.
+ */
+DirectResult fusion_ref_destroy (FusionRef *ref);
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/shm/Makefile.am b/Source/DirectFB/lib/fusion/shm/Makefile.am
new file mode 100755
index 0000000..23ed4a5
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/Makefile.am
@@ -0,0 +1,31 @@
+## Makefile.am for DirectFB/lib/fusion/shm
+
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"@DATADIR@\" \
+ -DMODULEDIR=\"@MODULEDIR@\"
+
+if ENABLE_MULTI
+SHMSOURCES = heap.c pool.c shm.c
+else
+SHMSOURCES = fake.c
+endif
+
+EXTRA_DIST = fake.c
+
+noinst_LTLIBRARIES = libfusion_shm.la
+
+libfusion_shm_la_SOURCES = \
+ $(SHMSOURCES)
+
+includedir = @INCLUDEDIR@/fusion/shm
+
+include_HEADERS = \
+ pool.h \
+ shm.h \
+ shm_internal.h
diff --git a/Source/DirectFB/lib/fusion/shm/Makefile.in b/Source/DirectFB/lib/fusion/shm/Makefile.in
new file mode 100755
index 0000000..987fa8f
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/Makefile.in
@@ -0,0 +1,565 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = lib/fusion/shm
+DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libfusion_shm_la_LIBADD =
+am__libfusion_shm_la_SOURCES_DIST = fake.c heap.c pool.c shm.c
+@ENABLE_MULTI_FALSE@am__objects_1 = fake.lo
+@ENABLE_MULTI_TRUE@am__objects_1 = heap.lo pool.lo shm.lo
+am_libfusion_shm_la_OBJECTS = $(am__objects_1)
+libfusion_shm_la_OBJECTS = $(am_libfusion_shm_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libfusion_shm_la_SOURCES)
+DIST_SOURCES = $(am__libfusion_shm_la_SOURCES_DIST)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(includedir)"
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @INCLUDEDIR@/fusion/shm
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"@DATADIR@\" \
+ -DMODULEDIR=\"@MODULEDIR@\"
+
+@ENABLE_MULTI_FALSE@SHMSOURCES = fake.c
+@ENABLE_MULTI_TRUE@SHMSOURCES = heap.c pool.c shm.c
+EXTRA_DIST = fake.c
+noinst_LTLIBRARIES = libfusion_shm.la
+libfusion_shm_la_SOURCES = \
+ $(SHMSOURCES)
+
+include_HEADERS = \
+ pool.h \
+ shm.h \
+ shm_internal.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/fusion/shm/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lib/fusion/shm/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libfusion_shm.la: $(libfusion_shm_la_OBJECTS) $(libfusion_shm_la_DEPENDENCIES)
+ $(LINK) $(libfusion_shm_la_OBJECTS) $(libfusion_shm_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shm.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-includeHEADERS install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-includeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/lib/fusion/shm/fake.c b/Source/DirectFB/lib/fusion/shm/fake.c
new file mode 100755
index 0000000..32e25cd
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/fake.c
@@ -0,0 +1,163 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+#include <fusion/shm/shm.h>
+#include <fusion/shm/pool.h>
+
+#include <fusion/shm/shm_internal.h>
+
+
+DirectResult
+fusion_shm_pool_create( FusionWorld *world,
+ const char *name,
+ unsigned int max_size,
+ bool debug,
+ FusionSHMPoolShared **ret_pool )
+{
+ FusionSHMPoolShared *pool;
+
+#if !DIRECT_BUILD_DEBUGS
+ debug = false;
+#endif
+
+ pool = D_CALLOC( 1, sizeof(FusionSHMPoolShared) );
+ if (!pool)
+ return D_OOM();
+
+ pool->debug = debug;
+
+ D_MAGIC_SET( pool, FusionSHMPoolShared );
+
+ *ret_pool = pool;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_destroy( FusionWorld *world,
+ FusionSHMPoolShared *pool )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ D_MAGIC_CLEAR( pool );
+
+ D_FREE( pool );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_attach( FusionSHM *shm,
+ FusionSHMPoolShared *pool )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ pool->index++;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_detach( FusionSHM *shm,
+ FusionSHMPoolShared *pool )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ D_ASSERT( pool->index > 0 );
+
+ pool->index--;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_allocate( FusionSHMPoolShared *pool,
+ int size,
+ bool clear,
+ bool lock,
+ void **ret_data )
+{
+ void *data;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ data = clear ? D_CALLOC( 1, size ) : D_MALLOC( size );
+ if (!data)
+ return DR_NOSHAREDMEMORY;
+
+ *ret_data = data;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_reallocate( FusionSHMPoolShared *pool,
+ void *data,
+ int size,
+ bool lock,
+ void **ret_data )
+{
+ void *new_data;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ new_data = D_REALLOC( data, size );
+ if (!new_data)
+ return DR_NOSHAREDMEMORY;
+
+ *ret_data = new_data;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_deallocate( FusionSHMPoolShared *pool,
+ void *data,
+ bool lock )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ D_FREE( data );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_enum_pools( FusionWorld *world,
+ FusionSHMPoolCallback callback,
+ void *ctx )
+{
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/fusion/shm/heap.c b/Source/DirectFB/lib/fusion/shm/heap.c
new file mode 100755
index 0000000..4a76229
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/heap.c
@@ -0,0 +1,802 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* Heap management adapted from libc
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written May 1989 by Mike Haertel.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/conf.h>
+#include <fusion/shmalloc.h>
+#include <fusion/fusion_internal.h>
+
+#include <fusion/shm/pool.h>
+#include <fusion/shm/shm_internal.h>
+
+
+D_DEBUG_DOMAIN( Fusion_SHMHeap, "Fusion/SHMHeap", "Fusion Shared Memory Heap" );
+
+/**********************************************************************************************************************/
+
+/* Aligned allocation. */
+static void *
+align( shmalloc_heap *heap, size_t size )
+{
+ void *result;
+ unsigned long adj;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %zu )\n", __FUNCTION__, heap, size );
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ result = __shmalloc_brk( heap, size );
+
+ adj = (unsigned long) result % BLOCKSIZE;
+ if (adj != 0) {
+ adj = BLOCKSIZE - adj;
+ __shmalloc_brk( heap, adj );
+ result = (char *) result + adj;
+ }
+
+ return result;
+}
+
+/* Get neatly aligned memory, initializing or
+ growing the heap info table as necessary. */
+static void *
+morecore( shmalloc_heap *heap, size_t size )
+{
+ void *result;
+ shmalloc_info *newinfo, *oldinfo;
+ size_t newsize;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %zu )\n", __FUNCTION__, heap, size );
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ result = align( heap, size );
+ if (result == NULL)
+ return NULL;
+
+ /* Check if we need to grow the info table. */
+ if ((size_t) BLOCK ((char *) result + size) > heap->heapsize) {
+ newsize = heap->heapsize;
+
+ while ((size_t) BLOCK ((char *) result + size) > newsize)
+ newsize *= 2;
+
+ newinfo = (shmalloc_info *) align( heap, newsize * sizeof (shmalloc_info) );
+ if (newinfo == NULL) {
+ __shmalloc_brk( heap, -size );
+ return NULL;
+ }
+
+ direct_memcpy( newinfo, heap->heapinfo,
+ heap->heapsize * sizeof (shmalloc_info) );
+
+ memset (newinfo + heap->heapsize,
+ 0, (newsize - heap->heapsize) * sizeof (shmalloc_info));
+
+ oldinfo = heap->heapinfo;
+
+ newinfo[BLOCK (oldinfo)].busy.type = 0;
+ newinfo[BLOCK (oldinfo)].busy.info.size = BLOCKIFY (heap->heapsize * sizeof (shmalloc_info));
+
+ heap->heapinfo = newinfo;
+
+ _fusion_shfree( heap, oldinfo );
+
+ heap->heapsize = newsize;
+ }
+
+ heap->heaplimit = BLOCK ((char *) result + size);
+
+ return result;
+}
+
+/**********************************************************************************************************************/
+
+/* Allocate memory from the heap. */
+void *
+_fusion_shmalloc( shmalloc_heap *heap, size_t size )
+{
+ void *result;
+ size_t block, blocks, lastblocks, start;
+ register size_t i;
+ struct list *next;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %zu )\n", __FUNCTION__, heap, size );
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ /* Some programs will call shmalloc (0). We let them pass. */
+ if (size == 0)
+ return NULL;
+
+ if (size < sizeof (struct list))
+ size = sizeof (struct list);
+
+ /* Determine the allocation policy based on the request size. */
+ if (size <= BLOCKSIZE / 2) {
+ /* Small allocation to receive a fragment of a block.
+ Determine the logarithm to base two of the fragment size. */
+ register size_t log = 1;
+ --size;
+ while ((size /= 2) != 0)
+ ++log;
+
+ /* Look in the fragment lists for a
+ free fragment of the desired size. */
+ next = heap->fraghead[log].next;
+ if (next != NULL) {
+ /* There are free fragments of this size.
+ Pop a fragment out of the fragment list and return it.
+ Update the block's nfree and first counters. */
+ result = (void *) next;
+ next->prev->next = next->next;
+ if (next->next != NULL)
+ next->next->prev = next->prev;
+ block = BLOCK (result);
+ if (--(heap->heapinfo[block].busy.info.frag.nfree) != 0)
+ heap->heapinfo[block].busy.info.frag.first = (unsigned long int)
+ ((unsigned long int) ((char *) next->next - (char *) NULL)
+ % BLOCKSIZE) >> log;
+
+ /* Update the statistics. */
+ heap->chunks_used++;
+ heap->bytes_used += 1 << log;
+ heap->chunks_free--;
+ heap->bytes_free -= 1 << log;
+ }
+ else {
+ /* No free fragments of the desired size, so get a new block
+ and break it into fragments, returning the first. */
+ result = _fusion_shmalloc( heap, BLOCKSIZE );
+ if (result == NULL)
+ return NULL;
+#if 1 /* Adapted from Mike */
+ heap->fragblocks[log]++;
+#endif
+
+ /* Link all fragments but the first into the free list. */
+ for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) {
+ next = (struct list *) ((char *) result + (i << log));
+ next->next = heap->fraghead[log].next;
+ next->prev = &heap->fraghead[log];
+ next->prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ }
+
+ /* Initialize the nfree and first counters for this block. */
+ block = BLOCK (result);
+ heap->heapinfo[block].busy.type = log;
+ heap->heapinfo[block].busy.info.frag.nfree = i - 1;
+ heap->heapinfo[block].busy.info.frag.first = i - 1;
+
+ heap->chunks_free += (BLOCKSIZE >> log) - 1;
+ heap->bytes_free += BLOCKSIZE - (1 << log);
+ heap->bytes_used -= BLOCKSIZE - (1 << log);
+ }
+ }
+ else {
+ /* Large allocation to receive one or more blocks.
+ Search the free list in a circle starting at the last place visited.
+ If we loop completely around without finding a large enough
+ space we will have to get more memory from the system. */
+ blocks = BLOCKIFY (size);
+ start = block = heap->heapindex;
+ while (heap->heapinfo[block].free.size < blocks) {
+ block = heap->heapinfo[block].free.next;
+ if (block == start) {
+ /* Need to get more from the system. Check to see if
+ the new core will be contiguous with the final free
+ block; if so we don't need to get as much. */
+ block = heap->heapinfo[0].free.prev;
+ lastblocks = heap->heapinfo[block].free.size;
+ if (heap->heaplimit != 0 && block + lastblocks == heap->heaplimit &&
+ __shmalloc_brk( heap, 0 ) == ADDRESS (block + lastblocks) &&
+ (morecore( heap, (blocks - lastblocks) * BLOCKSIZE) ) != NULL) {
+#if 1 /* Adapted from Mike */
+
+ /* Note that morecore() can change the location of
+ the final block if it moves the info table and the
+ old one gets coalesced into the final block. */
+ block = heap->heapinfo[0].free.prev;
+ heap->heapinfo[block].free.size += blocks - lastblocks;
+#else
+ heap->heapinfo[block].free.size = blocks;
+#endif
+ heap->bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+ continue;
+ }
+ result = morecore( heap, blocks * BLOCKSIZE );
+ if (result == NULL)
+ return NULL;
+ block = BLOCK (result);
+ heap->heapinfo[block].busy.type = 0;
+ heap->heapinfo[block].busy.info.size = blocks;
+ heap->chunks_used++;
+ heap->bytes_used += blocks * BLOCKSIZE;
+ return result;
+ }
+ }
+
+ /* At this point we have found a suitable free list entry.
+ Figure out how to remove what we need from the list. */
+ result = ADDRESS (block);
+ if (heap->heapinfo[block].free.size > blocks) {
+ /* The block we found has a bit left over,
+ so relink the tail end back into the free list. */
+ heap->heapinfo[block + blocks].free.size
+ = heap->heapinfo[block].free.size - blocks;
+ heap->heapinfo[block + blocks].free.next
+ = heap->heapinfo[block].free.next;
+ heap->heapinfo[block + blocks].free.prev
+ = heap->heapinfo[block].free.prev;
+ heap->heapinfo[heap->heapinfo[block].free.prev].free.next
+ = heap->heapinfo[heap->heapinfo[block].free.next].free.prev
+ = heap->heapindex = block + blocks;
+ }
+ else {
+ /* The block exactly matches our requirements,
+ so just remove it from the list. */
+ heap->heapinfo[heap->heapinfo[block].free.next].free.prev
+ = heap->heapinfo[block].free.prev;
+ heap->heapinfo[heap->heapinfo[block].free.prev].free.next
+ = heap->heapindex = heap->heapinfo[block].free.next;
+ heap->chunks_free--;
+ }
+
+ heap->heapinfo[block].busy.type = 0;
+ heap->heapinfo[block].busy.info.size = blocks;
+ heap->chunks_used++;
+ heap->bytes_used += blocks * BLOCKSIZE;
+ heap->bytes_free -= blocks * BLOCKSIZE;
+ }
+
+ return result;
+}
+
+/* Resize the given region to the new size, returning a pointer
+ to the (possibly moved) region. This is optimized for speed;
+ some benchmarks seem to indicate that greater compactness is
+ achieved by unconditionally allocating and copying to a
+ new region. This module has incestuous knowledge of the
+ internals of both free and shmalloc. */
+void *
+_fusion_shrealloc( shmalloc_heap *heap, void *ptr, size_t size )
+{
+ void *result;
+ int type;
+ size_t block, blocks, oldlimit;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %p, %zu )\n", __FUNCTION__, heap, ptr, size );
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ if (ptr == NULL)
+ return _fusion_shmalloc( heap, size );
+ else if (size == 0) {
+ _fusion_shfree( heap, ptr );
+ return NULL;
+ }
+
+ block = BLOCK (ptr);
+
+ type = heap->heapinfo[block].busy.type;
+ switch (type) {
+ case 0:
+ /* Maybe reallocate a large block to a small fragment. */
+ if (size <= BLOCKSIZE / 2) {
+ result = _fusion_shmalloc( heap, size );
+ if (result != NULL) {
+ direct_memcpy (result, ptr, size);
+ _fusion_shfree( heap, ptr );
+ return result;
+ }
+ }
+
+ /* The new size is a large allocation as well;
+ see if we can hold it in place. */
+ blocks = BLOCKIFY (size);
+ if (blocks < heap->heapinfo[block].busy.info.size) {
+ /* The new size is smaller; return
+ excess memory to the free list. */
+ heap->heapinfo[block + blocks].busy.type = 0;
+ heap->heapinfo[block + blocks].busy.info.size
+ = heap->heapinfo[block].busy.info.size - blocks;
+ heap->heapinfo[block].busy.info.size = blocks;
+ _fusion_shfree( heap, ADDRESS (block + blocks) );
+ result = ptr;
+ }
+ else if (blocks == heap->heapinfo[block].busy.info.size)
+ /* No size change necessary. */
+ result = ptr;
+ else {
+ /* Won't fit, so allocate a new region that will.
+ Free the old region first in case there is sufficient
+ adjacent free space to grow without moving. */
+ blocks = heap->heapinfo[block].busy.info.size;
+ /* Prevent free from actually returning memory to the system. */
+ oldlimit = heap->heaplimit;
+ heap->heaplimit = 0;
+ _fusion_shfree( heap, ptr );
+ heap->heaplimit = oldlimit;
+ result = _fusion_shmalloc( heap, size );
+ if (result == NULL) {
+ /* Now we're really in trouble. We have to unfree
+ the thing we just freed. Unfortunately it might
+ have been coalesced with its neighbors. */
+ if (heap->heapindex == block)
+ (void) _fusion_shmalloc( heap, blocks * BLOCKSIZE );
+ else {
+ void *previous = _fusion_shmalloc( heap, (block - heap->heapindex) * BLOCKSIZE );
+ (void) _fusion_shmalloc( heap, blocks * BLOCKSIZE );
+ _fusion_shfree( heap, previous );
+ }
+ return NULL;
+ }
+ if (ptr != result)
+ direct_memmove (result, ptr, blocks * BLOCKSIZE);
+ }
+ break;
+
+ default:
+ /* Old size is a fragment; type is logarithm
+ to base two of the fragment size. */
+ if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
+ /* The new size is the same kind of fragment. */
+ result = ptr;
+ else {
+ /* The new size is different; allocate a new space,
+ and copy the lesser of the new size and the old. */
+ result = _fusion_shmalloc( heap, size );
+ if (result == NULL)
+ return NULL;
+ direct_memcpy (result, ptr, MIN (size, (size_t) 1 << type));
+ _fusion_shfree( heap, ptr );
+ }
+ break;
+ }
+
+ return result;
+}
+
+/* Return memory to the heap. */
+void
+_fusion_shfree( shmalloc_heap *heap, void *ptr )
+{
+ int type;
+ size_t block, blocks;
+ register size_t i;
+ struct list *prev, *next;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %p )\n", __FUNCTION__, heap, ptr );
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ if (ptr == NULL)
+ return;
+
+ block = BLOCK (ptr);
+
+ type = heap->heapinfo[block].busy.type;
+ switch (type) {
+ case 0:
+ /* Get as many statistics as early as we can. */
+ heap->chunks_used--;
+ heap->bytes_used -= heap->heapinfo[block].busy.info.size * BLOCKSIZE;
+ heap->bytes_free += heap->heapinfo[block].busy.info.size * BLOCKSIZE;
+
+ /* Find the free cluster previous to this one in the free list.
+ Start searching at the last block referenced; this may benefit
+ programs with locality of allocation. */
+ i = heap->heapindex;
+ if (i > block)
+ while (i > block)
+ i = heap->heapinfo[i].free.prev;
+ else {
+ do
+ i = heap->heapinfo[i].free.next;
+ while (i > 0 && i < block);
+ i = heap->heapinfo[i].free.prev;
+ }
+
+ /* Determine how to link this block into the free list. */
+ if (block == i + heap->heapinfo[i].free.size) {
+ /* Coalesce this block with its predecessor. */
+ heap->heapinfo[i].free.size += heap->heapinfo[block].busy.info.size;
+ block = i;
+ }
+ else {
+ /* Really link this block back into the free list. */
+ heap->heapinfo[block].free.size = heap->heapinfo[block].busy.info.size;
+ heap->heapinfo[block].free.next = heap->heapinfo[i].free.next;
+ heap->heapinfo[block].free.prev = i;
+ heap->heapinfo[i].free.next = block;
+ heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block;
+ heap->chunks_free++;
+ }
+
+ /* Now that the block is linked in, see if we can coalesce it
+ with its successor (by deleting its successor from the list
+ and adding in its size). */
+ if (block + heap->heapinfo[block].free.size == heap->heapinfo[block].free.next) {
+ heap->heapinfo[block].free.size
+ += heap->heapinfo[heap->heapinfo[block].free.next].free.size;
+ heap->heapinfo[block].free.next
+ = heap->heapinfo[heap->heapinfo[block].free.next].free.next;
+ heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block;
+ heap->chunks_free--;
+ }
+
+ blocks = heap->heapinfo[block].free.size;
+
+/* FIXME: as this is used when kernel is detected as >= 2.6.19.2 only, this fallback definition should be ok for now */
+#ifndef MADV_REMOVE
+#define MADV_REMOVE 9
+#endif
+ /* Punch a hole into the tmpfs file to really free RAM. */
+ if (fusion_config->madv_remove)
+ madvise( ADDRESS(block), blocks * BLOCKSIZE, MADV_REMOVE );
+
+ /* Now see if we can truncate the end. */
+ if (blocks >= FINAL_FREE_BLOCKS && block + blocks == heap->heaplimit
+ && __shmalloc_brk( heap, 0 ) == ADDRESS (block + blocks))
+ {
+ register size_t bytes = blocks * BLOCKSIZE;
+ heap->heaplimit -= blocks;
+ __shmalloc_brk( heap, -bytes );
+ heap->heapinfo[heap->heapinfo[block].free.prev].free.next = heap->heapinfo[block].free.next;
+ heap->heapinfo[heap->heapinfo[block].free.next].free.prev = heap->heapinfo[block].free.prev;
+ block = heap->heapinfo[block].free.prev;
+ heap->chunks_free--;
+ heap->bytes_free -= bytes;
+ }
+
+ /* Set the next search to begin at this block. */
+ heap->heapindex = block;
+ break;
+
+ default:
+ /* Do some of the statistics. */
+ heap->chunks_used--;
+ heap->bytes_used -= 1 << type;
+ heap->chunks_free++;
+ heap->bytes_free += 1 << type;
+
+ /* Get the address of the first free fragment in this block. */
+ prev = (struct list *) ((char *) ADDRESS (block) +
+ (heap->heapinfo[block].busy.info.frag.first << type));
+
+#if 1 /* Adapted from Mike */
+ if ((int)heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1
+ && heap->fragblocks[type] > 1)
+#else
+ if ((int)heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+#endif
+ {
+ /* If all fragments of this block are free, remove them
+ from the fragment list and free the whole block. */
+#if 1 /* Adapted from Mike */
+ heap->fragblocks[type]--;
+#endif
+ next = prev;
+ for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
+ next = next->next;
+ prev->prev->next = next;
+ if (next != NULL)
+ next->prev = prev->prev;
+ heap->heapinfo[block].busy.type = 0;
+ heap->heapinfo[block].busy.info.size = 1;
+
+ /* Keep the statistics accurate. */
+ heap->chunks_used++;
+ heap->bytes_used += BLOCKSIZE;
+ heap->chunks_free -= BLOCKSIZE >> type;
+ heap->bytes_free -= BLOCKSIZE;
+
+ _fusion_shfree( heap, ADDRESS (block) );
+ }
+ else if (heap->heapinfo[block].busy.info.frag.nfree != 0) {
+ /* If some fragments of this block are free, link this
+ fragment into the fragment list after the first free
+ fragment of this block. */
+ next = (struct list *) ptr;
+ next->next = prev->next;
+ next->prev = prev;
+ prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ heap->heapinfo[block].busy.info.frag.nfree++;
+ }
+ else {
+ /* No fragments of this block are free, so link this
+ fragment into the fragment list and announce that
+ it is the first free fragment of this block. */
+ prev = (struct list *) ptr;
+ heap->heapinfo[block].busy.info.frag.nfree = 1;
+ heap->heapinfo[block].busy.info.frag.first = (unsigned long int)
+ ((unsigned long int) ((char *) ptr - (char *) NULL)
+ % BLOCKSIZE >> type);
+ prev->next = heap->fraghead[type].next;
+ prev->prev = &heap->fraghead[type];
+ prev->prev->next = prev;
+ if (prev->next != NULL)
+ prev->next->prev = prev;
+ }
+ break;
+ }
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+__shmalloc_init_heap( FusionSHM *shm,
+ const char *filename,
+ void *addr_base,
+ int space,
+ int *ret_fd,
+ int *ret_size )
+{
+ DirectResult ret;
+ int size;
+ FusionSHMShared *shared;
+ int heapsize = (space + BLOCKSIZE-1) / BLOCKSIZE;
+ int fd = -1;
+ shmalloc_heap *heap = NULL;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %d, %p, %p )\n",
+ __FUNCTION__, shm, filename, addr_base, space, ret_fd, ret_size );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_ASSERT( filename != NULL );
+ D_ASSERT( addr_base != NULL );
+ D_ASSERT( ret_fd != NULL );
+ D_ASSERT( ret_size != NULL );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+ D_ASSERT( shared->tmpfs[0] != 0 );
+
+ size = BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( heapsize * sizeof(shmalloc_info) );
+
+
+ D_DEBUG_AT( Fusion_SHMHeap, " -> opening shared memory file '%s'...\n", filename );
+
+ /* open the virtual file */
+ fd = open( filename, O_RDWR | O_CREAT | O_TRUNC, 0660 );
+ if (fd < 0) {
+ ret = errno2result(errno);
+ D_PERROR( "Fusion/SHM: Could not open shared memory file '%s'!\n", filename );
+ goto error;
+ }
+
+ if (fusion_config->shmfile_gid != (gid_t)-1) {
+ /* chgrp the SH_FILE dev entry */
+ if (fchown( fd, -1, fusion_config->shmfile_gid ) != 0)
+ D_WARN( "Fusion/SHM: Changing owner on %s failed... continuing on.", filename );
+ }
+
+ fchmod( fd, 0660 );
+ ftruncate( fd, size );
+
+ D_DEBUG_AT( Fusion_SHMHeap, " -> mmaping shared memory file... (%d bytes)\n", size );
+
+ /* map it shared */
+ heap = mmap( addr_base, size + space, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 );
+ if (heap == MAP_FAILED) {
+ ret = errno2result(errno);
+ D_PERROR( "Fusion/SHM: Could not mmap shared memory file '%s'!\n", filename );
+ goto error;
+ }
+
+ if (heap != addr_base) {
+ D_ERROR( "Fusion/SHM: mmap() returned address (%p) differs from requested (%p)\n", heap, addr_base );
+ ret = DR_FUSION;
+ goto error;
+ }
+
+ D_DEBUG_AT( Fusion_SHMHeap, " -> done.\n" );
+
+ heap->size = size;
+ heap->heapsize = heapsize;
+ heap->heapinfo = (void*) heap + BLOCKALIGN(sizeof(shmalloc_heap));
+ heap->heapbase = (char*) heap->heapinfo;
+
+ D_MAGIC_SET( heap, shmalloc_heap );
+
+ *ret_fd = fd;
+ *ret_size = size;
+
+ return DR_OK;
+
+
+error:
+ if (heap)
+ munmap( heap, size );
+
+ if (fd != -1) {
+ close( fd );
+ unlink( filename );
+ }
+
+ return ret;
+}
+
+DirectResult
+__shmalloc_join_heap( FusionSHM *shm,
+ const char *filename,
+ void *addr_base,
+ int size,
+ int *ret_fd )
+{
+ DirectResult ret;
+ FusionSHMShared *shared;
+ int fd = -1;
+ shmalloc_heap *heap = NULL;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %d, %p )\n",
+ __FUNCTION__, shm, filename, addr_base, size, ret_fd );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_ASSERT( filename != NULL );
+ D_ASSERT( addr_base != NULL );
+ D_ASSERT( size >= sizeof(shmalloc_heap) );
+ D_ASSERT( ret_fd != NULL );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+ D_ASSERT( shared->tmpfs[0] != 0 );
+
+ D_DEBUG_AT( Fusion_SHMHeap, " -> opening shared memory file '%s'...\n", filename );
+
+ /* open the virtual file */
+ fd = open( filename, O_RDWR );
+ if (fd < 0) {
+ ret = errno2result(errno);
+ D_PERROR( "Fusion/SHM: Could not open shared memory file '%s'!\n", filename );
+ goto error;
+ }
+
+ D_DEBUG_AT( Fusion_SHMHeap, " -> mmaping shared memory file... (%d bytes)\n", size );
+
+ /* map it shared */
+ heap = mmap( addr_base, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 );
+ if (heap == MAP_FAILED) {
+ ret = errno2result(errno);
+ D_PERROR( "Fusion/SHM: Could not mmap shared memory file '%s'!\n", filename );
+ goto error;
+ }
+
+ if (heap != addr_base) {
+ D_ERROR( "Fusion/SHM: mmap() returned address (%p) differs from requested (%p)\n", heap, addr_base );
+ ret = DR_FUSION;
+ goto error;
+ }
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ D_DEBUG_AT( Fusion_SHMHeap, " -> done.\n" );
+
+ *ret_fd = fd;
+
+ return DR_OK;
+
+
+error:
+ if (heap)
+ munmap( heap, size );
+
+ if (fd != -1)
+ close( fd );
+
+ return ret;
+}
+
+void *
+__shmalloc_brk( shmalloc_heap *heap, int increment )
+{
+ FusionSHMShared *shm;
+ FusionWorld *world;
+ FusionSHMPool *pool;
+ FusionSHMPoolShared *shared;
+
+ D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %d )\n", __FUNCTION__, heap, increment );
+
+ D_MAGIC_ASSERT( heap, shmalloc_heap );
+
+ shared = heap->pool;
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+ shm = shared->shm;
+ D_MAGIC_ASSERT( shm, FusionSHMShared );
+
+ world = _fusion_world( shm->world );
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ pool = &world->shm.pools[shared->index];
+ D_MAGIC_ASSERT( pool, FusionSHMPool );
+
+ if (increment) {
+ int new_size = heap->size + increment;
+
+ if (new_size > shared->max_size) {
+ D_WARN( "maximum shared memory size exceeded!" );
+ fusion_dbg_print_memleaks( shared );
+ return NULL;
+ }
+
+ if (ftruncate( pool->fd, new_size ) < 0) {
+ D_PERROR( "Fusion/SHM: ftruncating shared memory file failed!\n" );
+ return NULL;
+ }
+
+ heap->size = new_size;
+ }
+
+ return shared->addr_base + heap->size - increment;
+}
+
diff --git a/Source/DirectFB/lib/fusion/shm/pool.c b/Source/DirectFB/lib/fusion/shm/pool.c
new file mode 100755
index 0000000..030314f
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/pool.c
@@ -0,0 +1,954 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+#include <fusion/shmalloc.h>
+#include <fusion/fusion_internal.h>
+
+#include <fusion/shm/pool.h>
+#include <fusion/shm/shm_internal.h>
+
+
+D_DEBUG_DOMAIN( Fusion_SHMPool, "Fusion/SHMPool", "Fusion Shared Memory Pool" );
+
+/**********************************************************************************************************************/
+
+static DirectResult init_pool ( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared,
+ const char *name,
+ unsigned int max_size,
+ bool debug );
+
+static DirectResult join_pool ( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared );
+
+static void leave_pool ( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared );
+
+static void shutdown_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared );
+
+/**********************************************************************************************************************/
+
+DirectResult
+fusion_shm_pool_create( FusionWorld *world,
+ const char *name,
+ unsigned int max_size,
+ bool debug,
+ FusionSHMPoolShared **ret_pool )
+{
+ int i;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+ D_ASSERT( name != NULL );
+ D_ASSERT( max_size > 0 );
+ D_ASSERT( ret_pool != NULL );
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p [%d], '%s', %d, %p, %sdebug )\n", __FUNCTION__,
+ world, world->shared->world_index, name, max_size, ret_pool, debug ? "" : "non-" );
+
+#if !DIRECT_BUILD_DEBUGS
+ debug = false;
+#endif
+
+ shm = &world->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ if (max_size < 8192) {
+ D_ERROR( "Fusion/SHMPool: Maximum size (%d) should be 8192 at least!\n", max_size );
+ return DR_INVARG;
+ }
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ goto error;
+
+ if (shared->num_pools == FUSION_SHM_MAX_POOLS) {
+ D_ERROR( "Fusion/SHMPool: Maximum number of pools (%d) already reached!\n", FUSION_SHM_MAX_POOLS );
+ ret = DR_LIMITEXCEEDED;
+ goto error;
+ }
+
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (!shared->pools[i].active)
+ break;
+
+ D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared );
+ D_MAGIC_ASSUME( &shm->pools[i], FusionSHMPool );
+ }
+
+ D_ASSERT( i < FUSION_SHM_MAX_POOLS );
+
+ D_DEBUG_AT( Fusion_SHMPool, " -> index %d\n", i );
+
+ memset( &shm->pools[i], 0, sizeof(FusionSHMPool) );
+ memset( &shared->pools[i], 0, sizeof(FusionSHMPoolShared) );
+
+ shared->pools[i].index = i;
+
+ ret = init_pool( shm, &shm->pools[i], &shared->pools[i], name, max_size, debug );
+ if (ret)
+ goto error;
+
+ shared->num_pools++;
+
+ fusion_skirmish_dismiss( &shared->lock );
+
+ *ret_pool = &shared->pools[i];
+
+ D_DEBUG_AT( Fusion_SHMPool, " -> %p\n", *ret_pool );
+
+ return DR_OK;
+
+
+error:
+ fusion_skirmish_dismiss( &shared->lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_shm_pool_destroy( FusionWorld *world,
+ FusionSHMPoolShared *pool )
+{
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, world, pool );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ shm = &world->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ D_ASSERT( shared == pool->shm );
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return ret;
+
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ fusion_skirmish_dismiss( &shared->lock );
+ return ret;
+ }
+
+ D_ASSERT( pool->active );
+ D_ASSERT( pool->index >= 0 );
+ D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS );
+ D_ASSERT( pool->pool_id == shm->pools[pool->index].pool_id );
+ D_ASSERT( pool == &shared->pools[pool->index] );
+
+ D_MAGIC_ASSERT( &shm->pools[pool->index], FusionSHMPool );
+
+ shutdown_pool( shm, &shm->pools[pool->index], pool );
+
+ shared->num_pools--;
+
+ fusion_skirmish_dismiss( &shared->lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_attach( FusionSHM *shm,
+ FusionSHMPoolShared *pool )
+{
+ DirectResult ret;
+ FusionSHMShared *shared;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, shm, pool );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ D_ASSERT( shared == pool->shm );
+
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ return ret;
+ }
+
+ D_ASSERT( pool->active );
+ D_ASSERT( pool->index >= 0 );
+ D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS );
+ D_ASSERT( pool == &shared->pools[pool->index] );
+ D_ASSERT( !shm->pools[pool->index].attached );
+
+ ret = join_pool( shm, &shm->pools[pool->index], pool );
+
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return ret;
+}
+
+DirectResult
+fusion_shm_pool_detach( FusionSHM *shm,
+ FusionSHMPoolShared *pool )
+{
+ DirectResult ret;
+ FusionSHMShared *shared;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, shm, pool );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ D_ASSERT( shared == pool->shm );
+
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ fusion_skirmish_dismiss( &shared->lock );
+ return ret;
+ }
+
+ D_ASSERT( pool->active );
+ D_ASSERT( pool->index >= 0 );
+ D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS );
+ D_ASSERT( pool->pool_id == shm->pools[pool->index].pool_id );
+ D_ASSERT( pool == &shared->pools[pool->index] );
+ D_ASSERT( shm->pools[pool->index].attached );
+
+ D_MAGIC_ASSERT( &shm->pools[pool->index], FusionSHMPool );
+
+ leave_pool( shm, &shm->pools[pool->index], pool );
+
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_allocate( FusionSHMPoolShared *pool,
+ int size,
+ bool clear,
+ bool lock,
+ void **ret_data )
+{
+ DirectResult ret;
+ void *data;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %d, %sclear, %p )\n", __FUNCTION__,
+ pool, size, clear ? "" : "un", ret_data );
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ D_ASSERT( size > 0 );
+ D_ASSERT( ret_data != NULL );
+
+ if (lock) {
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret)
+ return ret;
+ }
+
+ __shmalloc_brk( pool->heap, 0 );
+
+ data = _fusion_shmalloc( pool->heap, size );
+ if (!data) {
+ if (lock)
+ fusion_skirmish_dismiss( &pool->lock );
+ return DR_NOSHAREDMEMORY;
+ }
+
+ if (clear)
+ memset( data, 0, size );
+
+ *ret_data = data;
+
+ if (lock)
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_reallocate( FusionSHMPoolShared *pool,
+ void *data,
+ int size,
+ bool lock,
+ void **ret_data )
+{
+ DirectResult ret;
+ void *new_data;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %d, %p )\n",
+ __FUNCTION__, pool, data, size, ret_data );
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ D_ASSERT( data != NULL );
+ D_ASSERT( data >= pool->addr_base );
+ D_ASSERT( data < pool->addr_base + pool->max_size );
+ D_ASSERT( size > 0 );
+ D_ASSERT( ret_data != NULL );
+
+ if (lock) {
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret)
+ return ret;
+ }
+
+ __shmalloc_brk( pool->heap, 0 );
+
+ new_data = _fusion_shrealloc( pool->heap, data, size );
+ if (!new_data) {
+ if (lock)
+ fusion_skirmish_dismiss( &pool->lock );
+ return DR_NOSHAREDMEMORY;
+ }
+
+ *ret_data = new_data;
+
+ if (lock)
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_pool_deallocate( FusionSHMPoolShared *pool,
+ void *data,
+ bool lock )
+{
+ DirectResult ret;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, pool, data );
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ D_ASSERT( data != NULL );
+ D_ASSERT( data >= pool->addr_base );
+ D_ASSERT( data < pool->addr_base + pool->max_size );
+
+ if (lock) {
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret)
+ return ret;
+ }
+
+ __shmalloc_brk( pool->heap, 0 );
+
+ _fusion_shfree( pool->heap, data );
+
+ if (lock)
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+#if FUSION_BUILD_KERNEL
+
+static DirectResult
+init_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared,
+ const char *name,
+ unsigned int max_size,
+ bool debug )
+{
+ DirectResult ret;
+ int fd;
+ int size;
+ FusionWorld *world;
+ FusionSHMPoolNew pool_new = { .pool_id = 0 };
+ FusionSHMPoolAttach pool_attach = { .pool_id = 0 };
+ FusionEntryInfo info;
+ char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n",
+ __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( shm->shared, FusionSHMShared );
+ D_ASSERT( name != NULL );
+ D_ASSERT( max_size > sizeof(shmalloc_heap) );
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_ASSERT( pool != NULL );
+ D_ASSERT( shared != NULL );
+
+ /* Fill out information for new pool. */
+ pool_new.max_size = max_size;
+
+ pool_new.max_size += BLOCKALIGN(sizeof(shmalloc_heap)) +
+ BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) );
+
+ /* Create the new pool. */
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_NEW, &pool_new )) {
+ if (errno == EINTR)
+ continue;
+
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_NEW failed!\n" );
+ return DR_FUSION;
+ }
+
+ /* Set the pool info. */
+ info.type = FT_SHMPOOL;
+ info.id = pool_new.pool_id;
+
+ snprintf( info.name, sizeof(info.name), "%s", name );
+
+ ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );
+
+
+ /* Set pool to attach to. */
+ pool_attach.pool_id = pool_new.pool_id;
+
+ /* Attach to the pool. */
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) {
+ if (errno == EINTR)
+ continue;
+
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" );
+
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" );
+ break;
+ }
+ }
+
+ return DR_FUSION;
+ }
+
+
+ /* Generate filename. */
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs,
+ fusion_world_index( shm->world ), pool_new.pool_id );
+
+ /* Initialize the heap. */
+ ret = __shmalloc_init_heap( shm, buf, pool_new.addr_base, max_size, &fd, &size );
+ if (ret) {
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" );
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+
+ /* Initialize local data. */
+ pool->attached = true;
+ pool->shm = shm;
+ pool->shared = shared;
+ pool->pool_id = pool_new.pool_id;
+ pool->fd = fd;
+ pool->filename = D_STRDUP( buf );
+
+ /* Initialize shared data. */
+ shared->active = true;
+ shared->debug = debug;
+ shared->shm = shm->shared;
+ shared->max_size = pool_new.max_size;
+ shared->pool_id = pool_new.pool_id;
+ shared->addr_base = pool_new.addr_base;
+ shared->heap = pool_new.addr_base;
+ shared->heap->pool = shared;
+
+ fusion_skirmish_init( &shared->lock, name, world );
+
+
+ D_MAGIC_SET( pool, FusionSHMPool );
+ D_MAGIC_SET( shared, FusionSHMPoolShared );
+
+
+ shared->name = SHSTRDUP( shared, name );
+
+ return DR_OK;
+}
+
+static DirectResult
+join_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared )
+{
+ DirectResult ret;
+ int fd;
+ FusionWorld *world;
+ FusionSHMPoolAttach pool_attach = { .pool_id = 0 };
+ char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( shm->shared, FusionSHMShared );
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+#if !DIRECT_BUILD_DEBUGS
+ if (shared->debug) {
+ D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" );
+ return DR_UNSUPPORTED;
+ }
+#endif
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+
+ /* Set pool to attach to. */
+ pool_attach.pool_id = shared->pool_id;
+
+ /* Attach to the pool. */
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) {
+ if (errno == EINTR)
+ continue;
+
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" );
+ return DR_FUSION;
+ }
+
+
+ /* Generate filename. */
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs,
+ fusion_world_index( shm->world ), shared->pool_id );
+
+ /* Join the heap. */
+ ret = __shmalloc_join_heap( shm, buf, pool_attach.addr_base, shared->max_size, &fd );
+ if (ret) {
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" );
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+
+ /* Initialize local data. */
+ pool->attached = true;
+ pool->shm = shm;
+ pool->shared = shared;
+ pool->pool_id = shared->pool_id;
+ pool->fd = fd;
+ pool->filename = D_STRDUP( buf );
+
+
+ D_MAGIC_SET( pool, FusionSHMPool );
+
+ return DR_OK;
+}
+
+static void
+leave_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared )
+{
+ FusionWorld *world;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( pool, FusionSHMPool );
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" );
+ break;
+ }
+ }
+
+ if (munmap( shared->addr_base, shared->max_size ))
+ D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename );
+
+ if (pool->fd != -1 && close( pool->fd ))
+ D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename );
+
+ pool->attached = false;
+
+ D_FREE( pool->filename );
+
+ D_MAGIC_CLEAR( pool );
+}
+
+static void
+shutdown_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared )
+{
+ FusionWorld *world;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( pool, FusionSHMPool );
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ SHFREE( shared, shared->name );
+
+ fusion_dbg_print_memleaks( shared );
+
+ while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) {
+ if (errno != EINTR) {
+ D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" );
+ break;
+ }
+ }
+
+ if (munmap( shared->addr_base, shared->max_size ))
+ D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename );
+
+ if (pool->fd != -1 && close( pool->fd ))
+ D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename );
+
+ if (unlink( pool->filename ))
+ D_PERROR( "Fusion/SHM: Could not unlink shared memory file '%s'!\n", pool->filename );
+
+ shared->active = false;
+
+ pool->attached = false;
+
+ D_FREE( pool->filename );
+
+ D_MAGIC_CLEAR( pool );
+
+ fusion_skirmish_destroy( &shared->lock );
+
+ D_MAGIC_CLEAR( shared );
+}
+
+#else /* FUSION_BUILD_KERNEL */
+
+static DirectResult
+init_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared,
+ const char *name,
+ unsigned int max_size,
+ bool debug )
+{
+ DirectResult ret;
+ int fd;
+ int size;
+ long page_size;
+ int pool_id;
+ unsigned int pool_max_size;
+ void *pool_addr_base = NULL;
+ FusionWorld *world;
+ char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n",
+ __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( shm->shared, FusionSHMShared );
+ D_ASSERT( name != NULL );
+ D_ASSERT( max_size > sizeof(shmalloc_heap) );
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ D_ASSERT( pool != NULL );
+ D_ASSERT( shared != NULL );
+
+ page_size = direct_pagesize();
+
+ pool_id = ++world->shared->pool_ids;
+
+ pool_max_size = max_size + BLOCKALIGN(sizeof(shmalloc_heap)) +
+ BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) );
+
+ pool_addr_base = world->shared->pool_base;
+ world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(page_size - 1)) + page_size;
+ /* Exceeded limit? */
+ if (world->shared->pool_base > world->shared->pool_max)
+ return DR_NOSHAREDMEMORY;
+
+ /* Generate filename. */
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs,
+ fusion_world_index( world ), pool_id );
+
+ /* Initialize the heap. */
+ ret = __shmalloc_init_heap( shm, buf, pool_addr_base, max_size, &fd, &size );
+ if (ret)
+ return ret;
+
+ /* Initialize local data. */
+ pool->attached = true;
+ pool->shm = shm;
+ pool->shared = shared;
+ pool->pool_id = pool_id;
+ pool->fd = fd;
+ pool->filename = D_STRDUP( buf );
+
+ /* Initialize shared data. */
+ shared->active = true;
+ shared->debug = debug;
+ shared->shm = shm->shared;
+ shared->max_size = pool_max_size;
+ shared->pool_id = pool_id;
+ shared->addr_base = pool_addr_base;
+ shared->heap = pool_addr_base;
+ shared->heap->pool = shared;
+
+ fusion_skirmish_init( &shared->lock, name, world );
+
+
+ D_MAGIC_SET( pool, FusionSHMPool );
+ D_MAGIC_SET( shared, FusionSHMPoolShared );
+
+
+ shared->name = SHSTRDUP( shared, name );
+
+ return DR_OK;
+}
+
+static DirectResult
+join_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared )
+{
+ DirectResult ret;
+ int fd;
+ FusionWorld *world;
+ char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32];
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( shm->shared, FusionSHMShared );
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+#if !DIRECT_BUILD_DEBUGS
+ if (shared->debug) {
+ D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" );
+ return DR_UNSUPPORTED;
+ }
+#endif
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ /* Generate filename. */
+ snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs,
+ fusion_world_index( shm->world ), shared->pool_id );
+
+ /* Join the heap. */
+ ret = __shmalloc_join_heap( shm, buf, shared->addr_base, shared->max_size, &fd );
+ if (ret)
+ return ret;
+
+ /* Initialize local data. */
+ pool->attached = true;
+ pool->shm = shm;
+ pool->shared = shared;
+ pool->pool_id = shared->pool_id;
+ pool->fd = fd;
+ pool->filename = D_STRDUP( buf );
+
+
+ D_MAGIC_SET( pool, FusionSHMPool );
+
+ return DR_OK;
+}
+
+static void
+leave_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared )
+{
+ FusionWorld *world;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( pool, FusionSHMPool );
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ if (munmap( shared->addr_base, shared->max_size ))
+ D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename );
+
+ if (pool->fd != -1 && close( pool->fd ))
+ D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename );
+
+ pool->attached = false;
+
+ D_FREE( pool->filename );
+
+ D_MAGIC_CLEAR( pool );
+}
+
+static void
+shutdown_pool( FusionSHM *shm,
+ FusionSHMPool *pool,
+ FusionSHMPoolShared *shared )
+{
+ FusionWorld *world;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared );
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( pool, FusionSHMPool );
+ D_MAGIC_ASSERT( shared, FusionSHMPoolShared );
+
+ world = shm->world;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ SHFREE( shared, shared->name );
+
+ fusion_dbg_print_memleaks( shared );
+
+ if (munmap( shared->addr_base, shared->max_size ))
+ D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename );
+
+ if (pool->fd != -1 && close( pool->fd ))
+ D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename );
+
+ if (unlink( pool->filename ))
+ D_PERROR( "Fusion/SHM: Could not unlink shared memory file '%s'!\n", pool->filename );
+
+ shared->active = false;
+
+ pool->attached = false;
+
+ D_FREE( pool->filename );
+
+ D_MAGIC_CLEAR( pool );
+
+ fusion_skirmish_destroy( &shared->lock );
+
+ D_MAGIC_CLEAR( shared );
+}
+
+#endif /* FUSION_BUILD_KERNEL */
+
+/**********************************************************************************************************************/
+
+#if FUSION_BUILD_KERNEL
+void
+_fusion_shmpool_process( FusionWorld *world,
+ int pool_id,
+ FusionSHMPoolMessage *msg )
+{
+ int i;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %d, %p )\n", __FUNCTION__, world, pool_id, msg );
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shm = &world->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return;
+
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (shm->pools[i].attached) {
+ D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );
+
+ if (shm->pools[i].pool_id == pool_id) {
+ switch (msg->type) {
+ case FSMT_REMAP:
+ break;
+
+ case FSMT_UNMAP:
+ D_UNIMPLEMENTED();
+ break;
+ }
+
+ break;
+ }
+ }
+ }
+
+ fusion_skirmish_dismiss( &shared->lock );
+}
+#endif /* FUSION_BUILD_KERNEL */
diff --git a/Source/DirectFB/lib/fusion/shm/pool.h b/Source/DirectFB/lib/fusion/shm/pool.h
new file mode 100755
index 0000000..b809a5a
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/pool.h
@@ -0,0 +1,69 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__SHM__POOL_H__
+#define __FUSION__SHM__POOL_H__
+
+#include <fusion/types.h>
+
+
+DirectResult fusion_shm_pool_create ( FusionWorld *world,
+ const char *name,
+ unsigned int max_size,
+ bool debug,
+ FusionSHMPoolShared **ret_pool );
+
+DirectResult fusion_shm_pool_destroy ( FusionWorld *world,
+ FusionSHMPoolShared *pool );
+
+
+DirectResult fusion_shm_pool_attach ( FusionSHM *shm,
+ FusionSHMPoolShared *pool );
+
+DirectResult fusion_shm_pool_detach ( FusionSHM *shm,
+ FusionSHMPoolShared *pool );
+
+
+DirectResult fusion_shm_pool_allocate ( FusionSHMPoolShared *pool,
+ int size,
+ bool clear,
+ bool lock,
+ void **ret_data );
+
+DirectResult fusion_shm_pool_reallocate( FusionSHMPoolShared *pool,
+ void *data,
+ int size,
+ bool lock,
+ void **ret_data );
+
+DirectResult fusion_shm_pool_deallocate( FusionSHMPoolShared *pool,
+ void *data,
+ bool lock );
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/shm/shm.c b/Source/DirectFB/lib/fusion/shm/shm.c
new file mode 100755
index 0000000..21c7f42
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/shm.c
@@ -0,0 +1,337 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/signals.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/conf.h>
+#include <fusion/fusion_internal.h>
+
+#include <fusion/shm/pool.h>
+#include <fusion/shm/shm.h>
+#include <fusion/shm/shm_internal.h>
+
+
+/**********************************************************************************************************************/
+
+static int
+find_tmpfs( char *name, int len )
+{
+ int largest = 0;
+ char buffer[1024];
+ FILE *mounts_handle;
+
+ mounts_handle = fopen( "/proc/mounts", "r" );
+ if (!mounts_handle)
+ return 0;
+
+ while (fgets( buffer, sizeof(buffer), mounts_handle )) {
+ char *mount_point;
+ char *mount_fs;
+ char *pointer = buffer;
+
+ strsep( &pointer, " " );
+
+ mount_point = strsep( &pointer, " " );
+ mount_fs = strsep( &pointer, " " );
+
+ if (mount_fs && mount_point && !access( mount_point, W_OK ) &&
+ (!strcmp( mount_fs, "tmpfs" ) || !strcmp( mount_fs, "shmfs" ) || !strcmp( mount_fs, "ramfs" )))
+ {
+ struct statfs stat;
+ int bytes;
+
+ if (statfs( mount_point, &stat )) {
+ D_PERROR( "Fusion/SHM: statfs on '%s' failed!\n", mount_point );
+ continue;
+ }
+
+ bytes = stat.f_blocks * stat.f_bsize;
+
+ if (bytes > largest || (bytes == largest && !strcmp(mount_point,"/dev/shm"))) {
+ largest = bytes;
+
+ direct_snputs( name, mount_point, len );
+ }
+ }
+ }
+
+ fclose( mounts_handle );
+
+ return largest;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+fusion_shm_init( FusionWorld *world )
+{
+ int i;
+ int num;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+
+ shm = &world->shm;
+ shared = &world->shared->shm;
+
+ /* Initialize local data. */
+ memset( shm, 0, sizeof(FusionSHM) );
+
+ shm->world = world;
+ shm->shared = shared;
+
+ /* Initialize shared data. */
+ if (fusion_master( world )) {
+ memset( shared, 0, sizeof(FusionSHMShared) );
+
+ if (fusion_config->tmpfs) {
+ snprintf( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, fusion_config->tmpfs );
+ }
+ else if (!find_tmpfs( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN )) {
+ D_ERROR( "Fusion/SHM: Could not find tmpfs mount point, falling back to /dev/shm!\n" );
+ snprintf( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, "/dev/shm" );
+ }
+
+ shared->world = world->shared;
+
+ /* Initialize shared lock. */
+ ret = fusion_skirmish_init( &shared->lock, "Fusion SHM", world );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Failed to create skirmish!\n" );
+ return ret;
+ }
+
+ /* Initialize static pool array. */
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++)
+ shared->pools[i].index = i;
+
+ D_MAGIC_SET( shm, FusionSHM );
+ D_MAGIC_SET( shared, FusionSHMShared );
+ }
+ else {
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return ret;
+
+ D_MAGIC_SET( shm, FusionSHM );
+
+ for (i=0, num=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (shared->pools[i].active) {
+ D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared );
+
+ ret = fusion_shm_pool_attach( shm, &shared->pools[i] );
+ if (ret) {
+ for (--i; i>=0; i--) {
+ if (shared->pools[i].active)
+ fusion_shm_pool_detach( shm, &shared->pools[i] );
+ }
+
+ fusion_skirmish_dismiss( &shared->lock );
+
+ D_MAGIC_CLEAR( shm );
+
+ return ret;
+ }
+
+ num++;
+ }
+ }
+
+ D_ASSERT( num == shared->num_pools );
+
+ fusion_skirmish_dismiss( &shared->lock );
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_deinit( FusionWorld *world )
+{
+ int i;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+
+ shm = &world->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+
+ shared = shm->shared;
+
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return ret;
+
+ /* Deinitialize shared data. */
+ if (fusion_master( world )) {
+ D_ASSUME( shared->num_pools == 0 );
+
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (shared->pools[i].active) {
+ D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared );
+ D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );
+
+ D_WARN( "destroying remaining '%s'", shared->pools[i].name );
+
+ fusion_shm_pool_destroy( world, &shared->pools[i] );
+ }
+ }
+
+ /* Destroy shared lock. */
+ fusion_skirmish_destroy( &shared->lock );
+
+ D_MAGIC_CLEAR( shared );
+ }
+ else {
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (shared->pools[i].active) {
+ D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared );
+ D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );
+
+ fusion_shm_pool_detach( shm, &shared->pools[i] );
+ }
+ }
+
+ fusion_skirmish_dismiss( &shared->lock );
+ }
+
+ D_MAGIC_CLEAR( shm );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_attach_unattached( FusionWorld *world )
+{
+ int i;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+
+ shm = &world->shm;
+ shared = &world->shared->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return ret;
+
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (!shared->pools[i].active)
+ continue;
+
+ D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared );
+
+ if (!shm->pools[i].attached) {
+ ret = fusion_shm_pool_attach( shm, &shared->pools[i] );
+ if (ret)
+ D_DERROR( ret, "fusion_shm_pool_attach( '%s' ) failed!\n", shared->pools[i].name );
+ }
+ else
+ D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );
+ }
+
+ fusion_skirmish_dismiss( &shared->lock );
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_shm_enum_pools( FusionWorld *world,
+ FusionSHMPoolCallback callback,
+ void *ctx )
+{
+ int i;
+ DirectResult ret;
+ FusionSHM *shm;
+ FusionSHMShared *shared;
+
+ D_MAGIC_ASSERT( world, FusionWorld );
+ D_MAGIC_ASSERT( world->shared, FusionWorldShared );
+ D_ASSERT( callback != NULL );
+
+ shm = &world->shm;
+ shared = &world->shared->shm;
+
+ D_MAGIC_ASSERT( shm, FusionSHM );
+ D_MAGIC_ASSERT( shared, FusionSHMShared );
+
+ ret = fusion_skirmish_prevail( &shared->lock );
+ if (ret)
+ return ret;
+
+ for (i=0; i<FUSION_SHM_MAX_POOLS; i++) {
+ if (!shared->pools[i].active)
+ continue;
+
+ if (!shm->pools[i].attached) {
+ D_BUG( "not attached to pool" );
+ continue;
+ }
+
+ D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool );
+ D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared );
+
+ if (callback( &shm->pools[i], ctx ) == DENUM_CANCEL)
+ break;
+ }
+
+ fusion_skirmish_dismiss( &shared->lock );
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/fusion/shm/shm.h b/Source/DirectFB/lib/fusion/shm/shm.h
new file mode 100755
index 0000000..6764d17
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/shm.h
@@ -0,0 +1,48 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__SHM__SHM_H__
+#define __FUSION__SHM__SHM_H__
+
+#include <fusion/types.h>
+
+typedef DirectEnumerationResult (*FusionSHMPoolCallback)( FusionSHMPool *pool,
+ void *ctx );
+
+DirectResult fusion_shm_init ( FusionWorld *world );
+
+DirectResult fusion_shm_deinit( FusionWorld *world );
+
+DirectResult fusion_shm_attach_unattached( FusionWorld *world );
+
+DirectResult fusion_shm_enum_pools( FusionWorld *world,
+ FusionSHMPoolCallback callback,
+ void *ctx );
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/shm/shm_internal.h b/Source/DirectFB/lib/fusion/shm/shm_internal.h
new file mode 100755
index 0000000..3e282a5
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shm/shm_internal.h
@@ -0,0 +1,264 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__SHM__SHM_INTERNAL_H__
+#define __FUSION__SHM__SHM_INTERNAL_H__
+
+#include <limits.h>
+
+#include <direct/list.h>
+
+#include <fusion/build.h>
+#include <fusion/lock.h>
+
+
+#define FUSION_SHM_MAX_POOLS 24
+#define FUSION_SHM_TMPFS_PATH_NAME_LEN 64
+
+
+typedef struct __shmalloc_heap shmalloc_heap;
+
+
+/*
+ * Local pool data.
+ */
+struct __Fusion_FusionSHMPool {
+ int magic;
+
+ bool attached; /* Indicates usage of this entry in the static pool array. */
+
+ FusionSHM *shm; /* Back pointer to local SHM data. */
+
+ FusionSHMPoolShared *shared; /* Pointer to shared pool data. */
+
+ int pool_id; /* The pool's ID within the world. */
+
+ int fd; /* File descriptor of shared memory file. */
+ char *filename; /* Name of the shared memory file. */
+};
+
+/*
+ * Shared pool data.
+ */
+struct __Fusion_FusionSHMPoolShared {
+ int magic;
+
+ bool debug; /* Debug allocations in this pool? */
+
+ int index; /* Index within the static pool array. */
+ bool active; /* Indicates usage of this entry in the static pool array. */
+
+ FusionSHMShared *shm; /* Back pointer to shared SHM data. */
+
+ int max_size; /* Maximum possible size of the shared memory. */
+ int pool_id; /* The pool's ID within the world. */
+ void *addr_base; /* Virtual starting address of shared memory. */
+
+ FusionSkirmish lock; /* Lock for this pool. */
+
+ shmalloc_heap *heap; /* The actual heap information ported from libc5. */
+
+ char *name; /* Name of the pool (allocated in the pool). */
+
+ DirectLink *allocs; /* Used for debugging. */
+};
+
+
+/*
+ * Local SHM data.
+ */
+struct __Fusion_FusionSHM {
+ int magic;
+
+ FusionWorld *world; /* Back pointer to local world data. */
+
+ FusionSHMShared *shared; /* Pointer to shared SHM data. */
+
+ FusionSHMPool pools[FUSION_SHM_MAX_POOLS]; /* Local data of all pools. */
+
+ DirectSignalHandler *signal_handler;
+};
+
+/*
+ * Shared SHM data.
+ */
+struct __Fusion_FusionSHMShared {
+ int magic;
+
+ FusionWorldShared *world; /* Back pointer to shared world data. */
+
+ FusionSkirmish lock; /* Lock for list of pools. */
+
+ int num_pools; /* Number of active pools. */
+ FusionSHMPoolShared pools[FUSION_SHM_MAX_POOLS]; /* Shared data of all pools. */
+
+ char tmpfs[FUSION_SHM_TMPFS_PATH_NAME_LEN];
+};
+
+
+
+/* The allocator divides the heap into blocks of fixed size; large
+ requests receive one or more whole blocks, and small requests
+ receive a fragment of a block. Fragment sizes are powers of two,
+ and all fragments of a block are the same size. When all the
+ fragments in a block have been freed, the block itself is freed. */
+#define INT_BIT (CHAR_BIT * sizeof(int))
+#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+#define BLOCKALIGN(SIZE) (((SIZE) + BLOCKSIZE - 1) & ~(BLOCKSIZE - 1))
+
+/* Number of contiguous free blocks allowed to build up at the end of
+ memory before they will be returned to the system. */
+#define FINAL_FREE_BLOCKS 8
+
+/* Address to block number and vice versa. */
+#define BLOCK(A) (((char *) (A) - heap->heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + heap->heapbase))
+
+
+/* Data structure giving per-block information. */
+typedef union {
+
+ /* Heap information for a busy block. */
+ struct {
+
+ /* Zero for a large block, or positive giving the
+ logarithm to the base two of the fragment size. */
+ int type;
+
+ union {
+ struct {
+ size_t nfree; /* Free fragments in a fragmented block. */
+ size_t first; /* First free fragment of the block. */
+ } frag;
+
+ /* Size (in blocks) of a large cluster. */
+ size_t size;
+ } info;
+ } busy;
+
+ /* Heap information for a free block
+ (that may be the first of a free cluster). */
+ struct {
+ size_t size; /* Size (in blocks) of a free cluster. */
+ size_t next; /* Index of next free cluster. */
+ size_t prev; /* Index of previous free cluster. */
+ } free;
+} shmalloc_info;
+
+/* Doubly linked lists of free fragments. */
+struct list {
+ struct list *next;
+ struct list *prev;
+};
+
+
+#define SHMEMDESC_FUNC_NAME_LENGTH 48
+#define SHMEMDESC_FILE_NAME_LENGTH 24
+
+/* Used for debugging. */
+typedef struct {
+ DirectLink link;
+
+ const void *mem;
+ size_t bytes;
+ char func[SHMEMDESC_FUNC_NAME_LENGTH];
+ char file[SHMEMDESC_FILE_NAME_LENGTH];
+ unsigned int line;
+
+ FusionID fid;
+} SHMemDesc;
+
+
+struct __shmalloc_heap {
+ int magic;
+
+ /* Pointer to first block of the heap. */
+ char *heapbase;
+
+ /* Block information table indexed by block number giving per-block information. */
+ shmalloc_info *heapinfo;
+
+ /* Number of info entries. */
+ size_t heapsize;
+
+ /* Current search index for the heap table. */
+ size_t heapindex;
+
+ /* Limit of valid info table indices. */
+ size_t heaplimit;
+
+#if 1 /* Adapted from Mike */
+ /* Count of large blocks allocated for each fragment size. */
+ int fragblocks[BLOCKLOG];
+#endif
+
+ /* Free list headers for each fragment size. */
+ struct list fraghead[BLOCKLOG];
+
+ /* Instrumentation. */
+ size_t chunks_used;
+ size_t bytes_used;
+ size_t chunks_free;
+ size_t bytes_free;
+
+ /* Total size of heap in bytes. */
+ int size;
+
+ /* Back pointer to shared memory pool. */
+ FusionSHMPoolShared *pool;
+};
+
+
+void *_fusion_shmalloc (shmalloc_heap *heap, size_t __size);
+
+void *_fusion_shrealloc (shmalloc_heap *heap, void *__ptr, size_t __size);
+
+void _fusion_shfree (shmalloc_heap *heap, void *__ptr);
+
+
+DirectResult __shmalloc_init_heap( FusionSHM *shm,
+ const char *filename,
+ void *addr_base,
+ int space,
+ int *ret_fd,
+ int *ret_size );
+
+DirectResult __shmalloc_join_heap( FusionSHM *shm,
+ const char *filename,
+ void *addr_base,
+ int size,
+ int *ret_fd );
+
+void *__shmalloc_brk ( shmalloc_heap *heap,
+ int increment );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/shmalloc.c b/Source/DirectFB/lib/fusion/shmalloc.c
new file mode 100755
index 0000000..5fd3408
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shmalloc.c
@@ -0,0 +1,679 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <direct/build.h>
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <fusion/build.h>
+#include <fusion/shmalloc.h>
+
+#include <fusion/fusion_internal.h>
+#include <fusion/shm/shm_internal.h>
+
+
+#if FUSION_BUILD_MULTI
+
+/*************************** MULTI APPLICATION CORE ***************************/
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+D_DEBUG_DOMAIN( Fusion_SHM, "Fusion/SHM", "Fusion Shared Memory" );
+
+void
+fusion_dbg_print_memleaks( FusionSHMPoolShared *pool )
+{
+ DirectResult ret;
+ SHMemDesc *desc;
+ unsigned int total = 0;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not lock shared memory pool!\n" );
+ return;
+ }
+
+ if (pool->allocs) {
+ direct_log_printf( NULL, "\nShared memory allocations remaining (%d) in '%s': \n",
+ direct_list_count_elements_EXPENSIVE( pool->allocs ), pool->name );
+
+ direct_list_foreach (desc, pool->allocs) {
+ direct_log_printf( NULL, " %9zu bytes at %p [%8lu] in %-30s [%3lx] (%s: %u)\n",
+ desc->bytes, desc->mem, (ulong)desc->mem - (ulong)pool->heap,
+ desc->func, desc->fid, desc->file, desc->line );
+
+ total += desc->bytes;
+ }
+
+ direct_log_printf( NULL, " -------\n %7dk total\n", total >> 10 );
+ direct_log_printf( NULL, "\nShared memory file size: %dk\n", pool->heap->size >> 10 );
+ }
+
+ fusion_skirmish_dismiss( &pool->lock );
+}
+
+static SHMemDesc *
+fill_shmem_desc( SHMemDesc *desc, int bytes, const char *func, const char *file, int line, FusionID fusion_id )
+{
+ D_ASSERT( desc != NULL );
+
+ desc->mem = desc + 1;
+ desc->bytes = bytes;
+
+ snprintf( desc->func, SHMEMDESC_FUNC_NAME_LENGTH, func );
+ snprintf( desc->file, SHMEMDESC_FILE_NAME_LENGTH, file );
+
+ desc->line = line;
+ desc->fid = fusion_id;
+
+ return desc;
+}
+
+/* Allocate SIZE bytes of memory. */
+void *
+fusion_dbg_shmalloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, size_t __size )
+{
+ DirectResult ret;
+ SHMemDesc *desc;
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( file != NULL );
+ D_ASSERT( line > 0 );
+ D_ASSERT( func != NULL );
+ D_ASSERT( __size > 0 );
+
+ if (!pool->debug)
+ return fusion_shmalloc( pool, __size );
+
+ /* Lock the pool. */
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not lock shared memory pool!\n" );
+ return NULL;
+ }
+
+ /* Allocate memory from the pool. */
+ ret = fusion_shm_pool_allocate( pool, __size + sizeof(SHMemDesc), false, false, &data );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not allocate %zu bytes from pool!\n", __size + sizeof(SHMemDesc) );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Fill description. */
+ desc = fill_shmem_desc( data, __size, func, file, line, _fusion_id(pool->shm->world) );
+
+ D_DEBUG_AT( Fusion_SHM, "allocating %9zu bytes at %p [%8lu] in %-30s [%3lx] (%s: %u)\n",
+ desc->bytes, desc->mem, (ulong)desc->mem - (ulong)pool->heap,
+ desc->func, desc->fid, desc->file, desc->line );
+
+ /* Add description to list. */
+ direct_list_append( &pool->allocs, &desc->link );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return data + sizeof(SHMemDesc);
+}
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+void *
+fusion_dbg_shcalloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, size_t __nmemb, size_t __size)
+{
+ DirectResult ret;
+ SHMemDesc *desc;
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( file != NULL );
+ D_ASSERT( line > 0 );
+ D_ASSERT( func != NULL );
+ D_ASSERT( __nmemb > 0 );
+ D_ASSERT( __size > 0 );
+
+ if (!pool->debug)
+ return fusion_shcalloc( pool, __nmemb, __size );
+
+ /* Lock the pool. */
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not lock shared memory pool!\n" );
+ return NULL;
+ }
+
+ /* Allocate memory from the pool. */
+ ret = fusion_shm_pool_allocate( pool, __nmemb * __size + sizeof(SHMemDesc), true, false, &data );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not allocate %zu bytes from pool!\n", __nmemb * __size + sizeof(SHMemDesc) );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Fill description. */
+ desc = fill_shmem_desc( data, __nmemb * __size, func, file, line, _fusion_id(pool->shm->world) );
+
+ D_DEBUG_AT( Fusion_SHM, "allocating %9zu bytes at %p [%8lu] in %-30s [%3lx] (%s: %u)\n",
+ desc->bytes, desc->mem, (ulong)desc->mem - (ulong)pool->heap,
+ desc->func, desc->fid, desc->file, desc->line );
+
+ /* Add description to list. */
+ direct_list_append( &pool->allocs, &desc->link );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return data + sizeof(SHMemDesc);
+}
+
+/* Re-allocate the previously allocated block
+ in __ptr, making the new block SIZE bytes long. */
+void *
+fusion_dbg_shrealloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *what, void *__ptr,
+ size_t __size )
+{
+ DirectResult ret;
+ SHMemDesc *desc;
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( file != NULL );
+ D_ASSERT( line > 0 );
+ D_ASSERT( func != NULL );
+ D_ASSERT( what != NULL );
+
+ if (!pool->debug)
+ return fusion_shrealloc( pool, __ptr, __size );
+
+ if (!__ptr)
+ return fusion_dbg_shmalloc( pool, file, line, func, __size );
+
+ if (!__size) {
+ fusion_dbg_shfree( pool, file, line, func, what, __ptr );
+ return NULL;
+ }
+
+ /* Lock the pool. */
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not lock shared memory pool!\n" );
+ return NULL;
+ }
+
+ /* Lookup the corresponding description. */
+ direct_list_foreach (desc, pool->allocs) {
+ if (desc->mem == __ptr)
+ break;
+ }
+
+ if (!desc) {
+ D_ERROR( "Fusion/SHM: Cannot reallocate unknown chunk at %p (%s) from [%s:%d in %s()]!\n",
+ __ptr, what, file, line, func );
+ D_BREAK( "unknown chunk" );
+ return NULL; /* shouldn't happen due to the break */
+ }
+
+ /* Remove the description in case the block moves. */
+ direct_list_remove( &pool->allocs, &desc->link );
+
+ /* Reallocate the memory block. */
+ ret = fusion_shm_pool_reallocate( pool, __ptr - sizeof(SHMemDesc), __size + sizeof(SHMemDesc), false, &data );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not reallocate from %zu to %zu bytes!\n",
+ desc->bytes + sizeof(SHMemDesc), __size + sizeof(SHMemDesc) );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Fill description. */
+ desc = fill_shmem_desc( data, __size, func, file, line, _fusion_id(pool->shm->world) );
+
+ D_DEBUG_AT( Fusion_SHM, "reallocating %9zu bytes at %p [%8lu] in %-30s [%3lx] (%s: %u) '%s'\n",
+ desc->bytes, desc->mem, (ulong)desc->mem - (ulong)pool->heap,
+ desc->func, desc->fid, desc->file, desc->line, what );
+
+ /* Add description to list. */
+ direct_list_append( &pool->allocs, &desc->link );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ return data + sizeof(SHMemDesc);
+}
+
+/* Free a block allocated by `shmalloc', `shrealloc' or `shcalloc'. */
+void
+fusion_dbg_shfree( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *what, void *__ptr )
+{
+ DirectResult ret;
+ SHMemDesc *desc;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( file != NULL );
+ D_ASSERT( line > 0 );
+ D_ASSERT( func != NULL );
+ D_ASSERT( what != NULL );
+ D_ASSERT( __ptr != NULL );
+
+ if (!pool->debug)
+ return fusion_shfree( pool, __ptr );
+
+ /* Lock the pool. */
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not lock shared memory pool!\n" );
+ return;
+ }
+
+ /* Lookup the corresponding description. */
+ direct_list_foreach (desc, pool->allocs) {
+ if (desc->mem == __ptr)
+ break;
+ }
+
+ if (!desc) {
+ D_ERROR( "Fusion/SHM: Cannot free unknown chunk at %p (%s) from [%s:%d in %s()]!\n",
+ __ptr, what, file, line, func );
+ D_BREAK( "unknown chunk" );
+ return; /* shouldn't happen due to the break */
+ }
+
+ D_DEBUG_AT( Fusion_SHM, "freeing %9zu bytes at %p [%8lu] in %-30s [%3lx] (%s: %u) '%s'\n",
+ desc->bytes, desc->mem, (ulong)desc->mem - (ulong)pool->heap,
+ desc->func, desc->fid, desc->file, desc->line, what );
+
+ /* Remove the description. */
+ direct_list_remove( &pool->allocs, &desc->link );
+
+ /* Free the memory block. */
+ fusion_shm_pool_deallocate( pool, __ptr - sizeof(SHMemDesc), false );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+}
+
+/* Duplicate string in shared memory. */
+char *
+fusion_dbg_shstrdup( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *string )
+{
+ DirectResult ret;
+ SHMemDesc *desc;
+ void *data = NULL;
+ int length;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( file != NULL );
+ D_ASSERT( line > 0 );
+ D_ASSERT( func != NULL );
+ D_ASSERT( string != NULL );
+
+ if (!pool->debug)
+ return fusion_shstrdup( pool, string );
+
+ length = strlen( string ) + 1;
+
+ /* Lock the pool. */
+ ret = fusion_skirmish_prevail( &pool->lock );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not lock shared memory pool!\n" );
+ return NULL;
+ }
+
+ /* Allocate memory from the pool. */
+ ret = fusion_shm_pool_allocate( pool, length + sizeof(SHMemDesc), false, false, &data );
+ if (ret) {
+ D_DERROR( ret, "Fusion/SHM: Could not allocate %zu bytes from pool!\n", length + sizeof(SHMemDesc) );
+ fusion_skirmish_dismiss( &pool->lock );
+ return NULL;
+ }
+
+ /* Fill description. */
+ desc = fill_shmem_desc( data, length, func, file, line, _fusion_id(pool->shm->world) );
+
+ D_DEBUG_AT( Fusion_SHM, "allocating %9zu bytes at %p [%8lu] in %-30s [%3lx] (%s: %u) <- \"%s\"\n",
+ desc->bytes, desc->mem, (ulong)desc->mem - (ulong)pool->heap,
+ desc->func, desc->fid, desc->file, desc->line, string );
+
+ D_DEBUG_AT( Fusion_SHM, " -> allocs: %p\n", pool->allocs );
+
+ /* Add description to list. */
+ direct_list_append( &pool->allocs, &desc->link );
+
+ /* Unlock the pool. */
+ fusion_skirmish_dismiss( &pool->lock );
+
+ /* Copy string content. */
+ direct_memcpy( data + sizeof(SHMemDesc), string, length );
+
+ return data + sizeof(SHMemDesc);
+}
+
+#else
+
+void
+fusion_dbg_print_memleaks( FusionSHMPoolShared *pool )
+{
+}
+
+#endif
+
+/**********************************************************************************************************************/
+
+/* Allocate SIZE bytes of memory. */
+void *
+fusion_shmalloc( FusionSHMPoolShared *pool, size_t __size )
+{
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __size > 0 );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ if (fusion_shm_pool_allocate( pool, __size, false, true, &data ))
+ return NULL;
+
+ D_ASSERT( data != NULL );
+
+ return data;
+}
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+void *
+fusion_shcalloc( FusionSHMPoolShared *pool, size_t __nmemb, size_t __size )
+{
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __nmemb > 0 );
+ D_ASSERT( __size > 0 );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ if (fusion_shm_pool_allocate( pool, __nmemb * __size, true, true, &data ))
+ return NULL;
+
+ D_ASSERT( data != NULL );
+
+ return data;
+}
+
+/* Re-allocate the previously allocated block
+ in __ptr, making the new block SIZE bytes long. */
+void *
+fusion_shrealloc( FusionSHMPoolShared *pool, void *__ptr, size_t __size )
+{
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ if (!__ptr)
+ return fusion_shmalloc( pool, __size );
+
+ if (!__size) {
+ fusion_shfree( pool, __ptr );
+ return NULL;
+ }
+
+ if (fusion_shm_pool_reallocate( pool, __ptr, __size, true, &data ))
+ return NULL;
+
+ D_ASSERT( data != NULL || __size == 0 );
+
+ return data;
+}
+
+/* Free a block allocated by `shmalloc', `shrealloc' or `shcalloc'. */
+void
+fusion_shfree( FusionSHMPoolShared *pool, void *__ptr )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __ptr != NULL );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ fusion_shm_pool_deallocate( pool, __ptr, true );
+}
+
+/* Duplicate string in shared memory. */
+char *
+fusion_shstrdup( FusionSHMPoolShared *pool, const char* string )
+{
+ int len;
+ void *data = NULL;
+
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( string != NULL );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ len = strlen( string ) + 1;
+
+ if (fusion_shm_pool_allocate( pool, len, false, true, &data ))
+ return NULL;
+
+ D_ASSERT( data != NULL );
+
+ direct_memcpy( data, string, len );
+
+ return data;
+}
+
+#else
+
+/************************** SINGLE APPLICATION CORE ***************************/
+
+#include <direct/mem.h>
+
+void
+fusion_dbg_print_memleaks( FusionSHMPoolShared *pool )
+{
+}
+
+#if DIRECT_BUILD_DEBUGS /* Build with debug support? */
+
+/* Allocate SIZE bytes of memory. */
+void *
+fusion_dbg_shmalloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, size_t __size )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __size > 0 );
+
+ if (pool->debug)
+ return direct_malloc( file, line, func, __size );
+
+ return malloc( __size );
+}
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+void *
+fusion_dbg_shcalloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, size_t __nmemb, size_t __size)
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __nmemb > 0 );
+ D_ASSERT( __size > 0 );
+
+ if (pool->debug)
+ return direct_calloc( file, line, func, __nmemb, __size );
+
+ return calloc( __nmemb, __size );
+}
+
+/* Re-allocate the previously allocated block
+ in __ptr, making the new block SIZE bytes long. */
+void *
+fusion_dbg_shrealloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *what, void *__ptr,
+ size_t __size )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ if (pool->debug)
+ return direct_realloc( file, line, func, what, __ptr, __size );
+
+ return realloc( __ptr, __size );
+}
+
+/* Free a block allocated by `shmalloc', `shrealloc' or `shcalloc'. */
+void
+fusion_dbg_shfree( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *what, void *__ptr )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __ptr != NULL );
+
+ if (pool->debug)
+ direct_free( file, line, func, what, __ptr );
+ else
+ free( __ptr );
+}
+
+/* Duplicate string in shared memory. */
+char *
+fusion_dbg_shstrdup( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *string )
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( string != NULL );
+
+ if (pool->debug)
+ return direct_strdup( file, line, func, string );
+
+ return strdup( string );
+}
+
+#endif
+
+/**********************************************************************************************************************/
+
+/* Allocate SIZE bytes of memory. */
+void *
+fusion_shmalloc (FusionSHMPoolShared *pool,
+ size_t __size)
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __size > 0 );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ return malloc( __size );
+}
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+void *
+fusion_shcalloc (FusionSHMPoolShared *pool,
+ size_t __nmemb, size_t __size)
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __nmemb > 0 );
+ D_ASSERT( __size > 0 );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ return calloc( __nmemb, __size );
+}
+
+/* Re-allocate the previously allocated block
+ in __ptr, making the new block SIZE bytes long. */
+void *
+fusion_shrealloc (FusionSHMPoolShared *pool,
+ void *__ptr, size_t __size)
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ return realloc( __ptr, __size );
+}
+
+/* Free a block allocated by `shmalloc', `shrealloc' or `shcalloc'. */
+void
+fusion_shfree (FusionSHMPoolShared *pool,
+ void *__ptr)
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( __ptr != NULL );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ free( __ptr );
+}
+
+/* Duplicate string in shared memory. */
+char *
+fusion_shstrdup (FusionSHMPoolShared *pool,
+ const char *string)
+{
+ D_MAGIC_ASSERT( pool, FusionSHMPoolShared );
+ D_ASSERT( string != NULL );
+
+ if (pool->debug)
+ D_WARN( "Fusion/SHMMalloc: Pool runs in debug mode, but access from pure-release is attempted!\n" );
+
+ return strdup( string );
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/shmalloc.h b/Source/DirectFB/lib/fusion/shmalloc.h
new file mode 100755
index 0000000..4b8c8d3
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/shmalloc.h
@@ -0,0 +1,124 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ Fusion shmalloc is based on GNU malloc. Please see below.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__SHMALLOC_H__
+#define __FUSION__SHMALLOC_H__
+
+#include <stddef.h>
+
+#include <direct/build.h>
+#include <fusion/build.h>
+
+#include <fusion/types.h>
+#include <fusion/shm/pool.h>
+
+
+#if FUSION_BUILD_MULTI && DIRECT_BUILD_TEXT
+#define D_OOSHM() (direct_messages_warn( __FUNCTION__, __FILE__, __LINE__, \
+ "out of shared memory" ), DR_NOSHAREDMEMORY)
+#else
+#define D_OOSHM() D_OOM()
+#endif
+
+
+
+void fusion_dbg_print_memleaks( FusionSHMPoolShared *pool );
+
+
+void *fusion_dbg_shmalloc ( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, size_t __size );
+
+void *fusion_dbg_shcalloc ( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, size_t __nmemb, size_t __size);
+
+void *fusion_dbg_shrealloc( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *what, void *__ptr,
+ size_t __size );
+
+void fusion_dbg_shfree ( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *what, void *__ptr );
+
+char *fusion_dbg_shstrdup ( FusionSHMPoolShared *pool,
+ const char *file, int line,
+ const char *func, const char *string );
+
+
+/* Allocate SIZE bytes of memory. */
+void *fusion_shmalloc (FusionSHMPoolShared *pool, size_t __size);
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+void *fusion_shcalloc (FusionSHMPoolShared *pool, size_t __nmemb, size_t __size);
+
+/* Re-allocate the previously allocated block
+ in __ptr, making the new block SIZE bytes long. */
+void *fusion_shrealloc (FusionSHMPoolShared *pool, void *__ptr, size_t __size);
+
+/* Free a block allocated by `shmalloc', `shrealloc' or `shcalloc'. */
+void fusion_shfree (FusionSHMPoolShared *pool, void *__ptr);
+
+/* Duplicate string in shared memory. */
+char *fusion_shstrdup (FusionSHMPoolShared *pool, const char *string);
+
+
+
+#if DIRECT_BUILD_DEBUGS || DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) || defined(DIRECT_FORCE_DEBUG)
+
+#if !DIRECT_BUILD_DEBUGS
+#warning Building with debug, but library headers suggest that debug is not supported.
+#endif
+
+
+#define SHMALLOC(pool,bytes) fusion_dbg_shmalloc( pool, __FILE__, __LINE__, __FUNCTION__, bytes )
+#define SHCALLOC(pool,count,bytes) fusion_dbg_shcalloc( pool, __FILE__, __LINE__, __FUNCTION__, count, bytes )
+#define SHREALLOC(pool,mem,bytes) fusion_dbg_shrealloc( pool, __FILE__, __LINE__, __FUNCTION__, #mem, mem, bytes )
+#define SHFREE(pool,mem) fusion_dbg_shfree( pool, __FILE__, __LINE__, __FUNCTION__, #mem,mem )
+#define SHSTRDUP(pool,string) fusion_dbg_shstrdup( pool, __FILE__, __LINE__, __FUNCTION__, string )
+
+
+#else
+
+
+#define SHMALLOC fusion_shmalloc
+#define SHCALLOC fusion_shcalloc
+#define SHREALLOC fusion_shrealloc
+#define SHFREE fusion_shfree
+#define SHSTRDUP fusion_shstrdup
+
+
+#endif
+
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/types.h b/Source/DirectFB/lib/fusion/types.h
new file mode 100755
index 0000000..bb5967f
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/types.h
@@ -0,0 +1,87 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__TYPES_H__
+#define __FUSION__TYPES_H__
+
+#include <fusion/build.h>
+
+#if FUSION_BUILD_MULTI && FUSION_BUILD_KERNEL
+
+#include <linux/fusion.h>
+
+#define FUSION_API_MAJOR_REQUIRED 8
+#define FUSION_API_MINOR_REQUIRED 0
+
+#if FUSION_API_MAJOR_REQUIRED > FUSION_API_MAJOR_PROVIDED
+#error Major version of Fusion Kernel Module too low! Upgrade your kernel.
+#else
+#if FUSION_API_MAJOR_REQUIRED == FUSION_API_MAJOR_PROVIDED
+#if FUSION_API_MINOR_REQUIRED > FUSION_API_MINOR_PROVIDED
+#error Minor version of Fusion Kernel Module too low! Upgrade your kernel.
+#endif
+#endif
+#endif
+
+#else
+typedef unsigned long FusionID;
+
+#define FUSION_ID_MASTER 1L
+
+typedef enum {
+ FCEF_NONE = 0x00000000,
+ FCEF_ONEWAY = 0x00000001,
+ FCEF_ALL = 0x00000001
+} FusionCallExecFlags;
+
+#endif
+
+#define FCEF_NODIRECT 0x80000000
+
+#include <direct/types.h>
+
+
+typedef struct __Fusion_FusionConfig FusionConfig;
+
+typedef struct __Fusion_FusionArena FusionArena;
+typedef struct __Fusion_FusionReactor FusionReactor;
+typedef struct __Fusion_FusionWorld FusionWorld;
+typedef struct __Fusion_FusionWorldShared FusionWorldShared;
+
+typedef struct __Fusion_FusionObject FusionObject;
+typedef struct __Fusion_FusionObjectPool FusionObjectPool;
+
+typedef struct __Fusion_FusionSHM FusionSHM;
+typedef struct __Fusion_FusionSHMShared FusionSHMShared;
+
+typedef struct __Fusion_FusionSHMPool FusionSHMPool;
+typedef struct __Fusion_FusionSHMPoolShared FusionSHMPoolShared;
+typedef struct __Fusion_FusionHash FusionHash;
+
+#endif
+
diff --git a/Source/DirectFB/lib/fusion/vector.c b/Source/DirectFB/lib/fusion/vector.c
new file mode 100755
index 0000000..aa8a4a0
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/vector.c
@@ -0,0 +1,230 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+
+#include <fusion/object.h>
+#include <fusion/shmalloc.h>
+#include <fusion/vector.h>
+
+
+static inline bool ensure_capacity( FusionVector *vector )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( vector->capacity > 0 );
+
+ if (!vector->elements) {
+ if (vector->pool)
+ vector->elements = SHMALLOC( vector->pool, vector->capacity * sizeof(void*) );
+ else
+ vector->elements = D_MALLOC( vector->capacity * sizeof(void*) );
+
+ if (!vector->elements)
+ return false;
+ }
+ else if (vector->count == vector->capacity) {
+ void *elements;
+ void *oldelements = vector->elements;
+ int capacity = vector->capacity << 1;
+
+ if (vector->pool)
+ elements = SHMALLOC( vector->pool, capacity * sizeof(void*) );
+ else
+ elements = D_MALLOC( capacity * sizeof(void*) );
+
+ if (!elements)
+ return false;
+
+ direct_memcpy( elements, vector->elements,
+ vector->count * sizeof(void*) );
+
+ vector->elements = elements;
+ vector->capacity = capacity;
+
+ if (vector->pool)
+ SHFREE( vector->pool, oldelements );
+ else
+ D_FREE( oldelements );
+ }
+
+ return true;
+}
+
+void
+fusion_vector_init( FusionVector *vector,
+ int capacity,
+ FusionSHMPoolShared *pool )
+{
+ D_ASSERT( vector != NULL );
+ D_ASSERT( capacity > 0 );
+
+ vector->elements = NULL;
+ vector->count = 0;
+ vector->capacity = capacity;
+ vector->pool = pool;
+
+ D_MAGIC_SET( vector, FusionVector );
+}
+
+void
+fusion_vector_destroy( FusionVector *vector )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( vector->count == 0 || vector->elements != NULL );
+
+ if (vector->elements) {
+ if (vector->pool)
+ SHFREE( vector->pool, vector->elements );
+ else
+ D_FREE( vector->elements );
+
+ vector->elements = NULL;
+ }
+
+ D_MAGIC_CLEAR( vector );
+}
+
+DirectResult
+fusion_vector_add( FusionVector *vector,
+ void *element )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( element != NULL );
+
+ /* Make sure there's a free entry left. */
+ if (!ensure_capacity( vector ))
+ return D_OOSHM();
+
+ /* Add the element to the vector. */
+ vector->elements[vector->count++] = element;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_vector_insert( FusionVector *vector,
+ void *element,
+ int index )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( element != NULL );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index <= vector->count );
+
+ /* Make sure there's a free entry left. */
+ if (!ensure_capacity( vector ))
+ return D_OOSHM();
+
+ /* Move elements from insertion point one up. */
+ memmove( &vector->elements[ index + 1 ],
+ &vector->elements[ index ],
+ (vector->count - index) * sizeof(void*) );
+
+ /* Insert the element into the vector. */
+ vector->elements[index] = element;
+
+ /* Increase the element counter. */
+ vector->count++;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_vector_move( FusionVector *vector,
+ int from,
+ int to )
+{
+ void *element;
+
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( from >= 0 );
+ D_ASSERT( from < vector->count );
+ D_ASSERT( to >= 0 );
+ D_ASSERT( to < vector->count );
+
+ if (to == from)
+ return DR_OK;
+
+ /* Save the element. */
+ element = vector->elements[from];
+
+ /* Move elements that lie on the way to the new position. */
+ if (to > from) {
+ /* Element is moving up -> move other elements down. */
+ memmove( &vector->elements[ from ],
+ &vector->elements[ from + 1 ],
+ (to - from) * sizeof(void*) );
+ }
+ else {
+ /* Element is moving down -> move other elements up. */
+ memmove( &vector->elements[ to + 1 ],
+ &vector->elements[ to ],
+ (from - to) * sizeof(void*) );
+ }
+
+ /* Restore the element at the new position. */
+ vector->elements[to] = element;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_vector_remove( FusionVector *vector,
+ int index )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < vector->count );
+
+ /* Move elements after this element one down. */
+ memmove( &vector->elements[ index ],
+ &vector->elements[ index + 1 ],
+ (vector->count - index - 1) * sizeof(void*) );
+
+ /* Decrease the element counter. */
+ vector->count--;
+
+ return DR_OK;
+}
+
+DirectResult
+fusion_vector_remove_last( FusionVector *vector )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( vector->count > 0 );
+
+ /* Decrease the element counter. */
+ vector->count--;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/fusion/vector.h b/Source/DirectFB/lib/fusion/vector.h
new file mode 100755
index 0000000..e978ce9
--- /dev/null
+++ b/Source/DirectFB/lib/fusion/vector.h
@@ -0,0 +1,164 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __FUSION__VECTOR_H__
+#define __FUSION__VECTOR_H__
+
+#include <limits.h>
+
+#include <fusion/types.h>
+
+#include <direct/debug.h>
+
+typedef struct {
+ int magic;
+
+ void **elements;
+ int count;
+
+ int capacity;
+
+ FusionSHMPoolShared *pool;
+} FusionVector;
+
+void fusion_vector_init ( FusionVector *vector,
+ int capacity,
+ FusionSHMPoolShared *pool );
+
+void fusion_vector_destroy ( FusionVector *vector );
+
+DirectResult fusion_vector_add ( FusionVector *vector,
+ void *element );
+
+DirectResult fusion_vector_insert ( FusionVector *vector,
+ void *element,
+ int index );
+
+DirectResult fusion_vector_move ( FusionVector *vector,
+ int from,
+ int to );
+
+DirectResult fusion_vector_remove ( FusionVector *vector,
+ int index );
+
+DirectResult fusion_vector_remove_last( FusionVector *vector );
+
+
+static inline bool
+fusion_vector_has_elements( const FusionVector *vector )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+
+ return vector->count > 0;
+}
+
+static inline bool
+fusion_vector_is_empty( const FusionVector *vector )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+
+ return vector->count == 0;
+}
+
+static inline int
+fusion_vector_size( const FusionVector *vector )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+
+ return vector->count;
+}
+
+static inline void *
+fusion_vector_at( const FusionVector *vector, int index )
+{
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < vector->count );
+
+ return vector->elements[index];
+}
+
+static inline bool
+fusion_vector_contains( const FusionVector *vector, const void *element )
+{
+ int i;
+ int count;
+ void * const *elements;
+
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( element != NULL );
+
+ count = vector->count;
+ elements = vector->elements;
+
+ /* Start with more recently added elements. */
+ for (i=count-1; i>=0; i--)
+ if (elements[i] == element)
+ return true;
+
+ return false;
+}
+
+static inline int
+fusion_vector_index_of( const FusionVector *vector, const void *element )
+{
+ int i;
+ int count;
+ void * const *elements;
+
+ D_MAGIC_ASSERT( vector, FusionVector );
+ D_ASSERT( element != NULL );
+
+ count = vector->count;
+ elements = vector->elements;
+
+ /* Start with more recently added elements. */
+ for (i=count-1; i>=0; i--)
+ if (elements[i] == element)
+ return i;
+
+ /*
+ * In case the return value isn't checked
+ * this will most likely generate a bad address.
+ */
+ return INT_MIN >> 2;
+}
+
+
+#define fusion_vector_foreach(element, index, vector) \
+ for ((index) = 0; \
+ (index) < (vector).count && (element = (vector).elements[index]); \
+ (index)++)
+
+#define fusion_vector_foreach_reverse(element, index, vector) \
+ for ((index) = (vector).count - 1; \
+ (index) >= 0 && (element = (vector).elements[index]); \
+ (index)--)
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/Makefile.am b/Source/DirectFB/lib/voodoo/Makefile.am
new file mode 100755
index 0000000..bf3c143
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/Makefile.am
@@ -0,0 +1,82 @@
+## Makefile.am for DirectFB/lib/voodoo
+
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\"
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = voodoo.pc
+
+
+# If the old location isn't cleared, builds of external modules fail
+install-exec-local:
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/voodoo
+
+
+includedir = @INCLUDEDIR@/voodoo
+
+include_HEADERS = \
+ build.h \
+ client.h \
+ conf.h \
+ interface.h \
+ manager.h \
+ message.h \
+ server.h \
+ play.h \
+ types.h
+
+
+lib_LTLIBRARIES = libvoodoo.la
+
+libvoodoo_la_SOURCES = \
+ client.c \
+ conf.c \
+ interface.c \
+ internal.h \
+ manager.c \
+ play.c \
+ server.c
+
+libvoodoo_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ $(DFB_LDFLAGS)
+
+libvoodoo_la_LIBADD = ../direct/libdirect.la
+
+
+#
+## and now rebuild the static version with the *correct* object files
+#
+if BUILD_STATIC
+
+clean-local:
+ rm -f libvoodoo_fixed.a
+
+all-local: libvoodoo_fixed.a
+
+libvoodoo_fixed.a: .libs/libvoodoo.a
+ rm -f libvoodoo_fixed.a
+ ${AR} cru libvoodoo_fixed.a `find . -name "*.o"`
+ ${RANLIB} libvoodoo_fixed.a
+ cp -pf libvoodoo_fixed.a .libs/libvoodoo.a
+
+.libs/libvoodoo.a: libvoodoo.la
+
+else
+
+clean-local:
+
+all-local:
+
+endif
+
+
+include $(top_srcdir)/rules/nmfile.make
diff --git a/Source/DirectFB/lib/voodoo/Makefile.in b/Source/DirectFB/lib/voodoo/Makefile.in
new file mode 100755
index 0000000..4a4a5a2
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/Makefile.in
@@ -0,0 +1,666 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/build.h.in \
+ $(srcdir)/voodoo.pc.in $(top_srcdir)/rules/nmfile.make
+subdir = lib/voodoo
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = build.h voodoo.pc
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(includedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libvoodoo_la_DEPENDENCIES = ../direct/libdirect.la
+am_libvoodoo_la_OBJECTS = client.lo conf.lo interface.lo play.lo manager.lo \
+ server.lo
+libvoodoo_la_OBJECTS = $(am_libvoodoo_la_OBJECTS)
+libvoodoo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libvoodoo_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libvoodoo_la_SOURCES)
+DIST_SOURCES = $(libvoodoo_la_SOURCES)
+pkgconfigDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(pkgconfig_DATA)
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @INCLUDEDIR@/voodoo
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\"
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = voodoo.pc
+include_HEADERS = \
+ build.h \
+ client.h \
+ conf.h \
+ interface.h \
+ manager.h \
+ message.h \
+ server.h \
+ play.h \
+ types.h
+
+lib_LTLIBRARIES = libvoodoo.la
+libvoodoo_la_SOURCES = \
+ client.c \
+ conf.c \
+ interface.c \
+ internal.h \
+ manager.c \
+ play.c \
+ server.c
+
+libvoodoo_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ $(DFB_LDFLAGS)
+
+libvoodoo_la_LIBADD = ../direct/libdirect.la
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@LIBTONM = $(LTLIBRARIES:.la=-$(LT_RELEASE).so.$(LT_BINARY))
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/nmfile.make $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/voodoo/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lib/voodoo/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+build.h: $(top_builddir)/config.status $(srcdir)/build.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+voodoo.pc: $(top_builddir)/config.status $(srcdir)/voodoo.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libvoodoo.la: $(libvoodoo_la_OBJECTS) $(libvoodoo_la_DEPENDENCIES)
+ $(libvoodoo_la_LINK) -rpath $(libdir) $(libvoodoo_la_OBJECTS) $(libvoodoo_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/play.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) all-local
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@BUILD_SHARED_FALSE@install-data-local:
+@ENABLE_TRACE_FALSE@install-data-local:
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-includeHEADERS \
+ install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-exec-local install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-pkgconfigDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am all-local check check-am clean \
+ clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-data-local install-dvi install-dvi-am \
+ install-exec install-exec-am install-exec-local install-html \
+ install-html-am install-includeHEADERS install-info \
+ install-info-am install-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-pkgconfigDATA
+
+
+# If the old location isn't cleared, builds of external modules fail
+install-exec-local:
+ rm -rf $(DESTDIR)$(INTERNALINCLUDEDIR)/voodoo
+
+#
+#
+
+@BUILD_STATIC_TRUE@clean-local:
+@BUILD_STATIC_TRUE@ rm -f libvoodoo_fixed.a
+
+@BUILD_STATIC_TRUE@all-local: libvoodoo_fixed.a
+
+@BUILD_STATIC_TRUE@libvoodoo_fixed.a: .libs/libvoodoo.a
+@BUILD_STATIC_TRUE@ rm -f libvoodoo_fixed.a
+@BUILD_STATIC_TRUE@ ${AR} cru libvoodoo_fixed.a `find . -name "*.o"`
+@BUILD_STATIC_TRUE@ ${RANLIB} libvoodoo_fixed.a
+@BUILD_STATIC_TRUE@ cp -pf libvoodoo_fixed.a .libs/libvoodoo.a
+
+@BUILD_STATIC_TRUE@.libs/libvoodoo.a: libvoodoo.la
+
+@BUILD_STATIC_FALSE@clean-local:
+
+@BUILD_STATIC_FALSE@all-local:
+
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@install-data-local:
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ mkdir -p -- "$(DESTDIR)$(libdir)"
+@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ nm -n ".libs/$(LIBTONM)" > "$(DESTDIR)$(libdir)/nm-n.$(LIBTONM)"
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/lib/voodoo/app.h b/Source/DirectFB/lib/voodoo/app.h
new file mode 100755
index 0000000..163edc6
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/app.h
@@ -0,0 +1,66 @@
+/*
+ (c) Copyright 2001-2010 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__APP_H__
+#define __VOODOO__APP_H__
+
+#include <voodoo/types.h>
+
+
+
+typedef enum {
+ VADESC_NONE = 0x00000000,
+
+ VADESC_NAME = 0x00000001,
+ VADESC_TEXT = 0x00000002,
+
+ VADESC_ALL = 0x00000003,
+} VoodooAppDescriptionFlags;
+
+
+#define VOODOO_APP_DESCRIPTION_NAME_LENGTH 128
+#define VOODOO_APP_DESCRIPTION_TEXT_LENGTH 1024
+
+typedef struct {
+ u8 uuid[16];
+ VoodooAppDescriptionFlags flags;
+
+ char name[VOODOO_APP_DESCRIPTION_NAME_LENGTH];
+ char text[VOODOO_APP_DESCRIPTION_TEXT_LENGTH];
+} VoodooAppDescription;
+
+typedef struct {
+ u8 uuid[16];
+
+ VoodooAppDescription app;
+ u8 player_uuid[16];
+} VoodooAppInstanceDescription;
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/build.h.in b/Source/DirectFB/lib/voodoo/build.h.in
new file mode 100755
index 0000000..c5553e2
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/build.h.in
@@ -0,0 +1,34 @@
+/*
+ (c) Copyright 2000-2002 convergence integrated media GmbH.
+ (c) Copyright 2002-2004 convergence GmbH.
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org> and
+ Ville Syrjälä <syrjala@sci.fi>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__BUILD_H__
+#define __VOODOO__BUILD_H__
+
+/* nothing yet */
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/client.c b/Source/DirectFB/lib/voodoo/client.c
new file mode 100755
index 0000000..66844e2
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/client.c
@@ -0,0 +1,208 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/client.h>
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+#include <voodoo/manager.h>
+#include <voodoo/play.h>
+
+/**********************************************************************************************************************/
+
+struct __V_VoodooClient {
+ DirectLink link;
+
+ int refs;
+
+ VoodooLink vl;
+ VoodooManager *manager;
+
+ char *host;
+ int port;
+};
+
+static DirectLink *m_clients; // FIXME: add lock
+
+/**********************************************************************************************************************/
+
+DirectResult
+voodoo_client_create( const char *host,
+ int port,
+ VoodooClient **ret_client )
+{
+ DirectResult ret;
+ VoodooClient *client;
+ VoodooPlayer *player;
+ int bc_num = 10;
+ int bc_wait = 4000;
+ char buf[100] = { 0 };
+ const char *hostname = host;
+ bool raw = true;
+
+ D_ASSERT( ret_client != NULL );
+
+ if (!port)
+ port = 2323;
+
+ direct_list_foreach (client, m_clients) {
+ if (!strcmp( client->host, host ) && client->port == port) {
+ D_INFO( "Voodoo/Client: Reconnecting to '%s', increasing ref count of existing connection!\n", host );
+
+ client->refs++;
+
+ *ret_client = client;
+
+ return DR_OK;
+ }
+ }
+
+
+ ret = voodoo_player_create( NULL, &player );
+ if (ret) {
+ D_DERROR( ret, "Voodoo/Client: Could not create the player!\n" );
+ return ret;
+ }
+
+ while (bc_num--) {
+ VoodooPlayInfo info;
+
+ // FIXME: resolve first, not late in voodoo_link_init_connect
+ if (hostname && hostname[0]) {
+ ret = voodoo_player_lookup_by_address( player, hostname, &info );
+ if (ret == DR_OK) {
+ if (info.flags & VPIF_LINK)
+ raw = false;
+
+ break;
+ }
+ }
+ else {
+ ret = voodoo_player_lookup( player, NULL, &info, buf, sizeof(buf) );
+ if (ret == DR_OK) {
+ if (info.flags & VPIF_LINK)
+ raw = false;
+
+ hostname = buf;
+
+ break;
+ }
+ }
+
+ voodoo_player_broadcast( player );
+
+ direct_thread_sleep( bc_wait );
+
+ bc_wait += bc_wait;
+ }
+
+ voodoo_player_destroy( player );
+
+ if (!hostname || !hostname[0]) {
+ D_ERROR( "Voodoo/Play: Did not find any other player!\n" );
+ return DR_ITEMNOTFOUND;
+ }
+
+
+ /* Allocate client structure. */
+ client = D_CALLOC( 1, sizeof(VoodooClient) );
+ if (!client)
+ return D_OOM();
+
+
+ /* Initialize client structure. */
+ ret = voodoo_link_init_connect( &client->vl, hostname, port,
+ !voodoo_config->link_packet && (voodoo_config->link_raw || raw) );
+ if (ret) {
+ D_DERROR( ret, "Voodoo/Client: Failed to initialize Voodoo Link!\n" );
+ D_FREE( client );
+ return ret;
+ }
+
+ /* Create the manager. */
+ ret = voodoo_manager_create( &client->vl, client, NULL, &client->manager );
+ if (ret) {
+ client->vl.Close( &client->vl );
+ D_FREE( client );
+ return ret;
+ }
+
+ client->refs = 1;
+ client->host = D_STRDUP( host );
+ client->port = port;
+
+ direct_list_prepend( &m_clients, &client->link );
+
+ /* Return the new client. */
+ *ret_client = client;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_client_destroy( VoodooClient *client )
+{
+ D_ASSERT( client != NULL );
+
+ D_INFO( "Voodoo/Client: Decreasing ref count of connection...\n" );
+
+ if (! --(client->refs)) {
+ voodoo_manager_destroy( client->manager );
+
+ //client->vl.Close( &client->vl );
+
+ direct_list_remove( &m_clients, &client->link );
+
+ D_FREE( client->host );
+ D_FREE( client );
+ }
+
+ return DR_OK;
+}
+
+VoodooManager *
+voodoo_client_manager( const VoodooClient *client )
+{
+ D_ASSERT( client != NULL );
+
+ return client->manager;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/client.h b/Source/DirectFB/lib/voodoo/client.h
new file mode 100755
index 0000000..5905ef8
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/client.h
@@ -0,0 +1,44 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CLIENT_H__
+#define __VOODOO__CLIENT_H__
+
+#include <voodoo/types.h>
+
+
+DirectResult voodoo_client_create ( const char *host,
+ int session,
+ VoodooClient **ret_client );
+
+DirectResult voodoo_client_destroy( VoodooClient *client );
+
+
+VoodooManager *voodoo_client_manager( const VoodooClient *client );
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/compat.h b/Source/DirectFB/lib/voodoo/compat.h
new file mode 100755
index 0000000..e7b5a75
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/compat.h
@@ -0,0 +1,8 @@
+#include "mutex.h"
+#include "waitqueue.h"
+
+#define direct_thread_sleep usleep
+#define direct_snprintf snprintf
+#define direct_sscanf sscanf
+#define direct_getpid getpid
+
diff --git a/Source/DirectFB/lib/voodoo/conf.c b/Source/DirectFB/lib/voodoo/conf.c
new file mode 100755
index 0000000..456643d
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/conf.c
@@ -0,0 +1,253 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <string.h>
+
+#include <direct/conf.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+
+
+static VoodooConfig config = {
+ .compression_min = 1
+};
+
+VoodooConfig *voodoo_config = &config;
+const char *voodoo_config_usage =
+ "libvoodoo options:\n"
+ " player-name=<name> Set player name\n"
+ " player-vendor=<name> Set player vendor\n"
+ " player-model=<name> Set player model\n"
+ " player-uuid=<name> Set player uuid\n"
+ " proxy-memory-max=<kB> Set maximum amount of memory per connection\n"
+ " proxy-surface-max=<kB> Set maximum amount of memory per surface\n"
+ " [no-]server-fork Fork a new process for each connection (default: no)\n"
+ " server-single=<interface> Enable single client mode for super interface, e.g. IDirectFB\n"
+ " compression-min=<bytes> Enable compression (if != 0) for packets with at least num bytes\n"
+ " [no-]link-raw Set link mode to 'raw'\n"
+ " [no-]link-packet Set link mode to 'packet'\n"
+ "\n";
+
+/**********************************************************************************************************************/
+
+DirectResult
+voodoo_config_set( const char *name, const char *value )
+{
+ if (strcmp (name, "player-name" ) == 0) {
+ if (value) {
+ direct_snputs( voodoo_config->play_info.name, value, VOODOO_PLAYER_NAME_LENGTH );
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "player-vendor" ) == 0) {
+ if (value) {
+ direct_snputs( voodoo_config->play_info.vendor, value, VOODOO_PLAYER_VENDOR_LENGTH );
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "player-model" ) == 0) {
+ if (value) {
+ direct_snputs( voodoo_config->play_info.model, value, VOODOO_PLAYER_MODEL_LENGTH );
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "player-uuid" ) == 0) {
+ if (value) {
+ sscanf( value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ (unsigned int*)&voodoo_config->play_info.uuid[0], (unsigned int*)&voodoo_config->play_info.uuid[1], (unsigned int*)&voodoo_config->play_info.uuid[2], (unsigned int*)&voodoo_config->play_info.uuid[3], (unsigned int*)&voodoo_config->play_info.uuid[4],
+ (unsigned int*)&voodoo_config->play_info.uuid[5], (unsigned int*)&voodoo_config->play_info.uuid[6], (unsigned int*)&voodoo_config->play_info.uuid[7], (unsigned int*)&voodoo_config->play_info.uuid[8], (unsigned int*)&voodoo_config->play_info.uuid[9],
+ (unsigned int*)&voodoo_config->play_info.uuid[10], (unsigned int*)&voodoo_config->play_info.uuid[11], (unsigned int*)&voodoo_config->play_info.uuid[12], (unsigned int*)&voodoo_config->play_info.uuid[13], (unsigned int*)&voodoo_config->play_info.uuid[14],
+ (unsigned int*)&voodoo_config->play_info.uuid[15] );
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "proxy-memory-max" ) == 0) {
+ if (value) {
+ unsigned int max;
+
+ if (sscanf( value, "%u", &max ) != 1) {
+ D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name );
+ return DR_INVARG;
+ }
+
+ voodoo_config->memory_max = max * 1024;
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "proxy-surface-max" ) == 0) {
+ if (value) {
+ unsigned int max;
+
+ if (sscanf( value, "%u", &max ) != 1) {
+ D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name );
+ return DR_INVARG;
+ }
+
+ voodoo_config->surface_max = max * 1024;
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "proxy-layer-mask" ) == 0) {
+ if (value) {
+ unsigned int mask;
+
+ if (sscanf( value, "%u", &mask ) != 1) {
+ D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name );
+ return DR_INVARG;
+ }
+
+ voodoo_config->layer_mask = mask;
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "proxy-stacking-mask" ) == 0) {
+ if (value) {
+ unsigned int mask;
+
+ if (sscanf( value, "%u", &mask ) != 1) {
+ D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name );
+ return DR_INVARG;
+ }
+
+ voodoo_config->stacking_mask = mask;
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "proxy-resource-id" ) == 0) {
+ if (value) {
+ unsigned int resource_id;
+
+ if (sscanf( value, "%u", &resource_id ) != 1) {
+ D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name );
+ return DR_INVARG;
+ }
+
+ voodoo_config->resource_id = resource_id;
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "server-fork" ) == 0) {
+ voodoo_config->server_fork = true;
+ } else
+ if (strcmp (name, "no-server-fork" ) == 0) {
+ voodoo_config->server_fork = false;
+ } else
+ if (strcmp (name, "server-single" ) == 0) {
+ if (value) {
+ if (voodoo_config->server_single)
+ D_FREE( voodoo_config->server_single );
+
+ voodoo_config->server_single = D_STRDUP( value );
+ if (!voodoo_config->server_single)
+ D_OOM();
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "play-broadcast" ) == 0) {
+ if (value) {
+ if (voodoo_config->play_broadcast)
+ D_FREE( voodoo_config->play_broadcast );
+
+ voodoo_config->play_broadcast = D_STRDUP( value );
+ if (!voodoo_config->play_broadcast)
+ D_OOM();
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "compression-min" ) == 0) {
+ if (value) {
+ unsigned int min;
+
+ if (sscanf( value, "%u", &min ) != 1) {
+ D_ERROR( "Voodoo/Config '%s': Invalid value specified!\n", name );
+ return DR_INVARG;
+ }
+
+ voodoo_config->compression_min = min;
+ }
+ else {
+ D_ERROR( "Voodoo/Config '%s': No value specified!\n", name );
+ return DR_INVARG;
+ }
+ } else
+ if (strcmp (name, "link-raw" ) == 0) {
+ voodoo_config->link_raw = true;
+ } else
+ if (strcmp (name, "no-link-raw" ) == 0) {
+ voodoo_config->link_raw = false;
+ } else
+ if (strcmp (name, "link-packet" ) == 0) {
+ voodoo_config->link_packet = true;
+ } else
+ if (strcmp (name, "no-link-packet" ) == 0) {
+ voodoo_config->link_packet = false;
+ } else
+ if (direct_config_set( name, value ))
+ return DR_UNSUPPORTED;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/conf.h b/Source/DirectFB/lib/voodoo/conf.h
new file mode 100755
index 0000000..57dac9a
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/conf.h
@@ -0,0 +1,58 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CONF_H__
+#define __VOODOO__CONF_H__
+
+#include <voodoo/play.h>
+
+
+struct __V_VoodooConfig {
+ VoodooPlayInfo play_info;
+ bool forward_nodes;
+ unsigned int memory_max;
+ unsigned int surface_max;
+ unsigned int layer_mask;
+ unsigned int stacking_mask;
+ unsigned int resource_id;
+ bool server_fork;
+ char *server_single;
+ char *play_broadcast;
+ unsigned int compression_min;
+ bool link_raw;
+ bool link_packet;
+};
+
+extern VoodooConfig *voodoo_config;
+
+
+DirectResult voodoo_config_set( const char *name, const char *value );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/connection.cpp b/Source/DirectFB/lib/voodoo/connection.cpp
new file mode 100755
index 0000000..3bde3e1
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection.cpp
@@ -0,0 +1,70 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/link.h>
+}
+
+#include <voodoo/connection.h>
+
+
+D_DEBUG_DOMAIN( Voodoo_Connection, "Voodoo/Connection", "Voodoo Connection" );
+
+/**********************************************************************************************************************/
+
+VoodooConnection::VoodooConnection( VoodooManager *manager,
+ VoodooLink *link )
+ :
+ magic(0),
+ manager(manager),
+ link(link)
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnection::%s( %p )\n", __func__, this );
+
+ D_MAGIC_SET( this, VoodooConnection );
+}
+
+VoodooConnection::~VoodooConnection()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnection::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ link->Close( link );
+
+ D_MAGIC_CLEAR( this );
+}
+
diff --git a/Source/DirectFB/lib/voodoo/connection.h b/Source/DirectFB/lib/voodoo/connection.h
new file mode 100755
index 0000000..0e6521b
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection.h
@@ -0,0 +1,60 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CONNECTION_H__
+#define __VOODOO__CONNECTION_H__
+
+extern "C" {
+#include <voodoo/types.h>
+}
+
+
+class VoodooConnection {
+protected:
+ int magic;
+
+ VoodooManager *manager;
+ VoodooLink *link;
+
+public:
+ VoodooConnection( VoodooManager *manager,
+ VoodooLink *link );
+
+ virtual ~VoodooConnection();
+
+ virtual void Start() = 0;
+ virtual void Stop() = 0;
+
+
+ virtual VoodooPacket *GetPacket( size_t length ) = 0;
+ virtual void PutPacket( VoodooPacket *packet,
+ bool flush ) = 0;
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/connection_link.cpp b/Source/DirectFB/lib/voodoo/connection_link.cpp
new file mode 100755
index 0000000..b0ae138
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_link.cpp
@@ -0,0 +1,331 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+extern "C" {
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/fastlz.h>
+#include <direct/hash.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+}
+
+#include <voodoo/connection_link.h>
+#include <voodoo/manager.h>
+#include <voodoo/packet.h>
+
+
+#include <vector>
+
+
+//namespace Voodoo {
+
+D_DEBUG_DOMAIN( Voodoo_Connection, "Voodoo/Connection", "Voodoo Connection" );
+D_DEBUG_DOMAIN( Voodoo_Input, "Voodoo/Input", "Voodoo Input" );
+D_DEBUG_DOMAIN( Voodoo_Output, "Voodoo/Output", "Voodoo Output" );
+
+/**********************************************************************************************************************/
+
+VoodooConnectionLink::VoodooConnectionLink( VoodooManager *manager,
+ VoodooLink *link )
+ :
+ VoodooConnection( manager, link )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p )\n", __func__, this );
+
+ input.start = 0;
+ input.last = 0;
+ input.end = 0;
+ input.max = 0;
+
+ output.packets = NULL;
+ output.sending = NULL;
+
+ /* Initialize all locks. */
+ direct_mutex_init( &output.lock );
+
+ /* Initialize all wait conditions. */
+ direct_waitqueue_init( &output.wait );
+
+ /* Set default buffer limit. */
+ input.max = VOODOO_CONNECTION_LINK_INPUT_BUF_MAX;
+
+ /* Allocate buffers. */
+ size_t input_buffer_size = VOODOO_CONNECTION_LINK_INPUT_BUF_MAX + VOODOO_PACKET_MAX + sizeof(VoodooPacketHeader);
+
+ input.buffer = (u8*) D_MALLOC( input_buffer_size );
+
+ D_INFO( "VoodooConnection/Link: Allocated "_ZU" kB input buffer at %p\n", input_buffer_size/1024, input.buffer );
+
+ direct_tls_register( &output.tls, OutputTLS_Destructor );
+}
+
+VoodooConnectionLink::~VoodooConnectionLink()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ /* Acquire locks and wake up waiters. */
+ direct_mutex_lock( &output.lock );
+ direct_waitqueue_broadcast( &output.wait );
+ direct_mutex_unlock( &output.lock );
+
+ /* Destroy conditions. */
+ direct_waitqueue_deinit( &output.wait );
+
+ /* Destroy locks. */
+ direct_mutex_deinit( &output.lock );
+
+ /* Deallocate buffers. */
+ D_FREE( input.buffer );
+
+ direct_tls_unregister( &output.tls );
+}
+
+/**********************************************************************************************************************/
+
+VoodooPacket *
+VoodooConnectionLink::GetPacket( size_t length )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p, length "_ZU" )\n", __func__, this, length );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+ D_ASSERT( length >= (int) sizeof(VoodooMessageHeader) );
+ D_ASSUME( length <= MAX_MSG_SIZE );
+
+ if (length > MAX_MSG_SIZE) {
+ D_WARN( _ZU" exceeds maximum message size of %d", length, MAX_MSG_SIZE );
+ return NULL;
+ }
+
+ size_t aligned = VOODOO_MSG_ALIGN( length );
+
+
+ Packets *packets = (Packets*) direct_tls_get( output.tls );
+
+ if (!packets) {
+ packets = new Packets( this );
+
+ direct_tls_set( output.tls, packets );
+ }
+
+ VoodooPacket *packet = packets->active;
+
+ if (packet) {
+ if (packet->append( aligned ))
+ return packet;
+
+ Flush( packet );
+ }
+
+ packet = packets->Get();
+ if (packet) {
+ if (packet->sending) {
+ direct_mutex_lock( &output.lock );
+
+ while (packet->sending)
+ direct_waitqueue_wait( &output.wait, &output.lock );
+
+ direct_mutex_unlock( &output.lock );
+ }
+ packet->reset( aligned );
+ }
+
+ return packet;
+}
+
+void
+VoodooConnectionLink::PutPacket( VoodooPacket *packet, bool flush )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p, %sflush )\n", __func__, this, flush ? "" : "NO " );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ Packets *packets = (Packets*) direct_tls_get( output.tls );
+
+ D_ASSERT( packets != NULL );
+ D_ASSERT( packet == packets->active );
+
+ if (flush) {
+ Flush( packet );
+
+ packets->active = NULL;
+ }
+}
+
+void
+VoodooConnectionLink::Stop()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ direct_mutex_lock( &output.lock );
+
+ while (output.packets) {
+ VoodooPacket *packet = (VoodooPacket*) output.packets;
+
+ D_DEBUG_AT( Voodoo_Connection, " -> discarding output packet %p\n", packet );
+
+ D_ASSUME( packet->sending );
+
+ packet->sending = false;
+
+ direct_list_remove( &output.packets, &packet->link );
+ }
+
+ direct_mutex_unlock( &output.lock );
+
+ direct_waitqueue_broadcast( &output.wait );
+}
+
+void
+VoodooConnectionLink::Flush( VoodooPacket *packet )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( %p, packet %p )\n", __func__, this, packet );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ direct_mutex_lock( &output.lock );
+
+ D_ASSERT( !direct_list_contains_element_EXPENSIVE( output.packets, &packet->link ) );
+
+ D_ASSERT( !packet->sending );
+
+ packet->sending = true;
+
+ direct_list_append( &output.packets, &packet->link );
+
+ direct_mutex_unlock( &output.lock );
+
+ link->WakeUp( link );
+}
+
+void
+VoodooConnectionLink::OutputTLS_Destructor( void *ptr )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::%s( ptr %p )\n", __func__, ptr );
+
+ Packets *packets = (Packets*) ptr;
+
+ delete packets;
+
+ D_DEBUG_AT( Voodoo_Connection, " -> OutputTLS_Destructor done\n" );
+}
+
+VoodooConnectionLink::Packets::Packets( VoodooConnectionLink* connection )
+ :
+ magic(0),
+ connection(connection),
+ next(0),
+ num(0),
+ active(NULL)
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::Packets::%s( %p )\n", __func__, this );
+
+ memset( packets, 0, sizeof(packets) );
+
+ D_MAGIC_SET( this, Packets );
+}
+
+VoodooConnectionLink::Packets::~Packets()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::Packets::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, Packets );
+
+ for (size_t i=0; i<num; i++) {
+ if (packets[i]) {
+ D_DEBUG_AT( Voodoo_Connection, " -> destroying output packet "_ZU" (%p)\n", i, packets[i] );
+
+ if (packets[i]->sending) {
+ direct_mutex_lock( &connection->output.lock );
+
+ while (packets[i]->sending) {
+ D_DEBUG_AT( Voodoo_Connection, " -> packet sending, waiting...\n" );
+
+ direct_waitqueue_wait( &connection->output.wait, &connection->output.lock );
+ }
+
+ direct_mutex_unlock( &connection->output.lock );
+ }
+
+ D_FREE( packets[i] );
+ }
+ }
+}
+
+VoodooPacket *
+VoodooConnectionLink::Packets::Get()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionLink::Packets::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, Packets );
+
+ VoodooPacket *packet;
+
+ if (num < VOODOO_CONNECTION_PACKET_NUM_OUTPUT) {
+ packet = packets[num] = VoodooPacket::New( 0 );
+
+ D_DEBUG_AT( Voodoo_Connection, " -> new ["_ZU"] %p\n", num, packet );
+
+ num++;
+ }
+ else {
+ packet = packets[next];
+
+ next = (next+1) % VOODOO_CONNECTION_PACKET_NUM_OUTPUT;
+
+ D_DEBUG_AT( Voodoo_Connection, " -> reusing %p\n", packet );
+ }
+
+ active = packet;
+
+ return packet;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/connection_link.h b/Source/DirectFB/lib/voodoo/connection_link.h
new file mode 100755
index 0000000..328151c
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_link.h
@@ -0,0 +1,106 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CONNECTION_LINK_H__
+#define __VOODOO__CONNECTION_LINK_H__
+
+#include <voodoo/connection.h>
+
+extern "C" {
+#include <direct/thread.h>
+}
+
+#define VOODOO_CONNECTION_PACKET_NUM_OUTPUT 2
+#define VOODOO_CONNECTION_LINK_INPUT_BUF_MAX ((VOODOO_PACKET_MAX + sizeof(VoodooPacketHeader)) * 1)
+
+
+class VoodooConnectionLink : public VoodooConnection {
+protected:
+ struct {
+ u8 *buffer;
+ size_t start;
+ size_t last;
+ size_t end;
+ size_t max;
+ } input;
+
+ struct {
+ DirectMutex lock;
+ DirectWaitQueue wait;
+ DirectTLS tls;
+ DirectLink *packets;
+
+ VoodooPacket *sending;
+ size_t sent;
+ } output;
+
+public:
+ VoodooConnectionLink( VoodooManager *manager,
+ VoodooLink *link );
+
+ virtual ~VoodooConnectionLink();
+
+
+ virtual VoodooPacket *GetPacket( size_t length );
+ virtual void PutPacket( VoodooPacket *packet,
+ bool flush );
+
+ virtual void Stop ();
+
+
+private:
+ void Flush ( VoodooPacket *packet );
+
+ static void OutputTLS_Destructor( void *ptr );
+
+
+private:
+ friend class Packets;
+
+ class Packets {
+ private:
+ int magic;
+ VoodooConnectionLink *connection;
+ VoodooPacket *packets[VOODOO_CONNECTION_PACKET_NUM_OUTPUT];
+ size_t next;
+ size_t num;
+
+ public:
+ VoodooPacket *active;
+
+ public:
+ Packets( VoodooConnectionLink *connection );
+
+ ~Packets();
+
+ VoodooPacket *Get();
+ };
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/connection_packet.cpp b/Source/DirectFB/lib/voodoo/connection_packet.cpp
new file mode 100755
index 0000000..1e8a77f
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_packet.cpp
@@ -0,0 +1,368 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/fastlz.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/link.h>
+}
+
+#include <voodoo/connection_packet.h>
+#include <voodoo/manager.h>
+#include <voodoo/packet.h>
+
+
+#include <vector>
+
+
+//namespace Voodoo {
+
+D_DEBUG_DOMAIN( Voodoo_Connection, "Voodoo/Connection", "Voodoo Connection" );
+D_DEBUG_DOMAIN( Voodoo_Input, "Voodoo/Input", "Voodoo Input" );
+D_DEBUG_DOMAIN( Voodoo_Output, "Voodoo/Output", "Voodoo Output" );
+
+/**********************************************************************************************************************/
+
+VoodooConnectionPacket::VoodooConnectionPacket( VoodooManager *manager,
+ VoodooLink *link )
+ :
+ VoodooConnectionLink( manager, link ),
+ stop( false ),
+ closed( false )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+}
+
+VoodooConnectionPacket::~VoodooConnectionPacket()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+}
+
+void
+VoodooConnectionPacket::Start()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ io = direct_thread_create( DTT_DEFAULT, io_loop_main, this, "Voodoo IO" );
+}
+
+void
+VoodooConnectionPacket::Stop()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ direct_mutex_lock( &output.lock );
+
+ while (!closed && output.packets) {
+ D_DEBUG_AT( Voodoo_Connection, " -> waiting for output packets to be sent...\n" );
+
+ direct_waitqueue_wait( &output.wait, &output.lock );
+ }
+
+ direct_mutex_unlock( &output.lock );
+
+ stop = true;
+
+ link->WakeUp( link );
+
+ /* Wait for manager threads exiting. */
+ direct_thread_join( io );
+ direct_thread_destroy( io );
+
+ VoodooConnectionLink::Stop();
+}
+
+/**********************************************************************************************************************/
+
+void *
+VoodooConnectionPacket::io_loop()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ while (!stop) {
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ if (input.start == input.max) {
+ input.start = 0;
+ input.end = 0;
+ input.last = 0;
+ input.max = VOODOO_CONNECTION_LINK_INPUT_BUF_MAX;
+ }
+
+ if (!stop) {
+ DirectResult ret;
+ VoodooChunk chunks[2];
+ VoodooChunk *chunk_read = NULL;
+ VoodooChunk *chunk_write = NULL;
+ size_t last = input.last;
+ VoodooPacket *packet = NULL;
+
+ std::vector<VoodooChunk> chunks_write;
+ std::vector<VoodooChunk> chunks_read;
+
+ if (!output.sending) {
+ direct_mutex_lock( &output.lock );
+
+ if (output.packets) {
+ VoodooPacket *packet = (VoodooPacket*) output.packets;
+
+ D_ASSERT( packet->sending );
+
+ if (voodoo_config->compression_min && packet->size() >= voodoo_config->compression_min) {
+ output.sending = VoodooPacket::Compressed( packet );
+
+ if (output.sending->flags() & VPHF_COMPRESSED) {
+ D_DEBUG_AT( Voodoo_Output, " -> Compressed %u to %u bytes... (packet %p)\n",
+ output.sending->uncompressed(), output.sending->size(), packet );
+
+ output.sending->sending = true;
+
+ packet->sending = false;
+
+ direct_list_remove( &output.packets, &packet->link );
+
+ direct_waitqueue_broadcast( &output.wait );
+ }
+ }
+ else
+ output.sending = packet;
+
+ output.sent = 0;
+ }
+
+ direct_mutex_unlock( &output.lock );
+ }
+
+ if (output.sending) {
+ packet = output.sending;
+
+ D_ASSERT( packet->sending );
+
+ chunk_write = &chunks[1];
+
+ chunk_write->ptr = (char*) packet->data_header() + output.sent;
+ chunk_write->length = VOODOO_MSG_ALIGN(packet->size() + sizeof(VoodooPacketHeader)) - output.sent;
+ chunk_write->done = 0;
+
+ chunks_write.push_back( chunks[1] );
+
+ chunk_write = chunks_write.data();
+ }
+
+ if (input.end < input.max && manager->DispatchReady()) {
+ chunk_read = &chunks[0];
+
+ chunk_read->ptr = input.buffer + input.end;
+ chunk_read->length = input.max - input.end;
+ chunk_read->done = 0;
+
+ chunks_read.push_back( chunks[0] );
+
+ chunk_read = chunks_read.data();
+ }
+
+
+ ret = link->SendReceive( link,
+ chunks_write.data(), chunks_write.size(),
+ chunks_read.data(), chunks_read.size() );
+ switch (ret) {
+ case DR_OK:
+ if (chunk_write && chunk_write->done) {
+ D_DEBUG_AT( Voodoo_Output, " -> Sent "_ZD"/"_ZD" bytes... (packet %p)\n", chunk_write->done, chunk_write->length, packet );
+
+ output.sent += chunk_write->done;
+
+ if (output.sent == VOODOO_MSG_ALIGN(packet->size() + sizeof(VoodooPacketHeader))) {
+ output.sending = NULL;
+
+ if (packet->flags() & VPHF_COMPRESSED) {
+ packet->sending = false;
+
+ D_FREE( packet );
+ }
+ else {
+ direct_mutex_lock( &output.lock );
+
+ packet->sending = false;
+
+ direct_list_remove( &output.packets, &packet->link );
+
+ direct_mutex_unlock( &output.lock );
+
+ direct_waitqueue_broadcast( &output.wait );
+ }
+ }
+ }
+ break;
+
+ case DR_TIMEOUT:
+ //D_DEBUG_AT( Voodoo_Connection, " -> timeout\n" );
+ break;
+
+ case DR_INTERRUPTED:
+ D_DEBUG_AT( Voodoo_Connection, " -> interrupted\n" );
+ break;
+
+ default:
+ if (ret == DR_IO)
+ D_DEBUG_AT( Voodoo_Connection, " -> Connection closed!\n" );
+ else
+ {
+ D_DERROR( ret, "Voodoo/ConnectionPacket: Could not receive data!\n" );
+ exit(0);
+ }
+
+ goto disconnect;
+ }
+
+
+ if (chunk_read && chunk_read->done) {
+ D_DEBUG_AT( Voodoo_Input, " -> Received "_ZD" bytes...\n", chunk_read->done );
+
+ input.end += (size_t) chunk_read->done;
+
+ do {
+ VoodooPacketHeader *header;
+ size_t aligned;
+
+ /* Get the packet header. */
+ header = (VoodooPacketHeader *)(input.buffer + last);
+ aligned = VOODOO_MSG_ALIGN( header->size );
+
+ D_DEBUG_AT( Voodoo_Input, " -> Next packet has %u ("_ZU") -> %u bytes (flags 0x%04x)...\n",
+ header->size, aligned, header->uncompressed, header->flags );
+
+ if (input.end - last >= sizeof(VoodooPacketHeader)) {
+ if (header->uncompressed < (int) sizeof(VoodooMessageHeader)) {
+ D_DERROR( ret, "Voodoo/ConnectionPacket: Data error, uncompressed %d < min %zu!\n", header->uncompressed, sizeof(VoodooPacketHeader) );
+
+ goto disconnect;
+ }
+
+ if (header->uncompressed > VOODOO_PACKET_MAX) {
+ D_DERROR( ret, "Voodoo/ConnectionPacket: Data error, uncompressed %d > max %d!\n", header->uncompressed, VOODOO_PACKET_MAX );
+
+ goto disconnect;
+ }
+ }
+
+ if (sizeof(VoodooPacketHeader) + aligned > input.end - last) {
+ D_DEBUG_AT( Voodoo_Input, " -> ...fetching tail of message.\n" );
+
+ /* Extend the buffer if the message doesn't fit into the default boundary. */
+ if (sizeof(VoodooPacketHeader) + aligned > input.max - last)
+ input.max = last + sizeof(VoodooPacketHeader) + aligned;
+
+ break;
+ }
+
+ last += sizeof(VoodooPacketHeader) + aligned;
+ } while (last < input.end);
+
+ if (last != input.last) {
+ input.last = last;
+
+ D_DEBUG_AT( Voodoo_Input, " { START "_ZD", LAST "_ZD", END "_ZD", MAX "_ZD" }\n",
+ input.start, input.last, input.end, input.max );
+
+ while (input.start < input.last) {
+ /* Get the packet header. */
+ VoodooPacketHeader *header = (VoodooPacketHeader *)(input.buffer + input.start);
+
+ VoodooPacket *p;
+
+ D_ASSERT( header->uncompressed <= VOODOO_PACKET_MAX );
+
+ if (header->flags & VPHF_COMPRESSED) {
+ size_t uncompressed = direct_fastlz_decompress( header + 1, header->size, tmp, header->uncompressed );
+
+ D_DEBUG_AT( Voodoo_Input, " -> Uncompressed "_ZU" bytes (%u compressed)\n", uncompressed, header->size );
+
+ (void) uncompressed;
+
+ D_ASSERT( uncompressed == header->uncompressed );
+
+ // FIXME: don't copy, but read into packet directly, maybe call manager->GetPacket() at the top of this loop
+ p = VoodooPacket::Copy( header->uncompressed, VPHF_NONE,
+ header->uncompressed, tmp );
+ }
+ else {
+ // FIXME: don't copy, but read into packet directly, maybe call manager->GetPacket() at the top of this loop
+ p = VoodooPacket::Copy( header->uncompressed, VPHF_NONE,
+ header->uncompressed, header + 1 );
+ }
+
+ manager->DispatchPacket( p );
+
+ input.start += VOODOO_MSG_ALIGN(header->size) + sizeof(VoodooPacketHeader);
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+
+
+disconnect:
+ closed = true;
+
+ manager->handle_disconnect();
+
+ return NULL;
+}
+
+/**********************************************************************************************************************/
+
+void *
+VoodooConnectionPacket::io_loop_main( DirectThread *thread, void *arg )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p, thread %p )\n", __func__, arg, thread );
+
+ VoodooConnectionPacket *connection = (VoodooConnectionPacket*) arg;
+
+ return connection->io_loop();
+}
+
diff --git a/Source/DirectFB/lib/voodoo/connection_packet.h b/Source/DirectFB/lib/voodoo/connection_packet.h
new file mode 100755
index 0000000..ec53e27
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_packet.h
@@ -0,0 +1,61 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CONNECTION_PACKET_H__
+#define __VOODOO__CONNECTION_PACKET_H__
+
+#include <voodoo/connection_link.h>
+
+
+class VoodooConnectionPacket : public VoodooConnectionLink {
+private:
+ char tmp[VOODOO_PACKET_MAX];
+ DirectThread *io;
+ bool stop;
+ bool closed;
+
+public:
+ VoodooConnectionPacket( VoodooManager *manager,
+ VoodooLink *link );
+
+ virtual ~VoodooConnectionPacket();
+
+ virtual void Start();
+ virtual void Stop();
+
+
+private:
+ void *io_loop();
+
+
+ static void *io_loop_main( DirectThread *thread,
+ void *arg );
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/connection_packet_old.cpp b/Source/DirectFB/lib/voodoo/connection_packet_old.cpp
new file mode 100755
index 0000000..0efec4d
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_packet_old.cpp
@@ -0,0 +1,433 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+extern "C" {
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/fastlz.h>
+#include <direct/hash.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+}
+
+#include <voodoo/connection_packet.h>
+#include <voodoo/manager.h>
+#include <voodoo/packet.h>
+
+
+#include <vector>
+
+
+#define IN_BUF_MAX (640 * 1024)
+#define OUT_BUF_MAX (640 * 1024)
+
+
+//namespace Voodoo {
+
+D_DEBUG_DOMAIN( Voodoo_Connection, "Voodoo/Connection", "Voodoo Connection" );
+D_DEBUG_DOMAIN( Voodoo_Input, "Voodoo/Input", "Voodoo Input" );
+D_DEBUG_DOMAIN( Voodoo_Output, "Voodoo/Output", "Voodoo Output" );
+
+/**********************************************************************************************************************/
+
+VoodooConnectionPacket::VoodooConnectionPacket( VoodooManager *manager,
+ VoodooLink *link )
+ :
+ VoodooConnection( manager, link )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ input.start = 0;
+ input.last = 0;
+ input.end = 0;
+ input.max = 0;
+
+ output.start = 0;
+ output.end = 0;
+
+ /* Initialize all locks. */
+ direct_recursive_mutex_init( &input.lock );
+ direct_recursive_mutex_init( &output.lock );
+
+ /* Initialize all wait conditions. */
+ direct_waitqueue_init( &input.wait );
+ direct_waitqueue_init( &output.wait );
+
+ /* Set default buffer limit. */
+ input.max = IN_BUF_MAX;
+
+ /* Allocate buffers. */
+ input.buffer = (u8*) D_MALLOC( IN_BUF_MAX + VOODOO_PACKET_MAX + sizeof(VoodooPacketHeader) );
+ output.buffer = (u8*) D_MALLOC( OUT_BUF_MAX );
+
+ io = direct_thread_create( DTT_DEFAULT, io_loop_main, this, "Voodoo IO" );
+}
+
+VoodooConnectionPacket::~VoodooConnectionPacket()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ link->WakeUp( link );
+
+ /* Acquire locks and wake up waiters. */
+ direct_mutex_lock( &input.lock );
+ direct_waitqueue_broadcast( &input.wait );
+ direct_mutex_unlock( &input.lock );
+
+ direct_mutex_lock( &output.lock );
+ direct_waitqueue_broadcast( &output.wait );
+ direct_mutex_unlock( &output.lock );
+
+ /* Wait for manager threads exiting. */
+ direct_thread_join( io );
+ direct_thread_destroy( io );
+
+ /* Destroy conditions. */
+ direct_waitqueue_deinit( &input.wait );
+ direct_waitqueue_deinit( &output.wait );
+
+ /* Destroy locks. */
+ direct_mutex_deinit( &input.lock );
+ direct_mutex_deinit( &output.lock );
+
+ /* Deallocate buffers. */
+ D_FREE( output.buffer );
+ D_FREE( input.buffer );
+}
+
+/**********************************************************************************************************************/
+
+void *
+VoodooConnectionPacket::io_loop_main( DirectThread *thread, void *arg )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p, thread %p )\n", __func__, arg, thread );
+
+ VoodooConnectionPacket *connection = (VoodooConnectionPacket*) arg;
+
+ return connection->io_loop();
+}
+
+void *
+VoodooConnectionPacket::io_loop()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p )\n", __func__, this );
+
+ while (!manager->is_quit) {
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+// direct_mutex_lock( &manager->input.lock );
+
+ if (input.start == input.max) {
+ input.start = 0;
+ input.end = 0;
+ input.last = 0;
+ input.max = IN_BUF_MAX;
+ }
+
+// direct_mutex_unlock( &input.lock );
+
+ if (!manager->is_quit) {
+ DirectResult ret;
+ VoodooChunk chunks[2];
+ VoodooChunk *chunk_read = NULL;
+ VoodooChunk *chunk_write = NULL;
+ size_t last = input.last;
+
+ std::vector<VoodooChunk> chunks_write;
+ std::vector<VoodooChunk> chunks_read;
+
+ direct_mutex_lock( &output.lock );
+
+ if (input.end < input.max) {
+ chunk_read = &chunks[0];
+
+ chunk_read->ptr = input.buffer + input.end;
+ chunk_read->length = input.max - input.end;
+ chunk_read->done = 0;
+
+ chunks_read.push_back( chunks[0] );
+
+ chunk_read = chunks_read.data();
+ }
+
+ if (output.end > output.start) {
+ chunk_write = &chunks[1];
+
+ chunk_write->ptr = output.buffer + output.start;
+ chunk_write->length = output.end - output.start;
+ chunk_write->done = 0;
+
+ if (chunk_write->length > 65536) {
+ chunk_write->length = 65536;
+ }
+
+ chunks_write.push_back( chunks[1] );
+
+ chunk_write = chunks_write.data();
+ }
+
+ if (!chunk_write)
+ direct_mutex_unlock( &output.lock );
+
+#if 0
+ if (chunk_write) {
+ char buf[chunk_write->length*4/3];
+
+ size_t comp = direct_fastlz_compress( chunk_write->ptr, chunk_write->length, buf );
+
+ D_DEBUG_AT( Voodoo_Output, " -> Compressed "_ZU"%% ("_ZU" -> "_ZU")\n",
+ comp * 100 / chunk_write->length, chunk_write->length, comp );
+ }
+#endif
+
+ ret = link->SendReceive( link,
+ chunks_write.data(), chunks_write.size(),
+ chunks_read.data(), chunks_read.size() );
+ switch (ret) {
+ case DR_OK:
+ if (chunk_write && chunk_write->done) {
+ D_DEBUG_AT( Voodoo_Output, " -> Sent "_ZD"/"_ZD" bytes...\n", chunk_write->done, chunk_write->length );
+
+ output.start += (size_t) chunk_write->done;
+
+ //direct_mutex_lock( &output.lock );
+
+ if (output.start == output.end) {
+ output.start = output.end = 0;
+
+ direct_waitqueue_broadcast( &output.wait );
+ }
+
+ //direct_mutex_unlock( &output.lock );
+ }
+ break;
+
+ case DR_TIMEOUT:
+ //D_WARN("timeout");
+ break;
+
+ case DR_INTERRUPTED:
+ //D_WARN("interrupted");
+ break;
+
+ default:
+ D_DERROR( ret, "Voodoo/Manager: Could not receive data!\n" );
+ manager->handle_disconnect();
+ break;
+ }
+
+ if (chunk_write)
+ direct_mutex_unlock( &output.lock );
+
+
+
+ if (chunk_read && chunk_read->done) {
+ D_DEBUG_AT( Voodoo_Input, " -> Received "_ZD" bytes...\n", chunk_read->done );
+
+ input.end += (size_t) chunk_read->done;
+
+ do {
+ VoodooPacketHeader *header;
+
+ /* Get the packet header. */
+ header = (VoodooPacketHeader *)(input.buffer + last);
+
+ D_DEBUG_AT( Voodoo_Input, " -> Next packet has %u bytes...\n", header->size );
+
+ D_ASSERT( header->size >= (int) sizeof(VoodooMessageHeader) );
+ D_ASSERT( header->size <= MAX_MSG_SIZE );
+
+ if (sizeof(VoodooPacketHeader) + header->size > input.end - last) {
+ D_DEBUG_AT( Voodoo_Input, " -> ...fetching tail of message.\n" );
+
+ /* Extend the buffer if the message doesn't fit into the default boundary. */
+ if (sizeof(VoodooPacketHeader) + header->size > input.max - last) {
+ D_ASSERT( input.max == IN_BUF_MAX );
+
+
+ input.max = last + sizeof(VoodooPacketHeader) + header->size;
+ }
+
+ break;
+ }
+
+ last += sizeof(VoodooPacketHeader) + header->size;
+ } while (last < input.end);
+
+ if (last != input.last) {
+
+ input.last = last;
+
+ D_DEBUG_AT( Voodoo_Input, " { START "_ZD", LAST "_ZD", END "_ZD", MAX "_ZD" }\n",
+ input.start, input.last, input.end, input.max );
+
+ while (input.start < input.last) {
+ /* Get the packet header. */
+ VoodooPacketHeader *header = (VoodooPacketHeader *)(input.buffer + input.start);
+
+ ProcessMessages( (VoodooMessageHeader *)(header + 1), header->uncompressed );
+
+ input.start += header->size + sizeof(VoodooPacketHeader);
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+VoodooConnectionPacket::lock_output( int length,
+ void **ret_ptr )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p, length %d )\n", __func__, this, length );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+ D_ASSERT( length >= (int) sizeof(VoodooMessageHeader) );
+ D_ASSUME( length <= MAX_MSG_SIZE );
+ D_ASSERT( ret_ptr != NULL );
+
+ if (length > MAX_MSG_SIZE) {
+ D_WARN( "%d exceeds maximum message size of %d", length, MAX_MSG_SIZE );
+ return DR_LIMITEXCEEDED;
+ }
+
+ int aligned = VOODOO_MSG_ALIGN( length );
+
+ direct_mutex_lock( &output.lock );
+
+ while (output.end + aligned > OUT_BUF_MAX) {
+ link->WakeUp( link );
+
+ direct_waitqueue_wait( &output.wait, &output.lock );
+
+ if (manager->is_quit) {
+ direct_mutex_lock( &output.lock );
+ return DR_DESTROYED;
+ }
+ }
+
+ *ret_ptr = output.buffer + output.end;
+
+ D_DEBUG_AT( Voodoo_Output, " -> offset "_ZD", aligned length %d\n", output.end, aligned );
+
+ output.end += aligned;
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooConnectionPacket::unlock_output( bool flush )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p, %sflush )\n", __func__, this, flush ? "" : "NO " );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ direct_mutex_unlock( &output.lock );
+
+ if (flush)
+ link->WakeUp( link );
+
+ return DR_OK;
+}
+
+VoodooPacket *
+VoodooConnectionPacket::GetPacket( size_t length )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p, length "_ZU" )\n", __func__, this, length );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+ D_ASSERT( length >= (int) sizeof(VoodooMessageHeader) );
+ D_ASSUME( length <= MAX_MSG_SIZE );
+
+ if (length > MAX_MSG_SIZE) {
+ D_WARN( _ZU" exceeds maximum message size of %d", length, MAX_MSG_SIZE );
+ return NULL;
+ }
+
+ int aligned = sizeof(VoodooPacketHeader) + VOODOO_MSG_ALIGN( length );
+
+ direct_mutex_lock( &output.lock );
+
+ while (output.end + aligned > OUT_BUF_MAX) {
+ link->WakeUp( link );
+
+ direct_waitqueue_wait( &output.wait, &output.lock );
+
+ if (manager->is_quit) {
+ direct_mutex_lock( &output.lock );
+ return NULL;
+ }
+ }
+
+ D_DEBUG_AT( Voodoo_Output, " -> offset "_ZD", aligned length %d\n", output.end, aligned );
+
+ output.end += aligned;
+
+ return VoodooPacket::New( output.buffer + output.end - aligned, aligned - sizeof(VoodooPacketHeader) );
+}
+
+void
+VoodooConnectionPacket::PutPacket( VoodooPacket *packet, bool flush )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionPacket::%s( %p, %sflush )\n", __func__, this, flush ? "" : "NO " );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ direct_mutex_unlock( &output.lock );
+
+ if (flush)
+ link->WakeUp( link );
+
+// delete packet;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/connection_packet_old.h b/Source/DirectFB/lib/voodoo/connection_packet_old.h
new file mode 100755
index 0000000..cfb10bf
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_packet_old.h
@@ -0,0 +1,87 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CONNECTION_PACKET_H__
+#define __VOODOO__CONNECTION_PACKET_H__
+
+#include <voodoo/connection.h>
+
+extern "C" {
+#include <direct/thread.h>
+}
+
+
+class VoodooConnectionPacket : public VoodooConnection {
+private:
+ DirectThread *io;
+
+ struct {
+ DirectMutex lock;
+ DirectWaitQueue wait;
+ u8 *buffer;
+ size_t start;
+ size_t last;
+ size_t end;
+ size_t max;
+ } input;
+
+ struct {
+ DirectMutex lock;
+ DirectWaitQueue wait;
+ u8 *buffer;
+ size_t start;
+ size_t end;
+ } output;
+
+public:
+ VoodooConnectionPacket( VoodooManager *manager,
+ VoodooLink *link );
+
+ virtual ~VoodooConnectionPacket();
+
+
+ virtual DirectResult lock_output ( int length,
+ void **ret_ptr );
+
+ virtual DirectResult unlock_output( bool flush );
+
+
+ virtual VoodooPacket *GetPacket( size_t length );
+ virtual void PutPacket( VoodooPacket *packet,
+ bool flush );
+
+
+private:
+ static void *io_loop_main ( DirectThread *thread,
+ void *arg );
+
+ void *io_loop ();
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/connection_raw.cpp b/Source/DirectFB/lib/voodoo/connection_raw.cpp
new file mode 100755
index 0000000..c6ba56a
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_raw.cpp
@@ -0,0 +1,341 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#ifdef VOODOO_CONNECTION_RAW_DUMP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#endif
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+}
+
+#include <voodoo/connection_raw.h>
+#include <voodoo/manager.h>
+#include <voodoo/packet.h>
+
+
+#include <vector>
+
+
+//namespace Voodoo {
+
+D_DEBUG_DOMAIN( Voodoo_Connection, "Voodoo/Connection", "Voodoo Connection" );
+D_DEBUG_DOMAIN( Voodoo_Input, "Voodoo/Input", "Voodoo Input" );
+D_DEBUG_DOMAIN( Voodoo_Output, "Voodoo/Output", "Voodoo Output" );
+
+/**********************************************************************************************************************/
+
+VoodooConnectionRaw::VoodooConnectionRaw( VoodooManager *manager,
+ VoodooLink *link )
+ :
+ VoodooConnectionLink( manager, link ),
+ stop( false ),
+ closed( false )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionRaw::%s( %p )\n", __func__, this );
+
+ if (link->code) {
+ input.end = 4;
+
+ memcpy( input.buffer, &link->code, sizeof(u32) );
+ }
+}
+
+VoodooConnectionRaw::~VoodooConnectionRaw()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionRaw::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+}
+
+void
+VoodooConnectionRaw::Start()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionRaw::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ io = direct_thread_create( DTT_DEFAULT, io_loop_main, this, "Voodoo IO" );
+}
+
+void
+VoodooConnectionRaw::Stop()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionRaw::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ direct_mutex_lock( &output.lock );
+
+ while (!closed && output.packets) {
+ D_DEBUG_AT( Voodoo_Connection, " -> waiting for output packets to be sent...\n" );
+
+ direct_waitqueue_wait( &output.wait, &output.lock );
+ }
+
+ direct_mutex_unlock( &output.lock );
+
+ stop = true;
+
+ link->WakeUp( link );
+
+ /* Wait for manager threads exiting. */
+ direct_thread_join( io );
+ direct_thread_destroy( io );
+
+ VoodooConnectionLink::Stop();
+}
+
+/**********************************************************************************************************************/
+
+void *
+VoodooConnectionRaw::io_loop()
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionRaw::%s( %p )\n", __func__, this );
+
+#ifdef VOODOO_CONNECTION_RAW_DUMP
+ int dump_fd = open("voodoo_write.raw", O_TRUNC|O_CREAT|O_WRONLY, 0660 );
+ int dump_read_fd = open("voodoo_read.raw", O_TRUNC|O_CREAT|O_WRONLY, 0660 );
+#endif
+
+ while (!stop) {
+ D_MAGIC_ASSERT( this, VoodooConnection );
+
+ if (input.start == input.max) {
+ input.start = 0;
+ input.end = 0;
+ input.last = 0;
+ input.max = VOODOO_CONNECTION_LINK_INPUT_BUF_MAX;
+ }
+
+ if (!stop) {
+ DirectResult ret;
+ VoodooChunk chunks[2];
+ VoodooChunk *chunk_read = NULL;
+ VoodooChunk *chunk_write = NULL;
+ size_t last = input.last;
+ VoodooPacket *packet = NULL;
+
+ std::vector<VoodooChunk> chunks_write;
+ std::vector<VoodooChunk> chunks_read;
+
+ if (!output.sending) {
+ direct_mutex_lock( &output.lock );
+
+ if (output.packets) {
+ VoodooPacket *packet = (VoodooPacket*) output.packets;
+
+ D_ASSERT( packet->sending );
+
+ output.sending = packet;
+ output.sent = 0;
+ }
+
+ direct_mutex_unlock( &output.lock );
+ }
+
+ if (output.sending) {
+ packet = output.sending;
+
+ D_ASSERT( packet->sending );
+
+ chunk_write = &chunks[1];
+
+ chunk_write->ptr = (char*) packet->data_start() + output.sent;
+ chunk_write->length = VOODOO_MSG_ALIGN(packet->size()) - output.sent;
+ chunk_write->done = 0;
+
+ chunks_write.push_back( chunks[1] );
+
+ chunk_write = chunks_write.data();
+ }
+
+ if (input.end < input.max && manager->DispatchReady()) {
+ chunk_read = &chunks[0];
+
+ chunk_read->ptr = input.buffer + input.end;
+ chunk_read->length = input.max - input.end;
+ chunk_read->done = 0;
+
+ chunks_read.push_back( chunks[0] );
+
+ chunk_read = chunks_read.data();
+ }
+
+
+ ret = link->SendReceive( link,
+ chunks_write.data(), chunks_write.size(),
+ chunks_read.data(), chunks_read.size() );
+ switch (ret) {
+ case DR_OK:
+ if (chunk_write && chunk_write->done) {
+ D_DEBUG_AT( Voodoo_Output, " -> Sent "_ZD"/"_ZD" bytes...\n", chunk_write->done, chunk_write->length );
+
+#ifdef VOODOO_CONNECTION_RAW_DUMP
+ write( dump_fd, chunk_write->ptr, chunk_write->done );
+#endif
+
+ output.sent += chunk_write->done;
+
+ if (output.sent == VOODOO_MSG_ALIGN(packet->size())) {
+ output.sending = NULL;
+
+ direct_mutex_lock( &output.lock );
+
+ packet->sending = false;
+
+ direct_list_remove( &output.packets, &packet->link );
+
+ direct_mutex_unlock( &output.lock );
+
+ direct_waitqueue_broadcast( &output.wait );
+ }
+ }
+ break;
+
+ case DR_TIMEOUT:
+ //D_DEBUG_AT( Voodoo_Connection, " -> timeout\n" );
+ break;
+
+ case DR_INTERRUPTED:
+ D_DEBUG_AT( Voodoo_Connection, " -> interrupted\n" );
+ break;
+
+ default:
+ if (ret == DR_IO)
+ D_DEBUG_AT( Voodoo_Connection, " -> Connection closed!\n" );
+ else
+ {
+ D_DERROR( ret, "Voodoo/ConnectionRaw: Could not receive data!\n" );
+ exit(0);
+ }
+
+ closed = true;
+
+ manager->handle_disconnect();
+
+ return NULL;
+ }
+
+
+ if (chunk_read && chunk_read->done) {
+ D_DEBUG_AT( Voodoo_Input, " -> Received "_ZD" bytes...\n", chunk_read->done );
+
+#ifdef VOODOO_CONNECTION_RAW_DUMP
+ write( dump_read_fd, chunk_read->ptr, chunk_read->done );
+#endif
+
+ input.end += (size_t) chunk_read->done;
+
+ do {
+ VoodooMessageHeader *header;
+ size_t aligned;
+
+ D_DEBUG_AT( Voodoo_Input, " { LAST "_ZD", INPUT LAST "_ZD" }\n", last, input.last );
+
+ if (input.end - last < 4) {
+ D_DEBUG_AT( Voodoo_Input, " -> ...only "_ZU" bytes left\n", input.end - last );
+ break;
+ }
+
+ /* Get the message header. */
+ header = (VoodooMessageHeader *)(input.buffer + last);
+ aligned = VOODOO_MSG_ALIGN( header->size );
+
+ D_DEBUG_AT( Voodoo_Input, " -> Next message has %d ("_ZD") bytes and is of type %d...\n",
+ header->size, aligned, header->type );
+
+ D_ASSERT( header->size >= (int) sizeof(VoodooMessageHeader) );
+ D_ASSERT( header->size <= MAX_MSG_SIZE );
+
+ if (aligned > input.end - last) {
+ D_DEBUG_AT( Voodoo_Input, " -> ...fetching tail of message.\n" );
+
+ /* Extend the buffer if the message doesn't fit into the default boundary. */
+ if (aligned > input.max - last)
+ input.max = last + aligned;
+
+ break;
+ }
+
+ last += aligned;
+ } while (last < input.end);
+
+ if (last != input.last) {
+ input.last = last;
+
+ D_DEBUG_AT( Voodoo_Input, " { START "_ZD", LAST "_ZD", END "_ZD", MAX "_ZD" }\n",
+ input.start, input.last, input.end, input.max );
+
+ // FIXME: don't copy, but read into packet directly, maybe call manager->GetPacket() at the top of this loop
+ VoodooPacket *p = VoodooPacket::Copy( input.last - input.start, VPHF_NONE,
+ input.last - input.start, input.buffer + input.start );
+
+ manager->DispatchPacket( p );
+
+ input.start = input.last;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**********************************************************************************************************************/
+
+void *
+VoodooConnectionRaw::io_loop_main( DirectThread *thread, void *arg )
+{
+ D_DEBUG_AT( Voodoo_Connection, "VoodooConnectionRaw::%s( %p, thread %p )\n", __func__, arg, thread );
+
+ VoodooConnectionRaw *connection = (VoodooConnectionRaw*) arg;
+
+ return connection->io_loop();
+}
+
diff --git a/Source/DirectFB/lib/voodoo/connection_raw.h b/Source/DirectFB/lib/voodoo/connection_raw.h
new file mode 100755
index 0000000..45ce4c5
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/connection_raw.h
@@ -0,0 +1,60 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__CONNECTION_RAW_H__
+#define __VOODOO__CONNECTION_RAW_H__
+
+#include <voodoo/connection_link.h>
+
+
+class VoodooConnectionRaw : public VoodooConnectionLink {
+private:
+ DirectThread *io;
+ bool stop;
+ bool closed;
+
+public:
+ VoodooConnectionRaw( VoodooManager *manager,
+ VoodooLink *link );
+
+ virtual ~VoodooConnectionRaw();
+
+ virtual void Start();
+ virtual void Stop();
+
+
+private:
+ void *io_loop();
+
+
+ static void *io_loop_main( DirectThread *thread,
+ void *arg );
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/dispatcher.cpp b/Source/DirectFB/lib/voodoo/dispatcher.cpp
new file mode 100755
index 0000000..af98c0a
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/dispatcher.cpp
@@ -0,0 +1,231 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/link.h>
+#include <voodoo/message.h>
+}
+
+#include <voodoo/dispatcher.h>
+#include <voodoo/manager.h>
+#include <voodoo/packet.h>
+
+
+D_DEBUG_DOMAIN( Voodoo_Dispatcher, "Voodoo/Dispatcher", "Voodoo Dispatcher" );
+
+/**********************************************************************************************************************/
+
+VoodooDispatcher::VoodooDispatcher( VoodooManager *manager )
+ :
+ magic(0),
+ manager(manager),
+ packets(NULL)
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this );
+
+ /* Initialize lock. */
+ direct_mutex_init( &lock );
+
+ /* Initialize wait queue. */
+ direct_waitqueue_init( &queue );
+
+ D_MAGIC_SET( this, VoodooDispatcher );
+
+
+ dispatch_loop = direct_thread_create( DTT_MESSAGING, DispatchLoopMain, this, "Voodoo Dispatch" );
+}
+
+VoodooDispatcher::~VoodooDispatcher()
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooDispatcher );
+
+ /* Acquire lock and wake up waiters. */
+ direct_mutex_lock( &lock );
+ direct_waitqueue_broadcast( &queue );
+ direct_mutex_unlock( &lock );
+
+ /* Wait for dispatcher loop exiting. */
+ direct_thread_join( dispatch_loop );
+ direct_thread_destroy( dispatch_loop );
+
+ /* Destroy queue. */
+ direct_waitqueue_deinit( &queue );
+
+ /* Destroy lock. */
+ direct_mutex_deinit( &lock );
+
+ D_MAGIC_CLEAR( this );
+}
+
+bool
+VoodooDispatcher::Ready()
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooDispatcher );
+
+ direct_mutex_lock( &lock );
+
+ bool ready = direct_list_count_elements_EXPENSIVE( packets ) < 3;
+
+ direct_mutex_unlock( &lock );
+
+ return ready;
+}
+
+void
+VoodooDispatcher::PutPacket( VoodooPacket *packet )
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p, packet %p )\n", __func__, this, packet );
+
+ D_MAGIC_ASSERT( this, VoodooDispatcher );
+
+ direct_mutex_lock( &lock );
+
+ direct_list_append( &packets, &packet->link );
+
+ direct_waitqueue_broadcast( &queue );
+
+ direct_mutex_unlock( &lock );
+}
+
+void
+VoodooDispatcher::ProcessMessages( VoodooMessageHeader *first,
+ size_t total_length )
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p, first %p, total_length "_ZU" )\n",
+ __func__, this, first, total_length );
+
+ D_MAGIC_ASSERT( this, VoodooDispatcher );
+
+ VoodooMessageHeader *header = first;
+ size_t offset = 0;
+ size_t aligned;
+
+ while (offset < total_length) {
+ /* Get the message header. */
+ header = (VoodooMessageHeader *)((char*) first + offset);
+ aligned = VOODOO_MSG_ALIGN( header->size );
+
+ D_DEBUG_AT( Voodoo_Dispatcher, " -> Next message has %d ("_ZU") bytes and is of type %d... (offset "_ZU"/"_ZU")\n",
+ header->size, aligned, header->type, offset, total_length );
+
+ D_ASSERT( header->size >= (int) sizeof(VoodooMessageHeader) );
+ D_ASSERT( header->size <= MAX_MSG_SIZE );
+
+ D_ASSERT( offset + aligned <= total_length );
+
+ switch (header->type) {
+ case VMSG_SUPER:
+ manager->handle_super( (VoodooSuperMessage*) header );
+ break;
+
+ case VMSG_REQUEST:
+ manager->handle_request( (VoodooRequestMessage*) header );
+ break;
+
+ case VMSG_RESPONSE:
+ manager->handle_response( (VoodooResponseMessage*) header );
+ break;
+
+ default:
+ D_BUG( "invalid message type %d", header->type );
+ break;
+ }
+
+ offset += aligned;
+ }
+
+ D_ASSERT( offset == total_length );
+}
+
+/**********************************************************************************************************************/
+
+void *
+VoodooDispatcher::DispatchLoop()
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this );
+
+ direct_mutex_lock( &lock );
+
+ while (!manager->is_quit) {
+ VoodooPacket *packet;
+
+ D_MAGIC_ASSERT( this, VoodooDispatcher );
+
+ if (packets) {
+ packet = (VoodooPacket*) packets;
+
+ direct_list_remove( &packets, &packet->link );
+
+ manager->link->WakeUp( manager->link );
+ }
+ else {
+ direct_waitqueue_wait( &queue, &lock );
+
+ continue;
+ }
+
+
+ direct_mutex_unlock( &lock );
+
+ ProcessMessages( (VoodooMessageHeader*) packet->data_start(), packet->size() );
+
+ D_FREE( packet );
+
+ direct_mutex_lock( &lock );
+ }
+
+ direct_mutex_unlock( &lock );
+
+ return NULL;
+}
+
+void *
+VoodooDispatcher::DispatchLoopMain( DirectThread *thread, void *arg )
+{
+ D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p, thread %p )\n", __func__, arg, thread );
+
+ VoodooDispatcher *dispatcher = (VoodooDispatcher*) arg;
+
+ return dispatcher->DispatchLoop();
+}
+
diff --git a/Source/DirectFB/lib/voodoo/dispatcher.h b/Source/DirectFB/lib/voodoo/dispatcher.h
new file mode 100755
index 0000000..f0518db
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/dispatcher.h
@@ -0,0 +1,71 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__DISPATCHER_H__
+#define __VOODOO__DISPATCHER_H__
+
+extern "C" {
+#include <voodoo/types.h>
+}
+
+
+class VoodooDispatcher {
+private:
+ int magic;
+
+ VoodooManager *manager;
+
+ DirectMutex lock;
+ DirectWaitQueue queue;
+
+ DirectThread *dispatch_loop;
+
+ DirectLink *packets;
+
+
+public:
+ VoodooDispatcher( VoodooManager *manager );
+
+ ~VoodooDispatcher();
+
+ bool Ready ();
+ void PutPacket( VoodooPacket *packet );
+
+
+private:
+ void *DispatchLoop();
+
+ static void *DispatchLoopMain( DirectThread *thread,
+ void *arg );
+
+ void ProcessMessages ( VoodooMessageHeader *first,
+ size_t total_length );
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/instance.cpp b/Source/DirectFB/lib/voodoo/instance.cpp
new file mode 100755
index 0000000..61bd20f
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/instance.cpp
@@ -0,0 +1,107 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/internal.h>
+}
+
+#include <voodoo/instance.h>
+#include <voodoo/manager.h>
+
+
+D_DEBUG_DOMAIN( Voodoo_Instance, "Voodoo/Instance", "Voodoo Instance" );
+
+/**********************************************************************************************************************/
+
+VoodooInstance::VoodooInstance()
+ :
+ magic(0),
+ refs(1)
+{
+ D_DEBUG_AT( Voodoo_Instance, "VoodooInstance::%s( %p )\n", __func__, this );
+
+ D_MAGIC_SET( this, VoodooInstance );
+}
+
+VoodooInstance::~VoodooInstance()
+{
+ D_DEBUG_AT( Voodoo_Instance, "VoodooInstance::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+
+ D_MAGIC_CLEAR( this );
+}
+
+void
+VoodooInstance::AddRef()
+{
+ D_DEBUG_AT( Voodoo_Instance, "VoodooInstance::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ D_ASSERT( refs > 0 );
+
+ refs++;
+}
+
+void
+VoodooInstance::Release()
+{
+ D_DEBUG_AT( Voodoo_Instance, "VoodooInstance::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ D_ASSERT( refs > 0 );
+
+ if (!--refs) {
+ D_DEBUG_AT( Voodoo_Instance, " -> zero refs, deleting instance...\n" );
+
+ delete this;
+ }
+}
+
+DirectResult
+VoodooInstance::Dispatch( VoodooManager *manager,
+ VoodooRequestMessage *msg )
+{
+ D_DEBUG_AT( Voodoo_Instance, "VoodooInstance::%s( %p, manager %p, msg %p )\n", __func__, this, manager, msg );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/instance.h b/Source/DirectFB/lib/voodoo/instance.h
new file mode 100755
index 0000000..a8b434c
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/instance.h
@@ -0,0 +1,61 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__INSTANCE_H__
+#define __VOODOO__INSTANCE_H__
+
+extern "C" {
+#include <voodoo/types.h>
+}
+
+
+class VoodooInstance {
+protected:
+ int magic;
+
+private:
+ unsigned int refs;
+
+public:
+ VoodooInstance();
+
+protected:
+ virtual ~VoodooInstance();
+
+public:
+ void AddRef();
+ void Release();
+
+
+public:
+ virtual DirectResult Dispatch( VoodooManager *manager,
+ VoodooRequestMessage *msg );
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/interface.c b/Source/DirectFB/lib/voodoo/interface.c
new file mode 100755
index 0000000..4281cb6
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/interface.c
@@ -0,0 +1,114 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/messages.h>
+
+#include <voodoo/interface.h>
+
+
+DirectResult
+voodoo_construct_requestor( VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID instance,
+ void *arg,
+ void **ret_requestor )
+{
+ DirectResult ret;
+ DirectInterfaceFuncs *funcs;
+ void *requestor;
+
+ D_ASSERT( manager != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( instance != VOODOO_INSTANCE_NONE );
+ D_ASSERT( ret_requestor != NULL );
+
+ ret = DirectGetInterface( &funcs, name, "Requestor", NULL, NULL );
+ if (ret) {
+ D_ERROR( "Voodoo/Interface: Could not load 'Requestor' implementation of '%s'!\n", name );
+ return ret;
+ }
+
+ ret = funcs->Allocate( &requestor );
+ if (ret)
+ return ret;
+
+ ret = funcs->Construct( requestor, manager, instance, arg );
+ if (ret)
+ return ret;
+
+ *ret_requestor = requestor;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_construct_dispatcher( VoodooManager *manager,
+ const char *name,
+ void *interface,
+ VoodooInstanceID super,
+ void *arg,
+ VoodooInstanceID *ret_instance,
+ void **ret_dispatcher )
+{
+ DirectResult ret;
+ DirectInterfaceFuncs *funcs;
+ void *dispatcher;
+ VoodooInstanceID instance;
+
+ D_ASSERT( manager != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( interface != NULL );
+ D_ASSERT( super != VOODOO_INSTANCE_NONE );
+ D_ASSERT( ret_instance != NULL );
+
+ ret = DirectGetInterface( &funcs, name, "Dispatcher", NULL, NULL );
+ if (ret) {
+ D_ERROR( "Voodoo/Interface: Could not load 'Dispatcher' implementation of '%s'!\n", name );
+ return ret;
+ }
+
+ ret = funcs->Allocate( &dispatcher );
+ if (ret)
+ return ret;
+
+ ret = funcs->Construct( dispatcher, interface, manager, super, arg, &instance );
+ if (ret)
+ return ret;
+
+ *ret_instance = instance;
+
+ if (ret_dispatcher)
+ *ret_dispatcher = dispatcher;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/interface.h b/Source/DirectFB/lib/voodoo/interface.h
new file mode 100755
index 0000000..8b1a47b
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/interface.h
@@ -0,0 +1,52 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__INTERFACE_H__
+#define __VOODOO__INTERFACE_H__
+
+#include <voodoo/types.h>
+
+
+DirectResult
+voodoo_construct_requestor( VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID instance,
+ void *arg,
+ void **ret_interface );
+
+DirectResult
+voodoo_construct_dispatcher( VoodooManager *manager,
+ const char *name,
+ void *interface,
+ VoodooInstanceID super,
+ void *arg,
+ VoodooInstanceID *ret_instance,
+ void **ret_dispatcher );
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/internal.h b/Source/DirectFB/lib/voodoo/internal.h
new file mode 100755
index 0000000..4eae9b0
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/internal.h
@@ -0,0 +1,40 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__INTERNAL_H__
+#define __VOODOO__INTERNAL_H__
+
+#include <voodoo/types.h>
+
+
+DirectResult VOODOO_API voodoo_server_construct( VoodooServer *server,
+ VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance );
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/ivoodooplayer.c b/Source/DirectFB/lib/voodoo/ivoodooplayer.c
new file mode 100755
index 0000000..2324667
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/ivoodooplayer.c
@@ -0,0 +1,247 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <semaphore.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <directfb_version.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/direct.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/interface.h>
+#include <voodoo/internal.h>
+#include <voodoo/manager.h>
+#include <voodoo/play_server.h>
+#include <voodoo/ivoodooplayer.h>
+
+
+D_DEBUG_DOMAIN( IVoodooPlayer_, "IVoodooPlayer", "IVoodooPlayer" );
+
+/**********************************************************************************************************************/
+
+static DirectResult CreateRemote( const char *host, int session, IVoodooPlayer **ret_interface );
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ int ref;
+} IVoodooPlayer_data;
+
+static DirectResult
+IVoodooPlayer_AddRef( IVoodooPlayer *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA( IVoodooPlayer );
+
+ data->ref++;
+
+ return DR_OK;
+}
+
+static DirectResult
+IVoodooPlayer_Release( IVoodooPlayer *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA( IVoodooPlayer );
+
+ if (!--data->ref)
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+
+ return DR_OK;
+}
+
+static DirectResult
+IVoodooPlayer_GetApps( IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppDescription *ret_applications )
+{
+ D_DEBUG_AT( IVoodooPlayer_, "%s()\n", __func__ );
+
+ if (!max_num || !ret_num || !ret_applications)
+ return DR_INVARG;
+
+ return voodoo_player_get_apps( voodoo_player, max_num, ret_num, ret_applications );
+}
+
+static DirectResult
+IVoodooPlayer_LaunchApp( IVoodooPlayer *thiz,
+ const u8 app_uuid[16],
+ const u8 player_uuid[16],
+ u8 ret_instance_uuid[16] )
+{
+ D_DEBUG_AT( IVoodooPlayer_, "%s()\n", __func__ );
+
+ if (!app_uuid || !player_uuid || !ret_instance_uuid)
+ return DR_INVARG;
+
+ return voodoo_player_launch_app( voodoo_player, app_uuid, player_uuid, ret_instance_uuid );
+}
+
+static DirectResult
+IVoodooPlayer_StopInstance( IVoodooPlayer *thiz,
+ const u8 instance_uuid[16] )
+{
+ D_DEBUG_AT( IVoodooPlayer_, "%s()\n", __func__ );
+
+ if (!instance_uuid)
+ return DR_INVARG;
+
+ return voodoo_player_stop_instance( voodoo_player, instance_uuid );
+}
+
+static DirectResult
+IVoodooPlayer_WaitInstance( IVoodooPlayer *thiz,
+ const u8 instance_uuid[16] )
+{
+ D_DEBUG_AT( IVoodooPlayer_, "%s()\n", __func__ );
+
+ if (!instance_uuid)
+ return DR_INVARG;
+
+ return voodoo_player_wait_instance( voodoo_player, instance_uuid );
+}
+
+static DirectResult
+IVoodooPlayer_GetInstances( IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppInstanceDescription *ret_instances )
+{
+ D_DEBUG_AT( IVoodooPlayer_, "%s()\n", __func__ );
+
+ if (!max_num || !ret_num || !ret_instances)
+ return DR_INVARG;
+
+ return voodoo_player_get_instances( voodoo_player, max_num, ret_num, ret_instances );
+}
+
+static DirectResult
+IVoodooPlayer_Construct( IVoodooPlayer *thiz )
+{
+ DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IVoodooPlayer );
+
+ data->ref = 1;
+
+ thiz->AddRef = IVoodooPlayer_AddRef;
+ thiz->Release = IVoodooPlayer_Release;
+ thiz->GetApps = IVoodooPlayer_GetApps;
+ thiz->LaunchApp = IVoodooPlayer_LaunchApp;
+ thiz->StopInstance = IVoodooPlayer_StopInstance;
+ thiz->WaitInstance = IVoodooPlayer_WaitInstance;
+ thiz->GetInstances = IVoodooPlayer_GetInstances;
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooPlayerCreate( IVoodooPlayer **ret_interface )
+{
+ DirectResult ret;
+ IVoodooPlayer *player;
+
+ if (!ret_interface)
+ return DR_INVARG;
+
+ if (dfb_config->remote.host)
+ return CreateRemote( dfb_config->remote.host, dfb_config->remote.session, ret_interface );
+
+ if (!voodoo_player)
+ return DR_NOSUCHINSTANCE;
+
+ DIRECT_ALLOCATE_INTERFACE( player, IVoodooPlayer );
+
+ ret = IVoodooPlayer_Construct( player );
+ if (ret)
+ return ret;
+
+ *ret_interface = player;
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+static DirectResult
+CreateRemote( const char *host, int session, IVoodooPlayer **ret_interface )
+{
+ DFBResult ret;
+ DirectInterfaceFuncs *funcs;
+ void *interface;
+
+ D_ASSERT( host != NULL );
+ D_ASSERT( ret_interface != NULL );
+
+ ret = DirectGetInterface( &funcs, "IVoodooPlayer", "Requestor", NULL, NULL );
+ if (ret)
+ return ret;
+
+ ret = funcs->Allocate( &interface );
+ if (ret)
+ return ret;
+
+ ret = funcs->Construct( interface, host, session );
+ if (ret)
+ return ret;
+
+ *ret_interface = interface;
+
+ return DFB_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/ivoodooplayer.h b/Source/DirectFB/lib/voodoo/ivoodooplayer.h
new file mode 100755
index 0000000..ae1ef03
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/ivoodooplayer.h
@@ -0,0 +1,74 @@
+/*
+ (c) Copyright 2001-2010 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __IVOODOOPLAYER_H__
+#define __IVOODOOPLAYER_H__
+
+#include <voodoo/app.h>
+
+
+DECLARE_INTERFACE( IVoodooPlayer );
+
+DEFINE_INTERFACE( IVoodooPlayer,
+
+ DirectResult (*GetApps)(
+ IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppDescription *ret_applications
+ );
+
+ DirectResult (*LaunchApp)(
+ IVoodooPlayer *thiz,
+ const u8 app_uuid[16],
+ const u8 player_uuid[16],
+ u8 ret_instance_uuid[16]
+ );
+
+ DirectResult (*StopInstance)(
+ IVoodooPlayer *thiz,
+ const u8 instance_uuid[16]
+ );
+
+ DirectResult (*WaitInstance)(
+ IVoodooPlayer *thiz,
+ const u8 instance_uuid[16]
+ );
+
+ DirectResult (*GetInstances)(
+ IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppInstanceDescription *ret_instances
+ );
+);
+
+
+DirectResult VoodooPlayerCreate( IVoodooPlayer **ret_interface );
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.c b/Source/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.c
new file mode 100755
index 0000000..bcf4711
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.c
@@ -0,0 +1,359 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/messages.h>
+
+#include <voodoo/ivoodooplayer.h>
+
+#include <voodoo/interface.h>
+#include <voodoo/manager.h>
+#include <voodoo/message.h>
+
+#include "ivoodooplayer_dispatcher.h"
+
+static DirectResult Probe( void );
+static DirectResult Construct( IVoodooPlayer *thiz,
+ VoodooManager *manager,
+ VoodooInstanceID *ret_instance );
+
+#include <direct/interface_implementation.h>
+
+DIRECT_INTERFACE_IMPLEMENTATION( IVoodooPlayer, Dispatcher )
+
+
+/**************************************************************************************************/
+
+/*
+ * private data struct of IVoodooPlayer_Dispatcher
+ */
+typedef struct {
+ int ref; /* reference counter */
+
+ IVoodooPlayer *real;
+
+ VoodooInstanceID self; /* The instance of this dispatcher itself. */
+} IVoodooPlayer_Dispatcher_data;
+
+/**************************************************************************************************/
+
+static void
+IVoodooPlayer_Dispatcher_Destruct( IVoodooPlayer *thiz )
+{
+ D_DEBUG( "%s (%p)\n", __FUNCTION__, thiz );
+
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+IVoodooPlayer_Dispatcher_AddRef( IVoodooPlayer *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ data->ref++;
+
+ return DR_OK;
+}
+
+static DirectResult
+IVoodooPlayer_Dispatcher_Release( IVoodooPlayer *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ if (--data->ref == 0)
+ IVoodooPlayer_Dispatcher_Destruct( thiz );
+
+ return DR_OK;
+}
+
+static DirectResult
+IVoodooPlayer_Dispatcher_GetApps( IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppDescription *ret_applications )
+{
+ return DR_UNIMPLEMENTED;
+}
+
+static DirectResult
+IVoodooPlayer_Dispatcher_LaunchApp( IVoodooPlayer *thiz,
+ const u8 app_uuid[16],
+ const u8 player_uuid[16],
+ u8 ret_instance_uuid[16] )
+{
+ return DR_UNIMPLEMENTED;
+}
+
+static DirectResult
+IVoodooPlayer_Dispatcher_StopInstance( IVoodooPlayer *thiz,
+ const u8 instance_uuid[16] )
+{
+ return DR_UNIMPLEMENTED;
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+Dispatch_GetApps( IVoodooPlayer *thiz, IVoodooPlayer *real,
+ VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ DirectResult ret;
+ unsigned int max_num;
+ VoodooMessageParser parser;
+ unsigned int num;
+ VoodooAppDescription *apps;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ VOODOO_PARSER_BEGIN( parser, msg );
+ VOODOO_PARSER_GET_UINT( parser, max_num );
+ VOODOO_PARSER_END( parser );
+
+ if (max_num > 1000)
+ return DR_LIMITEXCEEDED;
+
+ apps = D_MALLOC( max_num * sizeof(VoodooAppDescription) );
+ if (!apps)
+ return D_OOM();
+
+ ret = real->GetApps( real, max_num, &num, apps );
+ if (ret == DR_OK) {
+ if (num > 0) {
+ ret = voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_UINT, num,
+ VMBT_DATA, num * sizeof(VoodooAppDescription), apps,
+ VMBT_NONE );
+ }
+ else {
+ ret = voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_UINT, num,
+ VMBT_NONE );
+ }
+ }
+
+ D_FREE( apps );
+
+ return ret;
+}
+
+static DirectResult
+Dispatch_LaunchApp( IVoodooPlayer *thiz, IVoodooPlayer *real,
+ VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ DirectResult ret;
+ VoodooMessageParser parser;
+ const u8 *app_uuid;
+ const u8 *player_uuid;
+ u8 instance_uuid[16];
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ VOODOO_PARSER_BEGIN( parser, msg );
+ VOODOO_PARSER_GET_DATA( parser, app_uuid );
+ VOODOO_PARSER_GET_DATA( parser, player_uuid );
+ VOODOO_PARSER_END( parser );
+
+ ret = real->LaunchApp( real, app_uuid, player_uuid, instance_uuid );
+
+ return voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_DATA, 16, instance_uuid,
+ VMBT_NONE );
+}
+
+static DirectResult
+Dispatch_StopInstance( IVoodooPlayer *thiz, IVoodooPlayer *real,
+ VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ DirectResult ret;
+ VoodooMessageParser parser;
+ const u8 *instance_uuid;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ VOODOO_PARSER_BEGIN( parser, msg );
+ VOODOO_PARSER_GET_DATA( parser, instance_uuid );
+ VOODOO_PARSER_END( parser );
+
+ ret = real->StopInstance( real, instance_uuid );
+
+ return voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_NONE );
+}
+
+static DirectResult
+Dispatch_WaitInstance( IVoodooPlayer *thiz, IVoodooPlayer *real,
+ VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ DirectResult ret;
+ VoodooMessageParser parser;
+ const u8 *instance_uuid;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ VOODOO_PARSER_BEGIN( parser, msg );
+ VOODOO_PARSER_GET_DATA( parser, instance_uuid );
+ VOODOO_PARSER_END( parser );
+
+ ret = real->WaitInstance( real, instance_uuid );
+
+ return voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_NONE );
+}
+
+static DirectResult
+Dispatch_GetInstances( IVoodooPlayer *thiz, IVoodooPlayer *real,
+ VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ DirectResult ret;
+ unsigned int max_num;
+ VoodooMessageParser parser;
+ unsigned int num;
+ VoodooAppInstanceDescription *instances;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Dispatcher)
+
+ VOODOO_PARSER_BEGIN( parser, msg );
+ VOODOO_PARSER_GET_UINT( parser, max_num );
+ VOODOO_PARSER_END( parser );
+
+ if (max_num > 1000)
+ return DR_LIMITEXCEEDED;
+
+ instances = D_MALLOC( max_num * sizeof(VoodooAppInstanceDescription) );
+ if (!instances)
+ return D_OOM();
+
+ ret = real->GetInstances( real, max_num, &num, instances );
+ if (ret == DR_OK) {
+ if (num > 0) {
+ ret = voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_UINT, num,
+ VMBT_DATA, num * sizeof(VoodooAppInstanceDescription), instances,
+ VMBT_NONE );
+ }
+ else {
+ ret = voodoo_manager_respond( manager, true, msg->header.serial,
+ ret, VOODOO_INSTANCE_NONE,
+ VMBT_UINT, num,
+ VMBT_NONE );
+ }
+ }
+
+ D_FREE( instances );
+
+ return ret;
+}
+
+static DirectResult
+Dispatch( void *dispatcher, void *real, VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ D_DEBUG( "IVoodooPlayer/Dispatcher: "
+ "Handling request for instance %u with method %u...\n", msg->instance, msg->method );
+
+ switch (msg->method) {
+ case IVOODOOPLAYER_METHOD_ID_GetApps:
+ return Dispatch_GetApps( dispatcher, real, manager, msg );
+
+ case IVOODOOPLAYER_METHOD_ID_LaunchApp:
+ return Dispatch_LaunchApp( dispatcher, real, manager, msg );
+
+ case IVOODOOPLAYER_METHOD_ID_StopInstance:
+ return Dispatch_StopInstance( dispatcher, real, manager, msg );
+
+ case IVOODOOPLAYER_METHOD_ID_WaitInstance:
+ return Dispatch_WaitInstance( dispatcher, real, manager, msg );
+
+ case IVOODOOPLAYER_METHOD_ID_GetInstances:
+ return Dispatch_GetInstances( dispatcher, real, manager, msg );
+ }
+
+ return DR_NOSUCHMETHOD;
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+Probe()
+{
+ /* This implementation has to be loaded explicitly. */
+ return DR_UNSUPPORTED;
+}
+
+/*
+ * Constructor
+ *
+ * Fills in function pointers and intializes data structure.
+ */
+static DirectResult
+Construct( IVoodooPlayer *thiz, VoodooManager *manager, VoodooInstanceID *ret_instance )
+{
+ DirectResult ret;
+ IVoodooPlayer *real;
+ VoodooInstanceID instance;
+
+ DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IVoodooPlayer_Dispatcher)
+
+ ret = VoodooPlayerCreate( &real );
+ if (ret) {
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ ret = voodoo_manager_register_local( manager, VOODOO_INSTANCE_NONE, thiz, real, Dispatch, &instance );
+ if (ret) {
+ real->Release( real );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ *ret_instance = instance;
+
+ data->ref = 1;
+ data->real = real;
+ data->self = instance;
+
+ thiz->AddRef = IVoodooPlayer_Dispatcher_AddRef;
+ thiz->Release = IVoodooPlayer_Dispatcher_Release;
+ thiz->GetApps = IVoodooPlayer_Dispatcher_GetApps;
+ thiz->LaunchApp = IVoodooPlayer_Dispatcher_LaunchApp;
+ thiz->StopInstance = IVoodooPlayer_Dispatcher_StopInstance;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.h b/Source/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.h
new file mode 100755
index 0000000..a01d0d9
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/ivoodooplayer_dispatcher.h
@@ -0,0 +1,41 @@
+/*
+ (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __IVOODOOPLAYER_DISPATCHER_H__
+#define __IVOODOOPLAYER_DISPATCHER_H__
+
+#define IVOODOOPLAYER_METHOD_ID_AddRef 1
+#define IVOODOOPLAYER_METHOD_ID_Release 2
+#define IVOODOOPLAYER_METHOD_ID_GetApps 3
+#define IVOODOOPLAYER_METHOD_ID_LaunchApp 4
+#define IVOODOOPLAYER_METHOD_ID_StopInstance 5
+#define IVOODOOPLAYER_METHOD_ID_WaitInstance 6
+#define IVOODOOPLAYER_METHOD_ID_GetInstances 7
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/ivoodooplayer_requestor.c b/Source/DirectFB/lib/voodoo/ivoodooplayer_requestor.c
new file mode 100755
index 0000000..1ffdcf9
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/ivoodooplayer_requestor.c
@@ -0,0 +1,330 @@
+/*
+ (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/messages.h>
+
+#include <voodoo/ivoodooplayer.h>
+
+#include <voodoo/client.h>
+#include <voodoo/interface.h>
+#include <voodoo/manager.h>
+#include <voodoo/message.h>
+
+#include "ivoodooplayer_dispatcher.h"
+
+
+static DirectResult Probe( void );
+static DirectResult Construct( IVoodooPlayer *thiz, const char *host, int session );
+
+#include <direct/interface_implementation.h>
+
+DIRECT_INTERFACE_IMPLEMENTATION( IVoodooPlayer, Requestor )
+
+
+/**************************************************************************************************/
+
+/*
+ * private data struct of IVoodooPlayer_Requestor
+ */
+typedef struct {
+ int ref; /* reference counter */
+
+ VoodooClient *client;
+ VoodooManager *manager;
+
+ VoodooInstanceID instance;
+} IVoodooPlayer_Requestor_data;
+
+/**************************************************************************************************/
+
+static void
+IVoodooPlayer_Requestor_Destruct( IVoodooPlayer *thiz )
+{
+ IVoodooPlayer_Requestor_data *data = thiz->priv;
+
+ D_DEBUG( "%s (%p)\n", __FUNCTION__, thiz );
+
+ voodoo_client_destroy( data->client );
+
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+IVoodooPlayer_Requestor_AddRef( IVoodooPlayer *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ data->ref++;
+
+ return DR_OK;
+}
+
+static DirectResult
+IVoodooPlayer_Requestor_Release( IVoodooPlayer *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ if (--data->ref == 0)
+ IVoodooPlayer_Requestor_Destruct( thiz );
+
+ return DR_OK;
+}
+
+static DirectResult
+IVoodooPlayer_Requestor_GetApps( IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppDescription *ret_applications )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+
+ if (!max_num || !ret_num || !ret_applications)
+ return DR_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IVOODOOPLAYER_METHOD_ID_GetApps, VREQ_RESPOND, &response,
+ VMBT_UINT, max_num,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret == DR_OK) {
+ VoodooMessageParser parser;
+ unsigned int num;
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_UINT( parser, num );
+
+ if (num > max_num)
+ num = max_num;
+
+ *ret_num = num;
+
+ if (num > 0)
+ VOODOO_PARSER_READ_DATA( parser, ret_applications, num * sizeof(VoodooAppDescription) );
+
+ VOODOO_PARSER_END( parser );
+ }
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+}
+
+static DirectResult
+IVoodooPlayer_Requestor_LaunchApp( IVoodooPlayer *thiz,
+ const u8 app_uuid[16],
+ const u8 player_uuid[16],
+ u8 ret_instance_uuid[16] )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+
+ if (!app_uuid || !player_uuid || !ret_instance_uuid)
+ return DR_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IVOODOOPLAYER_METHOD_ID_LaunchApp, VREQ_RESPOND, &response,
+ VMBT_DATA, 16, app_uuid,
+ VMBT_DATA, 16, player_uuid,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret == DR_OK) {
+ VoodooMessageParser parser;
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_READ_DATA( parser, ret_instance_uuid, 16 );
+ VOODOO_PARSER_END( parser );
+ }
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+}
+
+static DirectResult
+IVoodooPlayer_Requestor_StopInstance( IVoodooPlayer *thiz,
+ const u8 instance_uuid[16] )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+
+ if (!instance_uuid)
+ return DR_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IVOODOOPLAYER_METHOD_ID_StopInstance, VREQ_RESPOND, &response,
+ VMBT_DATA, 16, instance_uuid,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+}
+
+static DirectResult
+IVoodooPlayer_Requestor_WaitInstance( IVoodooPlayer *thiz,
+ const u8 instance_uuid[16] )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+
+ if (!instance_uuid)
+ return DR_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IVOODOOPLAYER_METHOD_ID_WaitInstance, VREQ_RESPOND, &response,
+ VMBT_DATA, 16, instance_uuid,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+}
+
+static DirectResult
+IVoodooPlayer_Requestor_GetInstances( IVoodooPlayer *thiz,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppInstanceDescription *ret_instances )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+
+ if (!max_num || !ret_num || !ret_instances)
+ return DR_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA(IVoodooPlayer_Requestor)
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IVOODOOPLAYER_METHOD_ID_GetInstances, VREQ_RESPOND, &response,
+ VMBT_UINT, max_num,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret == DR_OK) {
+ VoodooMessageParser parser;
+ unsigned int num;
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_UINT( parser, num );
+
+ if (num > max_num)
+ num = max_num;
+
+ *ret_num = num;
+
+ if (num > 0)
+ VOODOO_PARSER_READ_DATA( parser, ret_instances, num * sizeof(VoodooAppInstanceDescription) );
+
+ VOODOO_PARSER_END( parser );
+ }
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+Probe()
+{
+ /* This implementation has to be loaded explicitly. */
+ return DR_UNSUPPORTED;
+}
+
+/*
+ * Constructor
+ *
+ * Fills in function pointers and intializes data structure.
+ */
+static DirectResult
+Construct( IVoodooPlayer *thiz, const char *host, int session )
+{
+ DirectResult ret;
+
+ DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IVoodooPlayer_Requestor)
+
+ data->ref = 1;
+
+ ret = voodoo_client_create( host, session, &data->client );
+ if (ret) {
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ data->manager = voodoo_client_manager( data->client );
+
+ ret = voodoo_manager_super( data->manager, "IVoodooPlayer", &data->instance );
+ if (ret) {
+ voodoo_client_destroy( data->client );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ thiz->AddRef = IVoodooPlayer_Requestor_AddRef;
+ thiz->Release = IVoodooPlayer_Requestor_Release;
+ thiz->GetApps = IVoodooPlayer_Requestor_GetApps;
+ thiz->LaunchApp = IVoodooPlayer_Requestor_LaunchApp;
+ thiz->StopInstance = IVoodooPlayer_Requestor_StopInstance;
+ thiz->WaitInstance = IVoodooPlayer_Requestor_WaitInstance;
+ thiz->GetInstances = IVoodooPlayer_Requestor_GetInstances;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/link.h b/Source/DirectFB/lib/voodoo/link.h
new file mode 100755
index 0000000..e54b1d4
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/link.h
@@ -0,0 +1,78 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__LINK_H__
+#define __VOODOO__LINK_H__
+
+#include <voodoo/types.h>
+
+
+typedef struct {
+ void *ptr;
+ size_t length;
+ size_t done;
+} VoodooChunk;
+
+
+struct __V_VoodooLink {
+ void *priv;
+ u32 code;
+
+ void (*Close)( VoodooLink *link );
+
+ /* See 'read(2)', blocking */
+ ssize_t (*Read) ( VoodooLink *link,
+ void *buffer,
+ size_t count );
+
+ /* See 'write(2)', blocking */
+ ssize_t (*Write)( VoodooLink *link,
+ const void *buffer,
+ size_t count );
+
+
+ /* For later... */
+ DirectResult (*SendReceive)( VoodooLink *link,
+ VoodooChunk *send,
+ size_t num_send,
+ VoodooChunk *recv,
+ size_t num_recv );
+
+ DirectResult (*WakeUp) ( VoodooLink *link );
+};
+
+
+DirectResult VOODOO_API voodoo_link_init_connect( VoodooLink *link,
+ const char *hostname,
+ int port,
+ bool raw );
+
+DirectResult VOODOO_API voodoo_link_init_fd ( VoodooLink *link,
+ int fd[2] );
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/manager.cpp b/Source/DirectFB/lib/voodoo/manager.cpp
new file mode 100755
index 0000000..3b2f70c
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/manager.cpp
@@ -0,0 +1,937 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <algorithm>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+}
+
+#include <voodoo/connection_packet.h>
+#include <voodoo/connection_raw.h>
+#include <voodoo/dispatcher.h>
+#include <voodoo/manager.h>
+#include <voodoo/packet.h>
+
+
+//namespace Voodoo {
+
+D_DEBUG_DOMAIN( Voodoo_Dispatch, "Voodoo/Dispatch", "Voodoo Dispatch" );
+D_DEBUG_DOMAIN( Voodoo_Manager, "Voodoo/Manager", "Voodoo Manager" );
+
+/**********************************************************************************************************************/
+
+VoodooManager::VoodooManager( VoodooLink *link,
+ VoodooContext *context )
+ :
+ magic(0),
+ is_quit(false),
+ msg_count(0),
+ msg_serial(0)
+{
+ D_ASSERT( link != NULL );
+
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ /* Store link and context */
+ this->link = link;
+ this->context = context;
+
+
+ instances.last = 0;
+
+ response.current = NULL;
+
+
+ /* Initialize all locks. */
+ direct_recursive_mutex_init( &instances.lock );
+ direct_recursive_mutex_init( &response.lock );
+
+ /* Initialize all wait conditions. */
+ direct_waitqueue_init( &response.wait_get );
+ direct_waitqueue_init( &response.wait_put );
+
+ D_MAGIC_SET( this, VoodooManager );
+
+
+ dispatcher = new VoodooDispatcher( this );
+
+
+ /* Add connection */
+ if ((link->code & 0x8000ffff) == 0x80008676) {
+ D_INFO( "Voodoo/Manager: Connection mode is PACKET\n" );
+
+ connection = new VoodooConnectionPacket( this, link );
+ }
+ else {
+ D_INFO( "Voodoo/Manager: Connection mode is RAW\n" );
+
+ connection = new VoodooConnectionRaw( this, link );
+
+ // FIXME: query manager dynamically for compression instead
+ voodoo_config->compression_min = 0;
+ }
+
+ connection->Start();
+}
+
+static void
+instance_iterator( std::pair<VoodooInstanceID,VoodooInstance*> pair )
+{
+ D_DEBUG_AT( Voodoo_Manager, "%s( id %u, instance %p )\n", __func__, pair.first, pair.second );
+
+ pair.second->Release();
+}
+
+VoodooManager::~VoodooManager()
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+
+ if (!is_quit)
+ quit();
+
+ connection->Stop();
+
+ /* Destroy dispatcher */
+ delete dispatcher;
+
+ /* Remove connection */
+ delete connection;
+
+ /* Destroy conditions. */
+ direct_waitqueue_deinit( &response.wait_get );
+ direct_waitqueue_deinit( &response.wait_put );
+
+ /* Destroy locks. */
+ direct_mutex_deinit( &instances.lock );
+ direct_mutex_deinit( &response.lock );
+
+ /* Release all remaining interfaces. */
+ std::for_each( instances.remote.begin(), instances.remote.end(), instance_iterator );
+ std::for_each( instances.local.begin(), instances.local.end(), instance_iterator );
+
+ D_MAGIC_CLEAR( this );
+}
+
+/**********************************************************************************************************************/
+
+void
+VoodooManager::DispatchPacket( VoodooPacket *packet )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p, packet %p )\n", __func__, this, packet );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSUME( !is_quit );
+
+ if (is_quit)
+ return;
+
+ dispatcher->PutPacket( packet );
+}
+
+bool
+VoodooManager::DispatchReady()
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+// D_ASSUME( !is_quit );
+
+ if (is_quit)
+ return false;
+
+ return dispatcher->Ready();
+}
+
+/**********************************************************************************************************************/
+
+void
+VoodooManager::quit()
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSUME( !is_quit );
+
+ if (is_quit)
+ return;
+
+ /* Have all threads quit upon this. */
+ is_quit = true;
+
+ /* Acquire locks and wake up waiters. */
+ direct_mutex_lock( &response.lock );
+ direct_waitqueue_broadcast( &response.wait_get );
+ direct_waitqueue_broadcast( &response.wait_put );
+ direct_mutex_unlock( &response.lock );
+}
+
+void
+VoodooManager::handle_disconnect()
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Remote site disconnected from manager at %p!\n", this );
+
+ quit();
+}
+
+void
+VoodooManager::handle_super( VoodooSuperMessage *super )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ DirectResult ret;
+ const char *name;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( super != NULL );
+ D_ASSERT( super->header.size >= (int) sizeof(VoodooSuperMessage) );
+ D_ASSERT( super->header.type == VMSG_SUPER );
+
+ name = (const char *) (super + 1);
+
+ D_DEBUG_AT( Voodoo_Dispatch, " -> Handling SUPER message %llu for '%s' (%d bytes).\n",
+ (unsigned long long)super->header.serial, name, super->header.size );
+
+ VoodooInstanceID instance_id;
+
+ ret = context->HandleSuper( this, name, &instance_id );
+ if (ret)
+ do_respond( true, super->header.serial, ret );
+ else
+ do_respond( true, super->header.serial, DR_OK, instance_id );
+}
+
+typedef struct {
+ VoodooManager *manager;
+ VoodooInstance *instance;
+ VoodooRequestMessage *request;
+} DispatchAsyncContext;
+
+void *
+VoodooManager::dispatch_async_thread( DirectThread *thread,
+ void *arg )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, arg );
+
+ DirectResult ret;
+ DispatchAsyncContext *context = (DispatchAsyncContext*) arg;
+ VoodooManager *manager = context->manager;
+ VoodooInstance *instance = context->instance;
+ VoodooRequestMessage *request = context->request;
+
+ ret = instance->Dispatch( manager, request );
+
+ if (ret && (request->flags & VREQ_RESPOND))
+ manager->do_respond( true, request->header.serial, ret );
+
+ D_FREE( context );
+
+ return NULL;
+}
+
+void
+VoodooManager::handle_request( VoodooRequestMessage *request )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ DirectResult ret;
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( request != NULL );
+ D_ASSERT( request->header.size >= (int) sizeof(VoodooRequestMessage) );
+ D_ASSERT( request->header.type == VMSG_REQUEST );
+
+ D_DEBUG_AT( Voodoo_Dispatch, " -> Handling REQUEST message %llu to %u::%u %s%s(%d bytes).\n",
+ (unsigned long long)request->header.serial, request->instance, request->method,
+ (request->flags & VREQ_RESPOND) ? "[RESPONDING] " : "",
+ (request->flags & VREQ_ASYNC) ? "[ASYNC] " : "",
+ request->header.size );
+
+ direct_mutex_lock( &instances.lock );
+
+ InstanceMap::iterator itr = instances.local.find( request->instance );
+
+ if (itr == instances.local.end()) {
+ direct_mutex_unlock( &instances.lock );
+
+ D_ERROR( "Voodoo/Dispatch: "
+ "Requested instance %u doesn't exist (anymore)!\n", request->instance );
+
+ if (request->flags & VREQ_RESPOND)
+ do_respond( true, request->header.serial, DR_NOSUCHINSTANCE );
+
+ return;
+ }
+
+ instance = (*itr).second;
+
+ if (request->flags & VREQ_ASYNC) {
+ DirectThread *thread;
+ DispatchAsyncContext *context;
+
+ context = (DispatchAsyncContext*) D_MALLOC( sizeof(DispatchAsyncContext) + request->header.size );
+ if (!context) {
+ D_WARN( "out of memory" );
+ direct_mutex_unlock( &instances.lock );
+ return;
+ }
+
+ context->manager = this;
+ context->instance = instance;
+ context->request = (VoodooRequestMessage*) (context + 1);
+
+ direct_memcpy( context->request, request, request->header.size );
+
+ thread = direct_thread_create( DTT_DEFAULT, dispatch_async_thread, context, "Voodoo Async" );
+ direct_thread_detach( thread );
+ // FIXME: free thread?
+ }
+ else {
+ ret = instance->Dispatch( this, request );
+
+ if (ret && (request->flags & VREQ_RESPOND))
+ do_respond( true, request->header.serial, ret );
+ }
+
+ direct_mutex_unlock( &instances.lock );
+}
+
+void
+VoodooManager::handle_response( VoodooResponseMessage *msg )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( msg != NULL );
+ D_ASSERT( msg->header.size >= (int) sizeof(VoodooResponseMessage) );
+ D_ASSERT( msg->header.type == VMSG_RESPONSE );
+ D_ASSERT( msg->request < msg_serial );
+
+ D_DEBUG_AT( Voodoo_Dispatch, " -> Handling RESPONSE message %llu (%s) with instance %u for request "
+ "%llu (%d bytes).\n", (unsigned long long)msg->header.serial, DirectResultString( msg->result ),
+ msg->instance, (unsigned long long)msg->request, msg->header.size );
+
+ direct_mutex_lock( &response.lock );
+
+ D_ASSERT( response.current == NULL );
+
+ response.current = msg;
+
+ direct_mutex_unlock( &response.lock );
+
+
+ direct_waitqueue_broadcast( &response.wait_get );
+
+ direct_mutex_lock( &response.lock );
+
+ while (response.current && !is_quit)
+ direct_waitqueue_wait( &response.wait_put, &response.lock );
+
+ direct_mutex_unlock( &response.lock );
+}
+
+/**************************************************************************************************/
+
+DirectResult
+VoodooManager::lock_response( VoodooMessageSerial request,
+ VoodooResponseMessage **ret_response )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ VoodooResponseMessage *msg = NULL;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( ret_response != NULL );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Locking response to request %llu...\n", (unsigned long long)request );
+
+ direct_mutex_lock( &response.lock );
+
+ while (!is_quit) {
+ msg = response.current;
+ if (msg && msg->request == request)
+ break;
+
+ if (msg)
+ D_DEBUG_AT( Voodoo_Manager, " -> ...current response is for request %llu...\n", (unsigned long long)msg->request );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> ...(still) waiting for response to request %llu...\n", (unsigned long long)request );
+
+ direct_waitqueue_wait( &response.wait_get, &response.lock );
+ }
+
+ if (is_quit) {
+ D_ERROR( "Voodoo/Manager: Quit while waiting for response!\n" );
+ direct_mutex_unlock( &response.lock );
+ return DR_DESTROYED;
+ }
+
+ D_DEBUG_AT( Voodoo_Manager, " -> ...locked response %llu to request %llu (%d bytes).\n",
+ (unsigned long long)msg->header.serial, (unsigned long long)request, msg->header.size );
+
+ *ret_response = msg;
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::unlock_response( VoodooResponseMessage *msg )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( msg != NULL );
+ D_ASSERT( msg == response.current );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Unlocking response %llu to request %llu (%d bytes)...\n",
+ (unsigned long long)msg->header.serial, (unsigned long long)msg->request, msg->header.size );
+
+ response.current = NULL;
+
+ direct_mutex_unlock( &response.lock );
+
+ direct_waitqueue_broadcast( &response.wait_put );
+
+ return DR_OK;
+}
+
+
+
+
+DirectResult
+VoodooManager::do_super( const char *name,
+ VoodooInstanceID *ret_instance )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ DirectResult ret;
+ int len;
+ int size;
+ VoodooPacket *packet;
+ VoodooMessageSerial serial;
+ VoodooSuperMessage *msg;
+ VoodooResponseMessage *response;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( name != NULL );
+ D_ASSERT( ret_instance != NULL );
+
+ if (is_quit) {
+ D_DEBUG_AT( Voodoo_Manager, " -> QUIT!\n" );
+ return DR_IO;
+ }
+
+ /* Calculate the total message size. */
+ len = strlen( name ) + 1;
+ size = sizeof(VoodooSuperMessage) + len;
+
+
+ /* Lock the output buffer for direct writing. */
+ packet = connection->GetPacket( size );
+ if (!packet)
+ return DR_FAILURE;
+
+ msg = (VoodooSuperMessage*) packet->data_raw();
+
+ serial = msg_serial++;
+
+ /* Fill message header. */
+ msg->header.size = size;
+ msg->header.serial = serial;
+ msg->header.type = VMSG_SUPER;
+
+ /* Append the name of the super interface to create. */
+ direct_memcpy( msg + 1, name, len );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Sending SUPER message %llu for '%s' (%d bytes).\n", (unsigned long long)serial, name, size );
+
+ /* Unlock the output buffer. */
+ connection->PutPacket( packet, true );
+
+
+ /* Wait for and lock the response buffer. */
+ ret = lock_response( serial, &response );
+ if (ret) {
+ D_ERROR( "Voodoo/Manager: "
+ "Waiting for the response failed (%s)!\n", DirectResultString( ret ) );
+ return ret;
+ }
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Got response %llu (%s) with instance %u for request %llu "
+ "(%d bytes).\n", (unsigned long long)response->header.serial, DirectResultString( ret ),
+ response->instance, (unsigned long long)response->request, response->header.size );
+
+ ret = response->result;
+ if (ret) {
+ D_ERROR( "Voodoo/Manager: Could not create remote super interface '%s' (%s)!\n",
+ name, DirectResultString( ret ) );
+ unlock_response( response );
+ return ret;
+ }
+
+ D_INFO( "Voodoo/Manager: Created remote super interface '%s'.\n", name );
+
+ /* Return the new instance ID. */
+ *ret_instance = response->instance;
+
+ /* Unlock the response buffer. */
+ unlock_response( response );
+
+ return DR_OK;
+}
+
+void
+VoodooManager::write_blocks( void *dst,
+ const VoodooMessageBlock *blocks,
+ size_t num )
+{
+ size_t i;
+ u32 *d32 = (u32*) dst;
+
+ for (i=0; i<num; i++) {
+ /* Write block type and length. */
+ d32[0] = blocks[i].type;
+ d32[1] = blocks[i].len;
+
+ /* Write block content. */
+ if (blocks[i].ptr) {
+ u32 *s32 = (u32*) blocks[i].ptr;
+
+ switch (blocks[i].len) {
+ case 16:
+ d32[5] = s32[3];
+ case 12:
+ d32[4] = s32[2];
+ case 8:
+ d32[3] = s32[1];
+ case 4:
+ d32[2] = s32[0];
+ break;
+
+ default:
+ direct_memcpy( &d32[2], blocks[i].ptr, blocks[i].len );
+ }
+ }
+ else if (blocks[i].len) {
+ D_ASSERT( blocks[i].len == 4 );
+
+ d32[2] = blocks[i].val;
+ }
+
+ /* Advance message data pointer. */
+ d32 += 2 + (VOODOO_MSG_ALIGN(blocks[i].len) >> 2);
+ }
+
+ /* Write terminator. */
+ d32[0] = VMBT_NONE;
+}
+
+DirectResult
+VoodooManager::do_request( VoodooInstanceID instance,
+ VoodooMethodID method,
+ VoodooRequestFlags flags,
+ VoodooResponseMessage **ret_response,
+ VoodooMessageBlock *blocks,
+ size_t num_blocks,
+ size_t data_size )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ DirectResult ret;
+ size_t size;
+ VoodooPacket *packet;
+ VoodooMessageSerial serial;
+ VoodooRequestMessage *msg;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( instance != VOODOO_INSTANCE_NONE );
+ D_ASSERT( ret_response != NULL || !(flags & VREQ_RESPOND) );
+ D_ASSUME( (flags & (VREQ_RESPOND | VREQ_QUEUE)) != (VREQ_RESPOND | VREQ_QUEUE) );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Instance %u, method %u, flags 0x%08x...\n", instance, method, flags );
+
+ if (is_quit) {
+ D_DEBUG_AT( Voodoo_Manager, " -> QUIT!\n" );
+ return DR_IO;
+ }
+
+ /* Calculate the total message size. */
+ size = sizeof(VoodooRequestMessage) + data_size;
+
+ D_DEBUG_AT( Voodoo_Manager, " -> complete message size: %d\n", size );
+
+ /* Lock the output buffer for direct writing. */
+ packet = connection->GetPacket( size );
+ if (!packet)
+ return DR_FAILURE;
+
+ msg = (VoodooRequestMessage*) packet->data_raw();
+
+ serial = msg_serial++;
+
+ /* Fill message header. */
+ msg->header.size = size;
+ msg->header.serial = serial;
+ msg->header.type = VMSG_REQUEST;
+
+ /* Fill message body. */
+ msg->instance = instance;
+ msg->method = method;
+ msg->flags = flags;
+
+ /* Append custom data. */
+ write_blocks( msg + 1, blocks, num_blocks );
+
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Sending REQUEST message %llu to %u::%u %s(%d bytes).\n",
+ (unsigned long long)serial, instance, method, (flags & VREQ_RESPOND) ? "[RESPONDING] " : "", size );
+
+ /* Unlock the output buffer. */
+ connection->PutPacket( packet, !(flags & VREQ_QUEUE) );
+
+ /* Wait for and lock the response buffer. */
+ if (flags & VREQ_RESPOND) {
+ VoodooResponseMessage *response;
+
+ ret = lock_response( serial, &response );
+ if (ret) {
+ D_ERROR( "Voodoo/Manager: "
+ "Waiting for the response failed (%s)!\n", DirectResultString( ret ) );
+ return ret;
+ }
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Got response %llu (%s) with instance %u for request %llu "
+ "(%d bytes).\n", (unsigned long long)response->header.serial, DirectResultString( response->result ),
+ response->instance, (unsigned long long)response->request, response->header.size );
+
+ *ret_response = response;
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::next_response( VoodooResponseMessage *response,
+ VoodooResponseMessage **ret_response )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ DirectResult ret;
+ VoodooMessageSerial serial;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( response != NULL );
+
+ serial = response->request;
+
+ /* Unlock the response buffer. */
+ unlock_response( response );
+
+ ret = lock_response( serial, &response );
+ if (ret) {
+ D_ERROR( "Voodoo/Manager: "
+ "Waiting for the response failed (%s)!\n", DirectResultString( ret ) );
+ return ret;
+ }
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Got response %llu (%s) with instance %u for request %llu "
+ "(%d bytes).\n", (unsigned long long)response->header.serial, DirectResultString( response->result ),
+ response->instance, (unsigned long long)response->request, response->header.size );
+
+ *ret_response = response;
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::finish_request( VoodooResponseMessage *response )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( response != NULL );
+
+ /* Unlock the response buffer. */
+ return unlock_response( response );
+}
+
+DirectResult
+VoodooManager::do_respond( bool flush,
+ VoodooMessageSerial request,
+ DirectResult result,
+ VoodooInstanceID instance,
+ VoodooMessageBlock *blocks,
+ size_t num_blocks,
+ size_t data_size )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ size_t size;
+ VoodooPacket *packet;
+ VoodooMessageSerial serial;
+ VoodooResponseMessage *msg;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Request %llu, result %d, instance %u...\n", (unsigned long long)request, result, instance );
+
+ if (is_quit) {
+ D_DEBUG_AT( Voodoo_Manager, " -> QUIT!\n" );
+ return DR_IO;
+ }
+
+ /* Calculate the total message size. */
+ size = sizeof(VoodooResponseMessage) + data_size;
+
+ D_DEBUG_AT( Voodoo_Manager, " -> complete message size: %d\n", size );
+
+
+ /* Lock the output buffer for direct writing. */
+ packet = connection->GetPacket( size );
+ if (!packet)
+ return DR_FAILURE;
+
+ msg = (VoodooResponseMessage*) packet->data_raw();
+
+ serial = msg_serial++;
+
+ /* Fill message header. */
+ msg->header.size = size;
+ msg->header.serial = serial;
+ msg->header.type = VMSG_RESPONSE;
+
+ /* Fill message body. */
+ msg->request = request;
+ msg->result = result;
+ msg->instance = instance;
+
+ /* Append custom data. */
+ write_blocks( msg + 1, blocks, num_blocks );
+
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Sending RESPONSE message %llu (%s) with instance %u for request %llu (%d bytes).\n",
+ (unsigned long long)serial, DirectResultString( result ), instance, (unsigned long long)request, size );
+
+ /* Unlock the output buffer. */
+ connection->PutPacket( packet, flush );
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::register_local( VoodooInstance *instance,
+ VoodooInstanceID *ret_instance )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ VoodooInstanceID instance_id;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( instance != NULL );
+ D_ASSERT( ret_instance != NULL );
+
+ instance->AddRef();
+
+ direct_mutex_lock( &instances.lock );
+
+ instance_id = ++instances.last;
+
+ instances.local[instance_id] = instance;
+
+ direct_mutex_unlock( &instances.lock );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Added local instance %u (%p)\n", instance_id, instance );
+
+ *ret_instance = instance_id;
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::unregister_local( VoodooInstanceID instance_id )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+
+ direct_mutex_lock( &instances.lock );
+
+ InstanceMap::iterator itr = instances.local.find( instance_id );
+
+ if (itr == instances.local.end()) {
+ direct_mutex_unlock( &instances.lock );
+ return DR_NOSUCHINSTANCE;
+ }
+
+ instance = (*itr).second;
+
+ instances.local.erase( itr );
+
+ direct_mutex_unlock( &instances.lock );
+
+ instance->Release();
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::lookup_local( VoodooInstanceID instance_id,
+ VoodooInstance **ret_instance )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( instance_id != VOODOO_INSTANCE_NONE );
+ D_ASSERT( ret_instance != NULL );
+
+ direct_mutex_lock( &instances.lock );
+
+ InstanceMap::iterator itr = instances.local.find( instance_id );
+
+ direct_mutex_unlock( &instances.lock );
+
+ if (itr == instances.local.end())
+ return DR_NOSUCHINSTANCE;
+
+ instance = (*itr).second;
+
+ // FIXME: addref?
+
+ *ret_instance = instance;
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::register_remote( VoodooInstance *instance,
+ VoodooInstanceID instance_id )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( instance != NULL );
+ D_ASSERT( instance_id != VOODOO_INSTANCE_NONE );
+
+ instance->AddRef();
+
+ direct_mutex_lock( &instances.lock );
+
+ instances.remote[instance_id] = instance;
+
+ direct_mutex_unlock( &instances.lock );
+
+ D_DEBUG_AT( Voodoo_Manager, " -> Added remote instance %u (%p)\n", instance_id, instance );
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::unregister_remote( VoodooInstanceID instance_id )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+
+ direct_mutex_lock( &instances.lock );
+
+ InstanceMap::iterator itr = instances.remote.find( instance_id );
+
+ if (itr == instances.remote.end()) {
+ direct_mutex_unlock( &instances.lock );
+ return DR_NOSUCHINSTANCE;
+ }
+
+ instance = (*itr).second;
+
+ instances.remote.erase( itr );
+
+ direct_mutex_unlock( &instances.lock );
+
+ instance->Release();
+
+ return DR_OK;
+}
+
+DirectResult
+VoodooManager::lookup_remote( VoodooInstanceID instance_id,
+ VoodooInstance **ret_instance )
+{
+ D_DEBUG_AT( Voodoo_Manager, "VoodooManager::%s( %p )\n", __func__, this );
+
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( this, VoodooManager );
+ D_ASSERT( instance_id != VOODOO_INSTANCE_NONE );
+ D_ASSERT( ret_instance != NULL );
+
+ direct_mutex_lock( &instances.lock );
+
+ InstanceMap::iterator itr = instances.remote.find( instance_id );
+
+ direct_mutex_unlock( &instances.lock );
+
+ if (itr == instances.remote.end())
+ return DR_NOSUCHINSTANCE;
+
+ instance = (*itr).second;
+
+ // FIXME: addref?
+
+ *ret_instance = instance;
+
+ return DR_OK;
+}
+
+//}
+
diff --git a/Source/DirectFB/lib/voodoo/manager.h b/Source/DirectFB/lib/voodoo/manager.h
new file mode 100755
index 0000000..ae3189b
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/manager.h
@@ -0,0 +1,279 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__MANAGER_H__
+#define __VOODOO__MANAGER_H__
+
+#include <voodoo/types.h>
+#include <voodoo/message.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#include <direct/interface.h>
+#include <direct/thread.h>
+}
+
+#include <map>
+
+#include <voodoo/instance.h>
+
+
+typedef struct {
+ VoodooMessageBlockType type;
+ unsigned int len;
+ void *ptr;
+ u32 val;
+} VoodooMessageBlock;
+
+
+typedef std::map<VoodooInstanceID,VoodooInstance*> InstanceMap;
+
+
+class VoodooDispatcher;
+
+
+class VoodooContext {
+public:
+ virtual DirectResult HandleSuper( VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance ) = 0;
+};
+
+
+class VoodooManager {
+public:
+ int magic;
+
+ bool is_quit;
+
+private:
+ friend class VoodooDispatcher;
+
+ VoodooLink *link;
+ VoodooConnection *connection;
+
+ VoodooContext *context;
+
+ size_t msg_count;
+ VoodooMessageSerial msg_serial;
+
+ struct {
+ DirectMutex lock;
+ InstanceMap local;
+ InstanceMap remote;
+ VoodooInstanceID last;
+ } instances;
+
+ struct {
+ DirectMutex lock;
+ DirectWaitQueue wait_get;
+ DirectWaitQueue wait_put;
+ VoodooResponseMessage *current;
+ } response;
+
+
+ VoodooDispatcher *dispatcher;
+
+
+
+public:
+ VoodooManager( VoodooLink *link,
+ VoodooContext *context );
+ ~VoodooManager();
+
+
+ /** New API **/
+
+ void DispatchPacket ( VoodooPacket *packet );
+ bool DispatchReady (); // FIXME: will be obsolete with GetPacket() method, called by connection code to read directly into packet
+
+
+
+ /** Old API **/
+
+ void quit ();
+
+
+ void handle_disconnect ();
+ void handle_super ( VoodooSuperMessage *super );
+
+ void handle_request ( VoodooRequestMessage *request );
+ void handle_response ( VoodooResponseMessage *response );
+
+
+private:
+ static void *dispatch_async_thread( DirectThread *thread,
+ void *arg );
+
+
+
+
+public:
+ DirectResult do_super ( const char *name,
+ VoodooInstanceID *ret_instance );
+
+ DirectResult do_request ( VoodooInstanceID instance,
+ VoodooMethodID method,
+ VoodooRequestFlags flags,
+ VoodooResponseMessage **ret_response,
+ VoodooMessageBlock *blocks = NULL,
+ size_t num_blocks = 0,
+ size_t data_size = 0 );
+
+ DirectResult next_response ( VoodooResponseMessage *response,
+ VoodooResponseMessage **ret_response );
+
+ DirectResult finish_request ( VoodooResponseMessage *response );
+
+ DirectResult do_respond ( bool flush,
+ VoodooMessageSerial request,
+ DirectResult result,
+ VoodooInstanceID instance = VOODOO_INSTANCE_NONE,
+ VoodooMessageBlock *blocks = NULL,
+ size_t num_blocks = 0,
+ size_t data_size = 0 );
+
+private:
+ inline void write_blocks ( void *dst,
+ const VoodooMessageBlock *blocks,
+ size_t num_blocks );
+
+ DirectResult lock_response ( VoodooMessageSerial request,
+ VoodooResponseMessage **ret_response );
+
+ DirectResult unlock_response ( VoodooResponseMessage *response );
+
+
+public:
+ DirectResult register_local ( VoodooInstance *instance,
+ VoodooInstanceID *ret_instance );
+
+ DirectResult unregister_local ( VoodooInstanceID instance_id );
+
+ DirectResult lookup_local ( VoodooInstanceID instance_id,
+ VoodooInstance **ret_instance );
+
+ DirectResult register_remote ( VoodooInstance *instance,
+ VoodooInstanceID instance_id );
+
+ DirectResult unregister_remote ( VoodooInstanceID instance_id );
+
+ DirectResult lookup_remote ( VoodooInstanceID instance_id,
+ VoodooInstance **ret_instance );
+};
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DirectResult VOODOO_API voodoo_manager_create ( VoodooLink *link,
+ VoodooClient *client,
+ VoodooServer *server,
+ VoodooManager **ret_manager );
+
+DirectResult VOODOO_API voodoo_manager_quit ( VoodooManager *manager );
+
+bool VOODOO_API voodoo_manager_is_closed ( const VoodooManager *manager );
+
+DirectResult VOODOO_API voodoo_manager_destroy ( VoodooManager *manager );
+
+
+/* Super */
+
+DirectResult VOODOO_API voodoo_manager_super ( VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance );
+
+
+/* Request */
+
+DirectResult VOODOO_API voodoo_manager_request ( VoodooManager *manager,
+ VoodooInstanceID instance,
+ VoodooMethodID method,
+ VoodooRequestFlags flags,
+ VoodooResponseMessage **ret_response, ... );
+
+DirectResult VOODOO_API voodoo_manager_next_response ( VoodooManager *manager,
+ VoodooResponseMessage *response,
+ VoodooResponseMessage **ret_response );
+
+DirectResult VOODOO_API voodoo_manager_finish_request ( VoodooManager *manager,
+ VoodooResponseMessage *response );
+
+
+/* Response */
+
+DirectResult VOODOO_API voodoo_manager_respond ( VoodooManager *manager,
+ bool flush,
+ VoodooMessageSerial request,
+ DirectResult result,
+ VoodooInstanceID instance, ... );
+
+
+/* Instances */
+
+DirectResult VOODOO_API voodoo_manager_register_local ( VoodooManager *manager,
+ VoodooInstanceID super,
+ void *dispatcher,
+ void *real,
+ VoodooDispatch dispatch,
+ VoodooInstanceID *ret_instance_id );
+
+DirectResult VOODOO_API voodoo_manager_unregister_local( VoodooManager *manager,
+ VoodooInstanceID instance_id );
+
+DirectResult VOODOO_API voodoo_manager_lookup_local ( VoodooManager *manager,
+ VoodooInstanceID instance,
+ void **ret_dispatcher,
+ void **ret_real );
+
+DirectResult VOODOO_API voodoo_manager_register_remote( VoodooManager *manager,
+ bool super,
+ void *requestor,
+ VoodooInstanceID instance );
+
+DirectResult VOODOO_API voodoo_manager_lookup_remote ( VoodooManager *manager,
+ VoodooInstanceID instance,
+ void **ret_requestor );
+
+
+/* Security */
+
+DirectResult VOODOO_API voodoo_manager_check_allocation( VoodooManager *manager,
+ unsigned int amount );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/manager_c.cpp b/Source/DirectFB/lib/voodoo/manager_c.cpp
new file mode 100755
index 0000000..7019da8
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/manager_c.cpp
@@ -0,0 +1,553 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <list>
+
+#include <stdarg.h>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/server.h>
+}
+
+#include <voodoo/manager.h>
+
+
+D_DEBUG_DOMAIN( Voodoo_Manager, "Voodoo/Manager", "Voodoo Manager" );
+
+/**********************************************************************************************************************/
+
+
+#define VOODOO_MANAGER_MESSAGE_BLOCKS_MAX 20
+
+static __inline__ int
+calc_blocks( va_list args,
+ VoodooMessageBlock *ret_blocks, size_t *ret_num )
+{
+ int size = 4; /* for the terminating VMBT_NONE */
+ size_t num = 0;
+ VoodooMessageBlockType type;
+
+ /* Fetch first block type. */
+ type = (VoodooMessageBlockType) va_arg( args, int );
+
+ while (type != VMBT_NONE) {
+ if (num == VOODOO_MANAGER_MESSAGE_BLOCKS_MAX) {
+ // FIXME: support more blocks?
+ D_UNIMPLEMENTED();
+ break;
+ }
+
+ /* Set message block type. */
+ ret_blocks[num].type = type;
+
+ switch (type) {
+ case VMBT_ID:
+ ret_blocks[num].len = 4;
+ ret_blocks[num].ptr = NULL;
+ ret_blocks[num].val = va_arg( args, u32 );
+
+ D_DEBUG( "Voodoo/Message: + ID %u\n", ret_blocks[num].val );
+ break;
+
+ case VMBT_INT:
+ ret_blocks[num].len = 4;
+ ret_blocks[num].ptr = NULL;
+ ret_blocks[num].val = va_arg( args, s32 );
+
+ D_DEBUG( "Voodoo/Message: + INT %d\n", ret_blocks[num].val );
+ break;
+
+ case VMBT_UINT:
+ ret_blocks[num].len = 4;
+ ret_blocks[num].ptr = NULL;
+ ret_blocks[num].val = va_arg( args, u32 );
+
+ D_DEBUG( "Voodoo/Message: + UINT %u\n", ret_blocks[num].val );
+ break;
+
+ case VMBT_DATA:
+ ret_blocks[num].len = va_arg( args, int );
+ ret_blocks[num].ptr = va_arg( args, void * );
+
+// D_ASSERT( ret_blocks[num].len > 0 );
+ D_ASSERT( ret_blocks[num].ptr != NULL );
+
+ D_DEBUG( "Voodoo/Message: + DATA at %p with length %d\n", ret_blocks[num].ptr, ret_blocks[num].len );
+ break;
+
+ case VMBT_ODATA:
+ ret_blocks[num].len = va_arg( args, int );
+ ret_blocks[num].ptr = va_arg( args, void * );
+
+ D_ASSERT( ret_blocks[num].len > 0 );
+
+ D_DEBUG( "Voodoo/Message: + ODATA at %p with length %d\n", ret_blocks[num].ptr, ret_blocks[num].len );
+
+ if (!ret_blocks[num].ptr)
+ ret_blocks[num].len = 0;
+ break;
+
+ case VMBT_STRING:
+ ret_blocks[num].ptr = va_arg( args, char * );
+ ret_blocks[num].len = strlen( (const char*) ret_blocks[num].ptr ) + 1;
+
+ D_ASSERT( ret_blocks[num].ptr != NULL );
+
+ D_DEBUG( "Voodoo/Message: + STRING '%s' at %p with length %d\n", (char*) ret_blocks[num].ptr, ret_blocks[num].ptr, ret_blocks[num].len );
+ break;
+
+ default:
+ D_BREAK( "unknown message block type" );
+ }
+
+ /* Fetch next block type. */
+ type = (VoodooMessageBlockType) va_arg( args, int );
+
+ size += 8 + VOODOO_MSG_ALIGN(ret_blocks[num].len);
+
+ num++;
+ }
+
+ *ret_num = num;
+
+ return size;
+}
+
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+/* Old C API
+ */
+
+/*
+
+
+register add refs proxy
+unregister releases proxy
+
+proxy destruct releases real
+
+*/
+
+class VoodooInstanceInterface : public VoodooInstance {
+public:
+ VoodooManager *manager;
+ VoodooInstance *super;
+ IAny *proxy;
+ IAny *real;
+ VoodooDispatch dispatch;
+
+
+ static std::list<VoodooInstanceInterface*> interfaces;
+
+
+public:
+ VoodooInstanceInterface( VoodooManager *manager,
+ VoodooInstance *super,
+ IAny *proxy,
+ IAny *real,
+ VoodooDispatch dispatch )
+ :
+ manager( manager ),
+ super( super ),
+ proxy( proxy ),
+ real( real ),
+ dispatch( dispatch )
+ {
+ D_DEBUG_AT( Voodoo_Manager, "VoodooInstanceInterface::%s( %p, manager %p, super %p, proxy %p, real %p, dispatch %p )\n",
+ __func__, this, manager, super, proxy, real, dispatch );
+
+ if (super)
+ super->AddRef();
+
+ interfaces.push_back( this );
+ }
+
+protected:
+ virtual ~VoodooInstanceInterface()
+ {
+ D_DEBUG_AT( Voodoo_Manager, "VoodooInstanceInterface::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ if (proxy) {
+ D_DEBUG_AT( Voodoo_Manager, " -> releasing proxy interface\n" );
+
+ proxy->Release( proxy );
+ }
+
+
+ if (super) {
+ D_DEBUG_AT( Voodoo_Manager, " -> releasing super instance\n" );
+
+ super->Release();
+ }
+
+ interfaces.remove( this );
+ }
+
+public:
+ virtual DirectResult
+ Dispatch( VoodooManager *manager,
+ VoodooRequestMessage *msg )
+ {
+ D_DEBUG_AT( Voodoo_Manager, "VoodooInstanceInterface::%s( %p, manager %p, msg %p )\n", __func__, this, manager, msg );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ D_ASSERT( dispatch != NULL );
+
+ return dispatch( proxy, real, manager, msg );
+ }
+};
+
+std::list<VoodooInstanceInterface*> VoodooInstanceInterface::interfaces;
+
+/**********************************************************************************************************************/
+
+class VoodooContextClassic : public VoodooContext {
+private:
+ VoodooServer *server;
+
+public:
+ VoodooContextClassic( VoodooServer *server )
+ :
+ server( server )
+ {
+ }
+
+ virtual DirectResult
+ HandleSuper( VoodooManager *manager, const char *name, VoodooInstanceID *ret_instance )
+ {
+ return voodoo_server_construct( server, manager, name, ret_instance );
+ }
+};
+
+DirectResult
+voodoo_manager_create( VoodooLink *link,
+ VoodooClient *client,
+ VoodooServer *server,
+ VoodooManager **ret_manager )
+{
+ D_ASSERT( ret_manager != NULL );
+
+ *ret_manager = new VoodooManager( link, new VoodooContextClassic( server ) ); // FIXME: leak
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_quit( VoodooManager *manager )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ manager->quit();
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_destroy( VoodooManager *manager )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ delete manager;
+
+ for (std::list<VoodooInstanceInterface*>::const_iterator iter = VoodooInstanceInterface::interfaces.begin();
+ iter != VoodooInstanceInterface::interfaces.end(); iter++)
+ {
+ VoodooInstanceInterface *instance = *iter;
+
+ if (instance->manager == manager)
+ D_INFO( "Zombie: Instance %p, proxy %p, real %p, super %p\n", instance, instance->proxy, instance->real, instance->super );
+ }
+
+ return DR_OK;
+}
+
+bool
+voodoo_manager_is_closed( const VoodooManager *manager )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->is_quit;
+}
+
+/**************************************************************************************************/
+
+DirectResult
+voodoo_manager_super( VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->do_super( name, ret_instance );
+}
+
+DirectResult
+voodoo_manager_request( VoodooManager *manager,
+ VoodooInstanceID instance,
+ VoodooMethodID method,
+ VoodooRequestFlags flags,
+ VoodooResponseMessage **ret_response, ... )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ va_list ap;
+
+ va_start( ap, ret_response );
+
+
+ VoodooMessageBlock blocks[VOODOO_MANAGER_MESSAGE_BLOCKS_MAX];
+ size_t num_blocks;
+ size_t data_size;
+
+ data_size = calc_blocks( ap, blocks, &num_blocks );
+
+
+ ret = manager->do_request( instance, method, flags, ret_response, blocks, num_blocks, data_size );
+
+ va_end( ap );
+
+ return ret;
+}
+
+DirectResult
+voodoo_manager_next_response( VoodooManager *manager,
+ VoodooResponseMessage *response,
+ VoodooResponseMessage **ret_response )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->next_response( response, ret_response );
+}
+
+DirectResult
+voodoo_manager_finish_request( VoodooManager *manager,
+ VoodooResponseMessage *response )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->finish_request( response );
+}
+
+DirectResult
+voodoo_manager_respond( VoodooManager *manager,
+ bool flush,
+ VoodooMessageSerial request,
+ DirectResult result,
+ VoodooInstanceID instance, ... )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ va_list ap;
+
+ va_start( ap, instance );
+
+
+ VoodooMessageBlock blocks[VOODOO_MANAGER_MESSAGE_BLOCKS_MAX];
+ size_t num_blocks;
+ size_t data_size;
+
+ data_size = calc_blocks( ap, blocks, &num_blocks );
+
+
+ ret = manager->do_respond( flush, request, result, instance, blocks, num_blocks, data_size );
+
+ va_end( ap );
+
+ return ret;
+}
+
+DirectResult
+voodoo_manager_register_local( VoodooManager *manager,
+ VoodooInstanceID super,
+ void *dispatcher,
+ void *real,
+ VoodooDispatch dispatch,
+ VoodooInstanceID *ret_instance )
+{
+ DirectResult ret;
+ VoodooInstance *super_instance = NULL;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ if (super != VOODOO_INSTANCE_NONE) {
+ ret = manager->lookup_local( super, &super_instance );
+ if (ret) {
+ D_DERROR( ret, "Voodoo/Manager: Could not lookup super instance %u!\n", super );
+ return ret;
+ }
+ }
+
+
+ VoodooInstanceInterface *instance = new VoodooInstanceInterface( manager, super_instance, (IAny*) dispatcher, (IAny*) real, dispatch );
+
+ ret = manager->register_local( instance, ret_instance );
+
+ instance->Release();
+
+ return ret;
+}
+
+DirectResult
+voodoo_manager_unregister_local( VoodooManager *manager,
+ VoodooInstanceID instance_id )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->unregister_local( instance_id );
+}
+
+DirectResult
+voodoo_manager_lookup_local( VoodooManager *manager,
+ VoodooInstanceID instance_id,
+ void **ret_dispatcher,
+ void **ret_real )
+{
+ DirectResult ret;
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ ret = manager->lookup_local( instance_id, &instance );
+ if (ret)
+ return ret;
+
+ if (ret_dispatcher)
+ *ret_dispatcher = ((VoodooInstanceInterface*) instance)->proxy;
+
+ if (ret_real)
+ *ret_real = ((VoodooInstanceInterface*) instance)->real;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_register_remote( VoodooManager *manager,
+ bool super,
+ void *requestor,
+ VoodooInstanceID instance_id )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ VoodooInstanceInterface *instance = new VoodooInstanceInterface( manager, NULL, (IAny*) requestor, NULL, NULL);
+
+ ret = manager->register_remote( instance, instance_id );
+
+ instance->Release();
+
+ return ret;
+}
+
+
+DirectResult
+voodoo_manager_lookup_remote( VoodooManager *manager,
+ VoodooInstanceID instance_id,
+ void **ret_requestor )
+{
+ DirectResult ret;
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ ret = manager->lookup_remote( instance_id, &instance );
+ if (ret)
+ return ret;
+
+ if (ret_requestor)
+ *ret_requestor = ((VoodooInstanceInterface*) instance)->proxy;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_check_allocation( VoodooManager *manager,
+ unsigned int amount )
+{
+#ifndef WIN32
+ FILE *f;
+ char buf[2000];
+ int size;
+ char *p;
+ size_t bytes;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ if (!voodoo_config->memory_max)
+ return DR_OK;
+
+ direct_snprintf( buf, sizeof(buf), "/proc/%d/status", direct_getpid() );
+
+ f = fopen( buf, "r" );
+ if (!f) {
+ D_ERROR( "Could not open '%s'!\n", buf );
+ return DR_FAILURE;
+ }
+
+ bytes = fread( buf, 1, sizeof(buf)-1, f );
+
+ fclose( f );
+
+ if (bytes) {
+ buf[bytes] = 0;
+
+ p = strstr( buf, "VmRSS:" );
+ if (!p) {
+ D_ERROR( "Could not find memory information!\n" );
+ return DR_FAILURE;
+ }
+
+ sscanf( p + 6, " %u", &size );
+
+ D_INFO( "SIZE: %u kB (+%u kB)\n", size, amount / 1024 );
+
+ if (size * 1024 + amount > voodoo_config->memory_max)
+ return DR_LIMITEXCEEDED;
+ }
+#endif
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/message.h b/Source/DirectFB/lib/voodoo/message.h
new file mode 100755
index 0000000..514b3bc
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/message.h
@@ -0,0 +1,258 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__MESSAGE_H__
+#define __VOODOO__MESSAGE_H__
+
+#include <voodoo/types.h>
+
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+
+
+#define VOODOO_MSG_ALIGN(i) (((i) + 3) & ~3)
+
+typedef enum {
+ VMBT_NONE,
+ VMBT_ID,
+ VMBT_INT,
+ VMBT_UINT,
+ VMBT_DATA,
+ VMBT_ODATA,
+ VMBT_STRING
+} VoodooMessageBlockType;
+
+typedef enum {
+ VREQ_NONE = 0x00000000,
+ VREQ_RESPOND = 0x00000001,
+ VREQ_ASYNC = 0x00000002,
+ VREQ_QUEUE = 0x00000004
+} VoodooRequestFlags;
+
+typedef enum {
+ VMSG_SUPER,
+ VMSG_REQUEST,
+ VMSG_RESPONSE,
+
+ VMSG_DISCOVER, // temporary solution for compatibility
+ VMSG_SENDINFO, // temporary solution for compatibility
+} VoodooMessageType;
+
+
+struct __V_VoodooMessageHeader {
+ int size;
+ VoodooMessageSerial serial;
+ u32 type;
+};
+
+
+struct __V_VoodooSuperMessage {
+ VoodooMessageHeader header;
+};
+
+struct __V_VoodooRequestMessage {
+ VoodooMessageHeader header;
+
+ VoodooInstanceID instance;
+ VoodooMethodID method;
+
+ u32 flags;
+};
+
+struct __V_VoodooResponseMessage {
+ VoodooMessageHeader header;
+
+ VoodooMessageSerial request;
+ DirectResult result;
+
+ VoodooInstanceID instance;
+};
+
+
+typedef struct {
+ int magic;
+
+ const void *msg;
+ const void *ptr;
+} VoodooMessageParser;
+
+
+
+#define __VOODOO_PARSER_PROLOG( parser, req_type ) \
+ const void *_vp_ptr; \
+ VoodooMessageBlockType _vp_type; \
+ int _vp_length; \
+ \
+ D_MAGIC_ASSERT( &(parser), VoodooMessageParser ); \
+ \
+ _vp_ptr = (parser).ptr; \
+ \
+ /* Read message block type. */ \
+ _vp_type = *(const u32*) _vp_ptr; \
+ \
+ D_ASSERT( _vp_type == (req_type) ); \
+ \
+ /* Read data block length. */ \
+ _vp_length = *(const s32*) (_vp_ptr + 4)
+
+
+#define __VOODOO_PARSER_EPILOG( parser ) \
+ /* Advance message data pointer. */ \
+ (parser).ptr += 8 + VOODOO_MSG_ALIGN(_vp_length)
+
+
+#define VOODOO_PARSER_BEGIN( parser, message ) \
+ do { \
+ const VoodooMessageHeader *_vp_header = (const VoodooMessageHeader *) (message); \
+ \
+ D_ASSERT( (message) != NULL ); \
+ D_ASSERT( _vp_header->type == VMSG_REQUEST || _vp_header->type == VMSG_RESPONSE ); \
+ \
+ (parser).msg = (message); \
+ (parser).ptr = (parser).msg + (_vp_header->type == VMSG_REQUEST ? \
+ sizeof(VoodooRequestMessage) : sizeof(VoodooResponseMessage)); \
+ \
+ D_MAGIC_SET_ONLY( &(parser), VoodooMessageParser ); \
+ } while (0)
+
+
+#define VOODOO_PARSER_GET_ID( parser, ret_id ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_ID ); \
+ \
+ D_ASSERT( _vp_length == 4 ); \
+ \
+ /* Read the ID. */ \
+ (ret_id) = *(const u32*) (_vp_ptr + 8); \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_GET_INT( parser, ret_int ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_INT ); \
+ \
+ D_ASSERT( _vp_length == 4 ); \
+ \
+ /* Read the integer. */ \
+ (ret_int) = *(const s32*) (_vp_ptr + 8); \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_GET_UINT( parser, ret_uint ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_UINT ); \
+ \
+ D_ASSERT( _vp_length == 4 ); \
+ \
+ /* Read the unsigned integer. */ \
+ (ret_uint) = *(const u32*) (_vp_ptr + 8); \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_GET_DATA( parser, ret_data ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_DATA ); \
+ \
+ D_ASSERT( _vp_length > 0 ); \
+ \
+ /* Return pointer to data. */ \
+ (ret_data) = _vp_ptr + 8; \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_READ_DATA( parser, dst, max_len ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_DATA ); \
+ \
+ D_ASSERT( _vp_length > 0 ); \
+ D_ASSERT( _vp_length <= max_len ); \
+ \
+ /* Copy data block. */ \
+ direct_memcpy( (dst), _vp_ptr + 8, _vp_length ); \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_COPY_DATA( parser, ret_data ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_DATA ); \
+ \
+ D_ASSERT( _vp_length > 0 ); \
+ \
+ /* Allocate memory on the stack. */ \
+ (ret_data) = alloca( _vp_length ); \
+ \
+ /* Copy data block. */ \
+ direct_memcpy( (ret_data), _vp_ptr + 8, _vp_length ); \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_GET_ODATA( parser, ret_data ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_ODATA ); \
+ \
+ D_ASSERT( _vp_length >= 0 ); \
+ \
+ /* Return pointer to data or NULL. */ \
+ if (_vp_length) \
+ (ret_data) = _vp_ptr + 8; \
+ else \
+ (ret_data) = NULL; \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+#define VOODOO_PARSER_GET_STRING( parser, ret_string ) \
+ do { \
+ __VOODOO_PARSER_PROLOG( parser, VMBT_STRING ); \
+ \
+ D_ASSERT( _vp_length > 0 ); \
+ \
+ /* Return pointer to string. */ \
+ (ret_string) = (const char*) (_vp_ptr + 8); \
+ \
+ __VOODOO_PARSER_EPILOG( parser ); \
+ } while (0)
+
+
+#define VOODOO_PARSER_END( parser ) \
+ do { \
+ D_MAGIC_ASSERT( &(parser), VoodooMessageParser ); \
+ \
+ D_ASSUME( *(const u32*) ((parser).ptr) == VMBT_NONE ); \
+ \
+ D_MAGIC_CLEAR( &(parser) ); \
+ } while (0)
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/mutex.c b/Source/DirectFB/lib/voodoo/mutex.c
new file mode 100755
index 0000000..dcc287d
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/mutex.c
@@ -0,0 +1,105 @@
+/*
+ (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/util.h>
+
+#include "mutex.h"
+
+/**********************************************************************************************************************/
+
+DirectResult
+direct_mutex_init( DirectMutex *mutex )
+{
+ if (pthread_mutex_init( &mutex->lock, NULL ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_recursive_mutex_init( DirectMutex *mutex )
+{
+ DirectResult ret = DR_OK;
+ int result;
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init( &attr );
+#if HAVE_DECL_PTHREAD_MUTEX_RECURSIVE
+ pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
+#endif
+ result = pthread_mutex_init( &mutex->lock, &attr );
+ if (result) {
+ ret = errno2result( errno );
+ D_PERROR( "Direct/Mutex: Could not initialize recursive mutex!\n" );
+ }
+
+ pthread_mutexattr_destroy( &attr );
+
+ return (DirectResult) ret;
+}
+
+__attribute__((no_instrument_function))
+DirectResult
+direct_mutex_lock( DirectMutex *mutex )
+{
+ if (pthread_mutex_lock( &mutex->lock ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+__attribute__((no_instrument_function))
+DirectResult
+direct_mutex_unlock( DirectMutex *mutex )
+{
+ if (pthread_mutex_unlock( &mutex->lock ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_mutex_trylock( DirectMutex *mutex )
+{
+ if (pthread_mutex_trylock( &mutex->lock ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+DirectResult
+direct_mutex_deinit( DirectMutex *mutex )
+{
+ if (pthread_mutex_destroy( &mutex->lock ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/mutex.h b/Source/DirectFB/lib/voodoo/mutex.h
new file mode 100755
index 0000000..fa520fd
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/mutex.h
@@ -0,0 +1,142 @@
+/*
+ (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__OS__LINUX__GLIBC__MUTEX_H__
+#define __DIRECT__OS__LINUX__GLIBC__MUTEX_H__
+
+#include <pthread.h>
+
+#include <direct/util.h>
+
+
+#define _ZU "%zu"
+#define _ZD "%zd"
+
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ pthread_mutex_t lock;
+} DirectMutex;
+
+/**********************************************************************************************************************/
+
+#define DIRECT_MUTEX_INITIALIZER(name) { PTHREAD_MUTEX_INITIALIZER }
+#define DIRECT_RECURSIVE_MUTEX_INITIALIZER(name) { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
+
+
+DirectResult direct_mutex_init ( DirectMutex *mutex );
+
+DirectResult direct_recursive_mutex_init ( DirectMutex *mutex );
+
+DirectResult direct_mutex_lock ( DirectMutex *mutex );
+
+DirectResult direct_mutex_unlock ( DirectMutex *mutex );
+
+DirectResult direct_mutex_trylock ( DirectMutex *mutex );
+
+DirectResult direct_mutex_deinit ( DirectMutex *mutex );
+
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+typedef struct {
+ pthread_key_t key;
+} DirectTLS;
+
+/**********************************************************************************************************************/
+
+#define DIRECT_TLS_DATA( name ) \
+ static DirectTLS name = { (pthread_key_t) -1 }
+
+/**********************************************************************************************************************/
+
+__attribute__((no_instrument_function))
+static inline void *direct_tls_get__( DirectTLS *tls );
+
+__attribute__((no_instrument_function))
+static inline DirectResult direct_tls_set__( DirectTLS *tls,
+ void *value );
+
+__attribute__((no_instrument_function))
+static inline DirectResult direct_tls_register( DirectTLS *tls,
+ void (*destructor)( void* ) );
+
+__attribute__((no_instrument_function))
+static inline DirectResult direct_tls_unregister( DirectTLS *tls );
+
+/**********************************************************************************************************************/
+
+#define direct_tls_get( name ) direct_tls_get__( &name )
+#define direct_tls_set( name, v ) direct_tls_set__( &name, v )
+
+/**********************************************************************************************************************/
+
+static inline void *
+direct_tls_get__( DirectTLS *tls )
+{
+ void *value;
+
+ value = pthread_getspecific( tls->key );
+
+ return value;
+}
+
+static inline DirectResult
+direct_tls_set__( DirectTLS *tls,
+ void *value )
+{
+ if (pthread_setspecific( tls->key, value ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_tls_register( DirectTLS *tls, void (*destructor)( void* ) )
+{
+ if (pthread_key_create( &tls->key, destructor ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_tls_unregister( DirectTLS *tls )
+{
+ if (pthread_key_delete( tls->key ))
+ return errno2result( errno );
+
+ tls->key = (pthread_key_t) -1;
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/packet.h b/Source/DirectFB/lib/voodoo/packet.h
new file mode 100755
index 0000000..3f97071
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/packet.h
@@ -0,0 +1,285 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__PACKET_H__
+#define __VOODOO__PACKET_H__
+
+extern "C" {
+#include <direct/fastlz.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+
+
+#include <voodoo/types.h>
+}
+
+
+typedef enum {
+ VPHF_NONE = 0x00000000,
+
+ VPHF_COMPRESSED = 0x00000001,
+
+ VPHF_ALL = 0x00000001
+} VoodooPacketHeaderFlags;
+
+
+typedef struct {
+ u32 size;
+ u32 flags;
+ u32 uncompressed;
+ u32 align;
+} VoodooPacketHeader;
+
+
+class VoodooPacket {
+public:
+ DirectLink link;
+ bool sending;
+
+private:
+ void *data;
+ void *current;
+ VoodooPacketHeader header;
+
+ VoodooPacket( u32 size,
+ void *data )
+ :
+ sending(false),
+ data(data),
+ current(data)
+ {
+ memset( &link, 0, sizeof(link) );
+
+ header.size = size;
+ header.flags = VPHF_NONE;
+ header.uncompressed = size;
+ }
+
+ VoodooPacket( u32 size,
+ u32 flags,
+ u32 uncompressed,
+ void *data )
+ :
+ sending(false),
+ data(data),
+ current(data)
+ {
+ memset( &link, 0, sizeof(link) );
+
+ header.size = size;
+ header.flags = VPHF_COMPRESSED;
+ header.uncompressed = uncompressed;
+ }
+
+ ~VoodooPacket() {};
+
+public:
+/*
+ static VoodooPacket *
+ New( u32 size )
+ {
+ VoodooPacket *packet = (VoodooPacket*) D_MALLOC( sizeof(VoodooPacket) + size );
+
+ if (!packet) {
+ D_OOM();
+ return NULL;
+ }
+
+ return new (packet) VoodooPacket( size, packet + 1 );
+
+
+ if (data)
+ this->data = data;
+ else
+ this->data = header + 1;
+ }
+*/
+ static VoodooPacket *
+ New( u32 size,
+ void *data )
+ {
+ return new VoodooPacket( size, data );
+ }
+
+ static VoodooPacket *
+ Reset( VoodooPacket *packet,
+ u32 size,
+ void *data )
+ {
+ return new (packet) VoodooPacket( size, data );
+ }
+
+ static VoodooPacket *
+ New( void *header,
+ u32 size )
+ {
+ VoodooPacketHeader *h = (VoodooPacketHeader*) header;
+
+ h->size = size;
+ h->flags = VPHF_NONE;
+ h->uncompressed = size;
+
+ return new VoodooPacket( size, (char*) header + sizeof(VoodooPacketHeader) );
+ }
+
+ static VoodooPacket *
+ New( u32 size )
+ {
+ VoodooPacket *p = (VoodooPacket*) D_MALLOC( sizeof(VoodooPacket) + VOODOO_PACKET_MAX );
+
+ if (!p) {
+ D_OOM();
+ return NULL;
+ }
+
+ return new (p) VoodooPacket( size, p + 1 );
+ }
+
+ static VoodooPacket *
+ Compressed( VoodooPacket *packet )
+ {
+ VoodooPacket *p = (VoodooPacket*) D_MALLOC( sizeof(VoodooPacket) + packet->header.size * 4 / 3 );
+
+ if (!p) {
+ D_OOM();
+ return NULL;
+ }
+
+ int compressed = direct_fastlz_compress( packet->data, packet->header.uncompressed, p + 1 );
+
+ if ((size_t) compressed < packet->header.uncompressed)
+ return new (p) VoodooPacket( compressed, VPHF_COMPRESSED, packet->header.uncompressed, p + 1 );
+
+ D_FREE( p );
+
+ return packet;
+ }
+
+ static VoodooPacket *
+ Copy( VoodooPacket *packet )
+ {
+ VoodooPacket *p = (VoodooPacket*) D_MALLOC( sizeof(VoodooPacket) + packet->header.size );
+
+ if (!p) {
+ D_OOM();
+ return NULL;
+ }
+
+ direct_memcpy( p + 1, packet->data_start(), packet->header.size );
+
+ return new (p) VoodooPacket( packet->header.size, packet->header.flags, packet->header.uncompressed, p + 1 );
+ }
+
+ static VoodooPacket *
+ Copy( u32 size,
+ u32 flags,
+ u32 uncompressed,
+ void *data )
+ {
+ VoodooPacket *p = (VoodooPacket*) D_MALLOC( sizeof(VoodooPacket) + size );
+
+ if (!p) {
+ D_OOM();
+ return NULL;
+ }
+
+ direct_memcpy( p + 1, data, size );
+
+ return new (p) VoodooPacket( size, flags, uncompressed, p + 1 );
+ }
+
+ inline u32
+ size() const
+ {
+ return header.size;
+ }
+
+ inline u32
+ flags() const
+ {
+ return header.flags;
+ }
+
+ inline u32
+ uncompressed() const
+ {
+ return header.uncompressed;
+ }
+
+ inline const void *
+ data_header() const
+ {
+ D_ASSERT( data == this + 1 );
+
+ return &header;
+ }
+
+ inline const void *
+ data_start() const
+ {
+ return data;
+ }
+
+ inline void *
+ data_raw() const
+ {
+ return current;
+ }
+
+
+ inline bool
+ append( size_t size )
+ {
+ D_ASSERT( data == this + 1 );
+
+ if (header.size + size > VOODOO_PACKET_MAX)
+ return false;
+
+ current = (char*) data + header.size;
+
+ header.size += size;
+ header.uncompressed += size;
+
+ return true;
+ }
+
+ inline void
+ reset( size_t size )
+ {
+ D_ASSERT( data == this + 1 );
+
+ current = (char*) data;
+
+ header.size = size;
+ header.uncompressed = size;
+ }
+};
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/play.c b/Source/DirectFB/lib/voodoo/play.c
new file mode 100755
index 0000000..a262472
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/play.c
@@ -0,0 +1,935 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <directfb_version.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/message.h>
+#include <voodoo/play.h>
+#include <voodoo/play_internal.h>
+
+#ifdef MACOS
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+D_DEBUG_DOMAIN( Voodoo_Play, "Voodoo/Play", "Voodoo Play" );
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ DirectLink link;
+
+ VoodooPlayVersion version;
+ VoodooPlayInfo info;
+
+ long long last_seen;
+ long long broadcast;
+
+ char addr[64];
+} PlayerNode;
+
+/**********************************************************************************************************************/
+
+static void player_send_info( VoodooPlayer *player,
+ const in_addr_t *in_addr,
+ bool discover );
+
+static void *player_main_loop( DirectThread *thread,
+ void *arg );
+
+/**********************************************************************************************************************/
+
+static const int one = 1;
+
+VoodooPlayVersion g_VoodooPlay_version;
+VoodooPlayInfo g_VoodooPlay_info;
+
+/**********************************************************************************************************************/
+
+static VoodooPlayer *g_VoodooPlayer;
+
+/**********************************************************************************************************************/
+
+/*
+ * FIXME
+ */
+static void
+generate_uuid( u8 *buf )
+{
+ int i;
+
+ srand( direct_clock_get_abs_micros() );
+
+ for (i=0; i<16; i++) {
+ buf[i] = rand();
+ }
+}
+
+/**********************************************************************************************************************/
+
+pthread_mutex_t gplayermut = PTHREAD_MUTEX_INITIALIZER;
+
+
+DirectResult createSocketForPlayer (int * retfd)
+{
+ int fd = -1;
+ *retfd = -1;
+ DirectResult ret;
+ struct sockaddr_in addr;
+ D_INFO("Voodoo/Player: Creating the Socket for player 0x%08x\n",(int) g_VoodooPlayer);
+ /* Create the player socket. */
+ fd = socket( PF_INET, SOCK_DGRAM, 0 );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Player: Could not create the socket via socket()!\n" );
+
+ return ret;
+ }
+
+ /* Allow reuse of local address. */
+ if (setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one) ) < 0)
+ D_PERROR( "Voodoo/Player: Could not set SO_REUSEADDR!\n" );
+
+ if (setsockopt( fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one) ) < 0)
+ D_PERROR( "Voodoo/Player: Could not set SO_BROADCAST!\n" );
+
+ /* Bind the socket to the local port. */
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr( "0.0.0.0" );
+ addr.sin_port = htons( 2323 );
+
+ if (bind( fd, (struct sockaddr*) &addr, sizeof(addr) )) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Player: Could not bind() the socket!\n" );
+ close( fd );
+
+ return ret;
+ }
+
+ *retfd = fd;
+ return DR_OK;
+
+
+}
+
+
+DirectResult
+voodoo_player_create( const VoodooPlayInfo *info,
+ VoodooPlayer **ret_player )
+{
+ DirectResult ret;
+ int fd;
+
+ VoodooPlayer *player;
+ pthread_mutex_lock(&gplayermut);
+ D_ASSERT( ret_player != NULL );
+
+ if (g_VoodooPlayer) {
+ *ret_player = g_VoodooPlayer;
+ pthread_mutex_unlock(&gplayermut);
+ return DR_OK;
+ }
+
+ ret = createSocketForPlayer(&fd);
+ if ( ret != DR_OK)
+ {
+ pthread_mutex_unlock(&gplayermut);
+ return ret;
+
+ }
+
+
+
+ /* Allocate player structure. */
+ player = D_CALLOC( 1, sizeof(VoodooPlayer) );
+ if (!player) {
+ D_WARN( "out of memory" );
+ close( fd );
+ pthread_mutex_unlock(&gplayermut);
+ return DR_NOLOCALMEMORY;
+ }
+
+ pthread_mutex_init( &player->lock, NULL );
+
+ /* Initialize player structure. */
+ player->fd = fd;
+
+ /* Fill version struct */
+ player->version.v[0] = VPVF_LITTLE_ENDIAN | VPVF_32BIT_SERIALS;
+ player->version.v[1] = DIRECTFB_MAJOR_VERSION;
+ player->version.v[2] = DIRECTFB_MINOR_VERSION;
+ player->version.v[3] = DIRECTFB_MICRO_VERSION;
+
+ /* Fill info struct */
+ direct_snputs( player->info.name, voodoo_config->play_info.name, VOODOO_PLAYER_NAME_LENGTH );
+ direct_snputs( player->info.vendor, voodoo_config->play_info.vendor, VOODOO_PLAYER_VENDOR_LENGTH );
+ direct_snputs( player->info.model, voodoo_config->play_info.model, VOODOO_PLAYER_MODEL_LENGTH );
+ direct_memcpy( player->info.uuid, voodoo_config->play_info.uuid, 16 );
+
+ if (info)
+ player->info = *info;
+
+ if (!player->info.name[0])
+ direct_snputs( player->info.name, "Unnamed Player", VOODOO_PLAYER_NAME_LENGTH );
+
+ if (!player->info.vendor[0])
+ direct_snputs( player->info.vendor, "Unknown Vendor", VOODOO_PLAYER_VENDOR_LENGTH );
+
+ if (!player->info.model[0])
+ direct_snputs( player->info.model, "Unknown Model", VOODOO_PLAYER_MODEL_LENGTH );
+
+ if (!player->info.uuid[0])
+ generate_uuid( player->info.uuid );
+
+ player->info.flags |= VPIF_LINK;
+
+ D_MAGIC_SET( player, VoodooPlayer );
+
+
+ g_VoodooPlay_version = player->version;
+ g_VoodooPlay_info = player->info;
+
+
+ char buf[33];
+
+ snprintf( buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ player->info.uuid[0], player->info.uuid[1], player->info.uuid[2], player->info.uuid[3], player->info.uuid[4],
+ player->info.uuid[5], player->info.uuid[6], player->info.uuid[7], player->info.uuid[8], player->info.uuid[9],
+ player->info.uuid[10], player->info.uuid[11], player->info.uuid[12], player->info.uuid[13], player->info.uuid[14],
+ player->info.uuid[15] );
+
+ D_INFO( "Running player '%s' with UUID %s!\n", player->info.name, buf );
+
+ /* Start messaging thread */
+ player->thread = direct_thread_create( DTT_DEFAULT, player_main_loop, player, "Voodoo/Player" );
+
+ /* Return the new player. */
+ *ret_player = player;
+
+ if (!g_VoodooPlayer)
+ g_VoodooPlayer = player;
+
+ pthread_mutex_unlock(&gplayermut);
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_destroy( VoodooPlayer *player )
+{
+ pthread_mutex_lock(&gplayermut);
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ if (g_VoodooPlayer == player)
+ {
+ pthread_mutex_unlock(&gplayermut);
+ return DR_OK;
+ }
+ D_INFO("Voodoo/Player: Destroying the player 0x%08x\n",(int) player);
+ player->quit = true;
+
+ direct_thread_join( player->thread );
+ direct_thread_destroy( player->thread );
+
+ close( player->fd );
+
+ pthread_mutex_destroy( &player->lock );
+
+ D_MAGIC_CLEAR( player );
+
+ D_FREE( player );
+ g_VoodooPlayer = NULL;
+ pthread_mutex_unlock(&gplayermut);
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_broadcast( VoodooPlayer *player )
+{
+#if !VOODOO_PLAY_FAKE
+ int ret;
+#ifdef MACOS
+ char *ptr, lastname[IFNAMSIZ];
+#else
+ int i;
+#endif
+ struct ifreq req[16];
+ struct ifconf conf;
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ player->broadcast++;
+
+ conf.ifc_buf = (char*) req;
+ conf.ifc_len = sizeof(req);
+
+ ret = ioctl( player->fd, SIOCGIFCONF, &conf );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFCONF ) failed!\n" );
+ return DR_FAILURE;
+ }
+
+#ifdef MACOS
+ // TIV: On iPhone (and I believe in general on BSD, you can't just plainly iterate on struct size)
+
+ lastname[0] = 0;
+
+ for (ptr = conf.ifc_buf; ptr < conf.ifc_buf + conf.ifc_len; )
+ {
+ char buf[100];
+ int len, flags;
+ struct ifreq ifrcopy, *ifr = (struct ifreq *)ptr;
+ struct sockaddr_in *addr = (struct sockaddr_in*) &ifr->ifr_broadaddr;
+
+ len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
+ ptr += sizeof(ifr->ifr_name) + len; // for next one in buffer
+
+ if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0)
+ {
+ continue; /* already processed this interface */
+ }
+
+ memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
+
+ ifrcopy = *ifr;
+ ioctl( player->fd, SIOCGIFFLAGS, &ifrcopy);
+ flags = ifrcopy.ifr_flags;
+ if ((flags & IFF_UP) == 0)
+ {
+ D_INFO( "Voodoo/Player: %-16s is not up.\n", ifrcopy.ifr_name );
+ continue; // ignore if interface not up
+ }
+
+ ret = ioctl( player->fd, SIOCGIFBRDADDR, ifr );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFBRDADDR ) %-16s failed!\n", ifr->ifr_name );
+ continue;
+ }
+
+ if (addr->sin_addr.s_addr) {
+ inet_ntop( AF_INET, &addr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s)\n", ifr->ifr_name, buf );
+ }
+ else {
+ ret = ioctl( player->fd, SIOCGIFDSTADDR, ifr );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFDSTADDR ) failed!\n" );
+ continue;
+ }
+
+ inet_ntop( AF_INET, &addr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s) (P-t-P)\n", ifr->ifr_name, buf );
+ }
+
+ player_send_info( player, &addr->sin_addr.s_addr, true );
+ }
+#else
+ D_INFO( "Voodoo/Player: Detected %d interfaces\n", conf.ifc_len/sizeof(req[0]) );
+
+ for (i=0; i<conf.ifc_len/sizeof(req[0]); i++) {
+ struct sockaddr_in *addr = (struct sockaddr_in*) &req[i].ifr_broadaddr;
+ char buf[100];
+
+ ret = ioctl( player->fd, SIOCGIFBRDADDR, &req[i] );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFBRDADDR ) failed!\n" );
+ continue;
+ }
+
+ if (addr->sin_addr.s_addr) {
+ inet_ntop( AF_INET, &addr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s)\n", req[i].ifr_name, buf );
+ }
+ else {
+ ret = ioctl( player->fd, SIOCGIFDSTADDR, &req[i] );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFDSTADDR ) failed!\n" );
+ continue;
+ }
+
+ inet_ntop( AF_INET, &addr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s) (P-t-P)\n", req[i].ifr_name, buf );
+ }
+
+ //addr->sin_addr.s_addr = inet_addr( "192.168.1.150" );
+ //addr->sin_addr.s_addr = inet_addr( "192.168.255.255" );
+
+ player_send_info( player, &addr->sin_addr.s_addr, true );
+ }
+#endif
+#endif
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_lookup( VoodooPlayer *player,
+ const u8 uuid[16],
+ VoodooPlayInfo *ret_info,
+ char *ret_addr,
+ int max_addr )
+{
+ PlayerNode *node;
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ pthread_mutex_lock( &player->lock );
+
+ direct_list_foreach (node, player->nodes) {
+ if (!uuid || !memcmp( node->info.uuid, uuid, 16 )) {
+ if (ret_info)
+ direct_memcpy( ret_info, &node->info, sizeof(VoodooPlayInfo) );
+
+ if (ret_addr)
+ direct_snputs( ret_addr, node->addr, max_addr );
+
+ pthread_mutex_unlock( &player->lock );
+ return DR_OK;
+ }
+ }
+
+ if (uuid && !memcmp( player->info.uuid, uuid, 16 )) {
+ if (ret_info)
+ direct_memcpy( ret_info, &player->info, sizeof(VoodooPlayInfo) );
+
+ if (ret_addr)
+ direct_snputs( ret_addr, "127.0.0.1", max_addr );
+
+ pthread_mutex_unlock( &player->lock );
+ return DR_OK;
+ }
+
+ pthread_mutex_unlock( &player->lock );
+
+ return DR_ITEMNOTFOUND;
+}
+
+DirectResult
+voodoo_player_lookup_by_address( VoodooPlayer *player,
+ const char *addr,
+ VoodooPlayInfo *ret_info )
+{
+ PlayerNode *node;
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ pthread_mutex_lock( &player->lock );
+
+ direct_list_foreach (node, player->nodes) {
+ if (!addr || !strcmp( node->addr, addr )) {
+ direct_memcpy( ret_info, &node->info, sizeof(VoodooPlayInfo) );
+
+ pthread_mutex_unlock( &player->lock );
+ return DR_OK;
+ }
+ }
+
+ if (addr && !strcmp( "127.0.0.1", addr )) {
+ direct_memcpy( ret_info, &player->info, sizeof(VoodooPlayInfo) );
+
+ pthread_mutex_unlock( &player->lock );
+ return DR_OK;
+ }
+
+ pthread_mutex_unlock( &player->lock );
+
+ return DR_ITEMNOTFOUND;
+}
+
+DirectResult
+voodoo_player_enumerate( VoodooPlayer *player,
+ VoodooPlayerCallback callback,
+ void *ctx )
+{
+ PlayerNode *node;
+ long long now = direct_clock_get_abs_millis();
+
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ pthread_mutex_lock( &player->lock );
+
+ direct_list_foreach (node, player->nodes) {
+ if (node->broadcast != player->broadcast && direct_clock_get_abs_millis() - node->last_seen > 1000)
+ continue;
+
+ if (callback( ctx, &node->info, &node->version,
+ node->addr, now - node->last_seen ) == DENUM_CANCEL)
+ break;
+ }
+
+ pthread_mutex_unlock( &player->lock );
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+__attribute__((unused))
+static void
+player_send_info( VoodooPlayer *player,
+ const in_addr_t *in_addr,
+ bool discover )
+{
+ int ret;
+ struct sockaddr_in addr;
+ VoodooPlayMessage msg;
+ PlayerNode *node;
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ msg.version = player->version;
+ msg.type = discover ? VPMT_DISCOVER : VPMT_SENDINFO;
+ msg.info = player->info;
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = *in_addr;
+ addr.sin_port = htons( 2323 );
+
+ ret = sendto( player->fd, &msg, sizeof(msg), 0, (struct sockaddr*) &addr, sizeof(addr) );
+ if (ret < 0) {
+ D_PERROR( "Voodoo/Player: sendto() failed!\n" );
+ return;
+ }
+
+ if (!discover && voodoo_config->forward_nodes) {
+ direct_list_foreach (node, player->nodes) {
+ VoodooPlayInfo info = node->info;
+
+ info.flags |= VPIF_LEVEL2;
+
+ msg.version = node->version;
+ msg.type = discover ? VPMT_DISCOVER : VPMT_SENDINFO;
+ msg.info = info;
+
+ ret = sendto( player->fd, &msg, sizeof(msg), 0, (struct sockaddr*) &addr, sizeof(addr) );
+ if (ret < 0) {
+ D_PERROR( "Voodoo/Player: sendto() failed!\n" );
+ return;
+ }
+ }
+ }
+}
+
+static void
+player_save_info( VoodooPlayer *player,
+ const VoodooPlayMessage *msg,
+ const char *addr )
+{
+ PlayerNode *node;
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ direct_list_foreach (node, player->nodes) {
+ if (!memcmp( node->info.uuid, msg->info.uuid, 16 )) {
+ if (msg->info.flags & VPIF_LEVEL2 && !(node->info.flags & VPIF_LEVEL2)) {
+ node->version = msg->version;
+ node->info = msg->info;
+
+ direct_snputs( node->addr, addr, sizeof(node->addr) );
+ }
+ node->version = msg->version;
+ node->info = msg->info;
+
+ node->last_seen = direct_clock_get_abs_millis();
+ node->broadcast = player->broadcast;
+
+ direct_snputs( node->addr, addr, sizeof(node->addr) );
+
+ return;
+
+ }
+ }
+
+ node = D_CALLOC( 1, sizeof(PlayerNode) );
+ if (!node) {
+ D_OOM();
+ return;
+ }
+
+ node->version = msg->version;
+ node->info = msg->info;
+
+ node->last_seen = direct_clock_get_abs_millis();
+ node->broadcast = player->broadcast;
+
+ direct_snputs( node->addr, addr, sizeof(node->addr) );
+
+
+ direct_list_append( &player->nodes, &node->link );
+}
+
+#if !VOODOO_PLAY_FAKE
+static void *
+player_main_loop( DirectThread *thread, void *arg )
+{
+ VoodooPlayer *player = arg;
+ int ret;
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ VoodooPlayMessage msg;
+ char buf[100];
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+ while (!player->quit) {
+ struct pollfd pf;
+
+ pf.fd = player->fd;
+ pf.events = POLLIN;
+
+ switch (poll( &pf, 1, 100 )) {
+ default:
+ ret = recvfrom( player->fd, &msg, sizeof(msg), 0, (struct sockaddr*) &addr, &addr_len );
+ if (ret < 0) {
+ D_PERROR( "Voodoo/Player: recvfrom() failed!\n" );
+ close(player->fd);
+ ret = createSocketForPlayer(&player->fd);
+
+ continue;
+ }
+
+ inet_ntop( AF_INET, &addr.sin_addr, buf, sizeof(buf) );
+
+ pthread_mutex_lock( &player->lock );
+
+ /* Send reply if message is not from ourself */
+ if (memcmp( msg.info.uuid, player->info.uuid, 16 )) {
+ switch (msg.type) {
+ case VPMT_DISCOVER:
+ D_INFO( "Voodoo/Player: Received DISCOVER from '%s' (%s)\n", msg.info.name, buf );
+ player_send_info( player, &addr.sin_addr.s_addr, false );
+ break;
+
+ case VPMT_SENDINFO:
+ D_INFO( "Voodoo/Player: Received SENDINFO from '%s' (%s)\n", msg.info.name, buf );
+ player_save_info( player, &msg, buf );
+ break;
+
+ default:
+ D_ERROR( "Voodoo/Player: Received unknown message (%s)\n", buf );
+ break;
+ }
+ }
+ else
+ D_INFO( "Voodoo/Player: Received message from ourself (%s)\n", buf );
+
+ pthread_mutex_unlock( &player->lock );
+ break;
+
+ case 0:
+ D_DEBUG( "Voodoo/Player: Timeout during poll()\n" );
+ break;
+
+ case -1:
+ if (errno != EINTR) {
+ D_PERROR( "Voodoo/Player: Could not poll() the socket!\n" );
+ close(player->fd);
+ ret = createSocketForPlayer(&player->fd);
+ // player->quit = true;
+ }
+ break;
+ }
+ }
+
+ return DR_OK;
+}
+#else
+
+static DirectResult
+send_discover_and_receive_info( int fd,
+ VoodooPlayVersion *ret_version,
+ VoodooPlayInfo *ret_info )
+{
+ int ret;
+ VoodooMessageHeader header;
+
+ D_INFO( "Voodoo/Player: Sending VMSG_DISCOVER message via Voodoo TCP port...\n" );
+
+ header.size = sizeof(VoodooMessageHeader);
+ header.serial = 0;
+ header.type = VMSG_DISCOVER;
+
+ ret = write( fd, &header, sizeof(header) );
+ if (ret < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Player: Failed to send VMSG_DISCOVER message via Voodoo TCP port!\n" );
+ return ret;
+ }
+
+
+
+ struct pollfd pfd;
+
+ pfd.events = POLL_IN;
+ pfd.fd = fd;
+
+ // wait for up to one second (old server will not reply anything, so we have to timeout)
+ ret = poll( &pfd, 1, 1000 );
+ if (ret < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Player: Failed to wait for reply after sending VMSG_DISCOVER message via Voodoo TCP port!\n" );
+ return ret;
+ }
+
+ if (ret == 0) {
+ D_INFO( "Voodoo/Player: Old Voodoo Server without VMSG_DISCOVER support (timeout waiting for reply)\n" );
+ return DR_UNSUPPORTED;
+ }
+
+ D_INFO( "Voodoo/Player: New Voodoo Server with VMSG_DISCOVER support, reading version/info (SENDINFO) reply...\n" );
+
+
+ struct {
+ VoodooMessageHeader header;
+ VoodooPlayVersion version;
+ VoodooPlayInfo info;
+ } msg;
+
+ size_t got = 0;
+
+ while (got < sizeof(msg)) {
+ ret = read( fd, (void*) &msg + got, sizeof(msg) - got );
+ if (ret < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Player: Failed to read after sending VMSG_DISCOVER message via Voodoo TCP port!\n" );
+ return ret;
+ }
+
+ got += ret;
+ }
+
+
+ if (msg.header.type != VMSG_SENDINFO) {
+ D_ERROR( "Voodoo/Player: Received message after sending VMSG_DISCOVER message via Voodoo TCP port is no VMSG_SENDINFO!\n");
+ return DR_INVARG;
+ }
+
+ *ret_version = msg.version;
+ *ret_info = msg.info;
+
+ D_INFO( "Voodoo/Player: Voodoo Server sent name '%s', version %d.%d.%d\n",
+ msg.info.name, msg.version.v[1], msg.version.v[2], msg.version.v[3] );
+
+ return DR_OK;
+}
+
+static void
+player_try_connect( VoodooPlayer *player,
+ u32 addr )
+{
+ DirectResult ret;
+ int fd, err;
+ struct in_addr sin_addr = { addr };
+
+ char buf[100];
+
+ inet_ntop( AF_INET, &sin_addr, buf, sizeof(buf) );
+
+
+ /* Create the client socket. */
+ fd = socket( AF_INET, SOCK_STREAM, 0 );
+ if (fd < 0) {
+ D_PERROR( "Voodoo/Player: Could not create the socket via socket( %d )!\n", AF_INET );
+ return;
+ }
+
+ struct sockaddr_in sock_addr;
+
+ sock_addr.sin_family = AF_INET;
+ sock_addr.sin_port = htons( 2323 );
+ sock_addr.sin_addr = sin_addr;
+
+ /* Connect to the server. */
+ err = connect( fd, (struct sockaddr*) &sock_addr, sizeof(sock_addr) );
+ if (err) {
+ D_PERROR( "Voodoo/Player: No Voodoo at '%s:2323'", buf );
+ close( fd );
+ return;
+ }
+
+ D_INFO( "Voodoo/Player: Found Voodoo at '%s'!\n", buf );
+
+
+ VoodooPlayMessage msg;
+
+
+ ret = send_discover_and_receive_info( fd, &msg.version, &msg.info );
+ if (ret) {
+ /* Fill version struct */
+ msg.version.v[0] = VPVF_LITTLE_ENDIAN | VPVF_32BIT_SERIALS;
+ msg.version.v[1] = DIRECTFB_MAJOR_VERSION;
+ msg.version.v[2] = DIRECTFB_MINOR_VERSION;
+ msg.version.v[3] = DIRECTFB_MICRO_VERSION;
+
+ msg.type = VPMT_SENDINFO;
+
+ /* Fill info struct */
+ direct_snputs( msg.info.name, "Unknown", VOODOO_PLAYER_NAME_LENGTH );
+ direct_snputs( msg.info.vendor, "Unknown", VOODOO_PLAYER_VENDOR_LENGTH );
+ direct_snputs( msg.info.model, "Unknown", VOODOO_PLAYER_MODEL_LENGTH );
+ generate_uuid( msg.info.uuid );
+ }
+
+
+ close( fd );
+
+
+ pthread_mutex_lock( &player->lock );
+
+ player_save_info( player, &msg, buf );
+
+ pthread_mutex_unlock( &player->lock );
+}
+
+typedef struct {
+ VoodooPlayer *player;
+ u32 addr;
+} PlayerTryContext;
+
+static void *
+player_try_thread( void *arg )
+{
+ PlayerTryContext *context = arg;
+
+ player_try_connect( context->player, context->addr );
+
+ D_FREE( context );
+
+ return NULL;
+}
+
+static void *
+player_main_loop( DirectThread *thread, void *arg )
+{
+ VoodooPlayer *player = arg;
+ int ret;
+ int i;
+ struct ifreq req[16];
+ struct ifconf conf;
+
+ D_MAGIC_ASSERT( player, VoodooPlayer );
+
+// while (!player->quit) {
+ conf.ifc_buf = (char*) req;
+ conf.ifc_len = sizeof(req);
+
+ ret = ioctl( player->fd, SIOCGIFCONF, &conf );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFCONF ) failed!\n" );
+ return NULL;
+ }
+
+ D_INFO( "Voodoo/Player: Detected %d interfaces\n", conf.ifc_len/sizeof(req[0]) );
+
+ for (i=0; i<conf.ifc_len/sizeof(req[0]); i++) {
+ struct sockaddr_in *addr = (struct sockaddr_in*) &req[i].ifr_broadaddr;
+ char buf[100];
+
+ ret = ioctl( player->fd, SIOCGIFBRDADDR, &req[i] );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFBRDADDR ) failed!\n" );
+ continue;
+ }
+
+ if (addr->sin_addr.s_addr) {
+ inet_ntop( AF_INET, &addr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s) [0x%08x]\n", req[i].ifr_name, buf, addr->sin_addr.s_addr );
+
+ u32 _addr = htonl( addr->sin_addr.s_addr );
+ u32 a;
+
+ for (a = (_addr & ~0xff) + 1; a < (_addr | 0xff); a++) {
+ if (a == _addr)
+ continue;
+
+ PlayerTryContext *context = D_CALLOC( 1, sizeof(PlayerTryContext) );
+
+ context->player = player;
+ context->addr = ntohl(a);
+
+
+ pthread_t t;
+
+ pthread_create( &t, NULL, player_try_thread, context );
+ }
+ }
+ else {
+ ret = ioctl( player->fd, SIOCGIFDSTADDR, &req[i] );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFDSTADDR ) failed!\n" );
+ continue;
+ }
+
+ inet_ntop( AF_INET, &addr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s) (P-t-P)\n", req[i].ifr_name, buf );
+ }
+ }
+// }
+
+ return DR_OK;
+}
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/play.h b/Source/DirectFB/lib/voodoo/play.h
new file mode 100755
index 0000000..1dc50df
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/play.h
@@ -0,0 +1,146 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__PLAY_H__
+#define __VOODOO__PLAY_H__
+
+#include <voodoo/types.h>
+
+
+#define VOODOO_PLAY_VERSION_FIXED_SIZE 32
+
+#define VOODOO_PLAYER_NAME_LENGTH 96
+
+#define VOODOO_PLAYER_VENDOR_LENGTH 96
+#define VOODOO_PLAYER_MODEL_LENGTH 96
+
+
+#define VOODOO_LINK_PORT 8676 // 'V' 'L'
+
+
+typedef enum {
+ VPVF_NONE = 0x00000000,
+
+ VPVF_LITTLE_ENDIAN = 0x00000001, /* Always set, no big endian support for now */
+ VPVF_32BIT_SERIALS = 0x00000002, /* Using 32bit message serials, always set */
+
+ VPVF_ALL = 0x00000007
+} VoodooPlayVersionFlags;
+
+typedef struct {
+ u8 v[4]; /* flags, major, minor, micro */
+} VoodooPlayVersion;
+
+
+typedef enum {
+ VPIF_NONE = 0x00000000,
+
+ VPIF_LEVEL2 = 0x00000001,
+ VPIF_LINK = 0x00000002, /* Supports new VoodooLink protocol */
+
+ VPIF_ALL = 0x00000003
+} VoodooPlayInfoFlags;
+
+typedef struct {
+ VoodooPlayInfoFlags flags;
+
+ u8 uuid[16];
+
+ char name[VOODOO_PLAYER_NAME_LENGTH]; /* "My Philips TV" */
+
+ char vendor[VOODOO_PLAYER_VENDOR_LENGTH]; /* "Philips Consumer Lifestyle" */
+ char model[VOODOO_PLAYER_MODEL_LENGTH]; /* "32PFL9604H/10" */
+} VoodooPlayInfo;
+
+
+typedef enum {
+ VPMT_INVALID,
+
+ VPMT_DISCOVER,
+ VPMT_SENDINFO,
+} VoodooPlayMessageType;
+
+
+
+/*
+
+ One play message on a new connection from both sides.
+ Both sides having received the other side's info know if the connection is to be closed or can succeed.
+
+ Game about endianness conversion: both sides randomly send 0 or 1 as part of the info,
+ if both are equal, then server converts, otherwise client
+*/
+
+typedef struct {
+ /* Version information first in structure, fixed size (union!) */
+ union {
+ char __fixed[VOODOO_PLAY_VERSION_FIXED_SIZE];
+
+
+ VoodooPlayVersion version; /* (1.0, ...) */
+ };
+
+ VoodooPlayMessageType type;
+
+ union {
+ VoodooPlayInfo info; /* DISCOVER, SENDINFO */
+ };
+} VoodooPlayMessage;
+
+
+typedef DirectEnumerationResult (*VoodooPlayerCallback)( void *ctx,
+ const VoodooPlayInfo *info,
+ const VoodooPlayVersion *version,
+ const char *address,
+ unsigned int ms_since_last_seen );
+
+
+DirectResult voodoo_player_create ( const VoodooPlayInfo *info,
+ VoodooPlayer **ret_player );
+
+DirectResult voodoo_player_destroy ( VoodooPlayer *player );
+
+DirectResult voodoo_player_broadcast ( VoodooPlayer *player );
+
+DirectResult voodoo_player_lookup ( VoodooPlayer *player,
+ const u8 uuid[16],
+ VoodooPlayInfo *ret_info,
+ char *ret_addr,
+ int max_addr );
+
+DirectResult voodoo_player_lookup_by_address( VoodooPlayer *player,
+ const char *addr,
+ VoodooPlayInfo *ret_info );
+
+DirectResult voodoo_player_enumerate ( VoodooPlayer *player,
+ VoodooPlayerCallback callback,
+ void *ctx );
+
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/play_internal.h b/Source/DirectFB/lib/voodoo/play_internal.h
new file mode 100755
index 0000000..0aa0f91
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/play_internal.h
@@ -0,0 +1,89 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__PLAY_INTERNAL_H__
+#define __VOODOO__PLAY_INTERNAL_H__
+
+#include <voodoo/app.h>
+#include <voodoo/play.h>
+#include <voodoo/play_server.h>
+
+#include <direct/list.h>
+#include <direct/thread.h>
+
+
+struct __V_VoodooPlayer {
+ int magic;
+
+ int fd;
+
+ pthread_mutex_t lock;
+
+ bool quit;
+
+ VoodooPlayVersion version;
+ VoodooPlayInfo info;
+
+ DirectThread *thread;
+
+ DirectLink *nodes;
+
+ long long broadcast;
+
+ VoodooServer *server;
+
+ const VoodooAppDescription *apps;
+ unsigned int num_apps;
+
+ VoodooPlayerLaunchFunc launch_func;
+ VoodooPlayerStopFunc stop_func;
+ void *ctx;
+
+ DirectLink *instances;
+ pthread_mutex_t instances_lock;
+ pthread_cond_t instances_cond;
+};
+
+
+typedef struct {
+ DirectLink link;
+
+ u8 uuid[16];
+
+ void *data;
+
+ VoodooAppDescription app;
+ u8 player_uuid[16];
+} VoodooAppInstance;
+
+
+extern VoodooPlayVersion g_VoodooPlay_version;
+extern VoodooPlayInfo g_VoodooPlay_info;
+
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/play_server.c b/Source/DirectFB/lib/voodoo/play_server.c
new file mode 100755
index 0000000..1e933f5
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/play_server.c
@@ -0,0 +1,430 @@
+/*
+ (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <directfb_version.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/play_server.h>
+#include <voodoo/play_internal.h>
+#include <voodoo/server.h>
+
+D_DEBUG_DOMAIN( Voodoo_Play_Server, "Voodoo/Play/Server", "Voodoo Play Server" );
+
+/**********************************************************************************************************************/
+
+VoodooPlayer *voodoo_player;
+
+/**********************************************************************************************************************/
+/*
+ * FIXME
+ */
+static void
+generate_uuid( u8 *buf )
+{
+ int i;
+
+ for (i=0; i<16; i++) {
+ buf[i] = rand();
+ }
+}
+
+static DirectResult
+ConstructDispatcher( VoodooServer *server,
+ VoodooManager *manager,
+ const char *name,
+ void *ctx,
+ VoodooInstanceID *ret_instance )
+{
+ DirectResult ret;
+ DirectInterfaceFuncs *funcs;
+ void *interface;
+ VoodooInstanceID instance;
+
+ D_ASSERT( server != NULL );
+ D_ASSERT( manager != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( ret_instance != NULL );
+
+ ret = DirectGetInterface( &funcs, name, "Dispatcher", NULL, NULL );
+ if (ret)
+ return ret;
+
+ ret = funcs->Allocate( &interface );
+ if (ret)
+ return ret;
+
+ ret = funcs->Construct( interface, manager, &instance );
+ if (ret)
+ return ret;
+
+ *ret_instance = instance;
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+voodoo_player_run_server( VoodooPlayer *player,
+ const VoodooAppDescription *apps,
+ unsigned int num_apps,
+ VoodooPlayerLaunchFunc launch_func,
+ VoodooPlayerStopFunc stop_func,
+ void *ctx )
+{
+ DirectResult ret;
+ VoodooServer *server;
+
+ D_ASSERT( player != NULL );
+ D_ASSERT( apps != NULL );
+ D_ASSERT( num_apps > 0 );
+ D_ASSERT( launch_func != NULL );
+
+ if (voodoo_player) {
+ D_ERROR( "Voodoo/Play: Already running as a server!\n" );
+ return DR_BUSY;
+ }
+
+ ret = voodoo_server_create( &server );
+ if (ret)
+ return ret;
+
+ ret = voodoo_server_register( server, "IVoodooPlayer", ConstructDispatcher, NULL );
+ if (ret) {
+ D_ERROR( "Voodoo/Player: Could not register super interface 'IVoodooPlayer'!\n" );
+ voodoo_server_destroy( server );
+ return ret;
+ }
+
+ player->server = server;
+ player->apps = apps;
+ player->num_apps = num_apps;
+ player->launch_func = launch_func;
+ player->stop_func = stop_func;
+ player->ctx = ctx;
+
+ pthread_mutex_init( &player->instances_lock, NULL );
+ pthread_cond_init( &player->instances_cond, NULL );
+
+ voodoo_player = player;
+
+ ret = voodoo_server_run( server, false );
+ if (ret)
+ D_DERROR( ret, "Voodoo/Player: Server exiting!\n" );
+
+ voodoo_player = NULL;
+
+ player->server = NULL;
+ player->apps = NULL;
+ player->num_apps = 0;
+ player->launch_func = NULL;
+ player->stop_func = NULL;
+ player->ctx = NULL;
+ player->instances = NULL;
+
+ pthread_mutex_destroy( &player->instances_lock );
+ pthread_cond_destroy( &player->instances_cond );
+
+ voodoo_server_destroy( server );
+
+ return ret;
+}
+
+DirectResult
+voodoo_player_get_apps( VoodooPlayer *player,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppDescription *ret_apps )
+{
+ D_ASSERT( player != NULL );
+ D_ASSERT( ret_num != NULL );
+ D_ASSERT( ret_apps != NULL );
+
+ ///
+
+ unsigned int num = max_num;
+
+ if (num > player->num_apps)
+ num = player->num_apps;
+
+ *ret_num = num;
+
+ direct_memcpy( ret_apps, player->apps, sizeof(VoodooAppDescription) * num );
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_launch_app( VoodooPlayer *player,
+ const u8 app_uuid[16],
+ const u8 player_uuid[16],
+ u8 ret_instance_uuid[16] )
+{
+ DirectResult ret;
+ int i;
+
+ D_ASSERT( player != NULL );
+ D_ASSERT( app_uuid != NULL );
+ D_ASSERT( player_uuid != NULL );
+ D_ASSERT( ret_instance_uuid != NULL );
+
+
+ char buf1[33];
+ char buf2[33];
+
+ snprintf( buf1, sizeof(buf1), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ app_uuid[0], app_uuid[1], app_uuid[2], app_uuid[3], app_uuid[4],
+ app_uuid[5], app_uuid[6], app_uuid[7], app_uuid[8], app_uuid[9],
+ app_uuid[10], app_uuid[11], app_uuid[12], app_uuid[13], app_uuid[14],
+ app_uuid[15] );
+
+ snprintf( buf2, sizeof(buf2), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ player_uuid[0], player_uuid[1], player_uuid[2], player_uuid[3], player_uuid[4],
+ player_uuid[5], player_uuid[6], player_uuid[7], player_uuid[8], player_uuid[9],
+ player_uuid[10], player_uuid[11], player_uuid[12], player_uuid[13], player_uuid[14],
+ player_uuid[15] );
+
+ D_INFO( "Voodoo/Player: Launching application %s on %s...\n", buf1, buf2 );
+
+
+ const VoodooAppDescription *app = NULL;
+
+ for (i=0; i<player->num_apps; i++) {
+ if (!memcmp( app_uuid, player->apps[i].uuid, 16 )) {
+ app = &player->apps[i];
+ break;
+ }
+ }
+
+ if (!app) {
+ D_ERROR( "Voodoo/Player: Could not lookup application with UUID %s!\n", buf1 );
+ return DR_ITEMNOTFOUND;
+ }
+
+
+ VoodooPlayInfo info;
+ char addr[1000];
+
+
+ voodoo_player_broadcast( player );
+ sleep( 1 );
+
+ ret = voodoo_player_lookup( player, player_uuid, &info, addr, sizeof(addr) );
+ if (ret) {
+ if ( (player_uuid[0]==0xf0) && (player_uuid[1]==0xf0) && (player_uuid[2]==0xf0) && (player_uuid[3]==0xf0)
+ && (player_uuid[4]==0xf0) && (player_uuid[5]==0xf0) && (player_uuid[6]==0xf0) && (player_uuid[7]==0xf0)
+ && (player_uuid[8]==0xf0) && (player_uuid[9]==0xf0) && (player_uuid[10]==0xf0) && (player_uuid[11]==0xf0) )
+ {
+ sprintf(addr, "%d.%d.%d.%d", player_uuid[12], player_uuid[13], player_uuid[14], player_uuid[15]);
+ }
+ else
+ {
+ D_DERROR( ret, "Voodoo/Player: Could not lookup player with UUID %s!\n", buf2 );
+ return ret;
+ }
+ }
+
+
+ VoodooAppInstance *instance;
+
+ instance = D_CALLOC( 1, sizeof(VoodooAppInstance) );
+ if (!instance)
+ return D_OOM();
+
+ ret = player->launch_func( player, player->ctx, app, &info, addr, &instance->data );
+ if (ret) {
+ D_DERROR( ret, "Voodoo/Player: Could not launch application '%s'\n", app->name );
+ D_FREE( instance );
+ return ret;
+ }
+
+ generate_uuid( instance->uuid );
+
+ direct_memcpy( &instance->app, app, sizeof(VoodooAppDescription) );
+ direct_memcpy( instance->player_uuid, player_uuid, 16 );
+
+
+
+ pthread_mutex_lock( &player->instances_lock );
+
+ direct_list_append( &player->instances, &instance->link );
+
+ direct_memcpy( ret_instance_uuid, instance->uuid, 16 );
+
+ pthread_mutex_unlock( &player->instances_lock );
+
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_stop_instance( VoodooPlayer *player,
+ const u8 instance_uuid[16] )
+{
+ DirectResult ret;
+ char buf1[33];
+ VoodooAppInstance *instance;
+
+ snprintf( buf1, sizeof(buf1), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ instance_uuid[0], instance_uuid[1], instance_uuid[2], instance_uuid[3], instance_uuid[4],
+ instance_uuid[5], instance_uuid[6], instance_uuid[7], instance_uuid[8], instance_uuid[9],
+ instance_uuid[10], instance_uuid[11], instance_uuid[12], instance_uuid[13], instance_uuid[14],
+ instance_uuid[15] );
+
+ D_INFO( "Voodoo/Player: Stopping instance %s...\n", buf1 );
+
+ pthread_mutex_lock( &player->instances_lock );
+
+ direct_list_foreach (instance, player->instances) {
+ if (!memcmp( instance->uuid, instance_uuid, 16 ))
+ break;
+ }
+
+ if (!instance) {
+ D_ERROR( "Voodoo/Player: Could not find instance with UUID %s!\n", buf1 );
+ pthread_mutex_unlock( &player->instances_lock );
+ return DR_NOSUCHINSTANCE;
+ }
+
+ ret = player->stop_func( player, player->ctx, instance->data );
+ if (ret) {
+ D_DERROR( ret, "Voodoo/Player: Could not stop instance with UUID %s!\n", buf1 );
+ pthread_mutex_unlock( &player->instances_lock );
+ return ret;
+ }
+
+ direct_list_remove( &player->instances, &instance->link );
+
+ pthread_cond_broadcast( &player->instances_cond );
+
+ pthread_mutex_unlock( &player->instances_lock );
+
+ D_FREE( instance );
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_wait_instance( VoodooPlayer *player,
+ const u8 instance_uuid[16] )
+{
+ char buf1[33];
+ VoodooAppInstance *instance;
+
+ snprintf( buf1, sizeof(buf1), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ instance_uuid[0], instance_uuid[1], instance_uuid[2], instance_uuid[3], instance_uuid[4],
+ instance_uuid[5], instance_uuid[6], instance_uuid[7], instance_uuid[8], instance_uuid[9],
+ instance_uuid[10], instance_uuid[11], instance_uuid[12], instance_uuid[13], instance_uuid[14],
+ instance_uuid[15] );
+
+ D_INFO( "Voodoo/Player: Waiting for instance %s...\n", buf1 );
+
+
+ do {
+ pthread_mutex_lock( &player->instances_lock );
+
+ direct_list_foreach (instance, player->instances) {
+ if (!memcmp( instance->uuid, instance_uuid, 16 )) {
+ pthread_cond_wait( &player->instances_cond, &player->instances_lock );
+ break;
+ }
+ }
+
+ pthread_mutex_unlock( &player->instances_lock );
+ } while (instance);
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_player_get_instances( VoodooPlayer *player,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppInstanceDescription *ret_instances )
+{
+ VoodooAppInstance *instance;
+
+ D_ASSERT( player != NULL );
+ D_ASSERT( ret_num != NULL );
+ D_ASSERT( ret_instances != NULL );
+
+ ///
+
+ pthread_mutex_lock( &player->instances_lock );
+
+ unsigned int i = 0;
+
+ direct_list_foreach (instance, player->instances) {
+ if (i == max_num)
+ break;
+
+ direct_memcpy( ret_instances[i].uuid, instance->uuid, 16 );
+ direct_memcpy( &ret_instances[i].app, &instance->app, sizeof(VoodooAppDescription) );
+ direct_memcpy( ret_instances[i].player_uuid, instance->player_uuid, 16 );
+
+ i++;
+ }
+
+ *ret_num = i;
+
+ pthread_mutex_unlock( &player->instances_lock );
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/play_server.h b/Source/DirectFB/lib/voodoo/play_server.h
new file mode 100755
index 0000000..9677e7e
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/play_server.h
@@ -0,0 +1,79 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__PLAY_SERVER_H__
+#define __VOODOO__PLAY_SERVER_H__
+
+#include <voodoo/app.h>
+#include <voodoo/play.h>
+
+
+typedef DirectResult (*VoodooPlayerLaunchFunc)( VoodooPlayer *player,
+ void *ctx,
+ const VoodooAppDescription *app,
+ const VoodooPlayInfo *player_info,
+ const char *player_addr,
+ void **ret_data );
+
+typedef DirectResult (*VoodooPlayerStopFunc) ( VoodooPlayer *player,
+ void *ctx,
+ void *data );
+
+
+DirectResult voodoo_player_run_server ( VoodooPlayer *player,
+ const VoodooAppDescription *apps,
+ unsigned int num_apps,
+ VoodooPlayerLaunchFunc launch_func,
+ VoodooPlayerStopFunc stop_func,
+ void *ctx );
+
+DirectResult voodoo_player_get_apps ( VoodooPlayer *player,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppDescription *ret_apps );
+
+DirectResult voodoo_player_launch_app ( VoodooPlayer *player,
+ const u8 app_uuid[16],
+ const u8 player_uuid[16],
+ u8 ret_instance_uuid[16] );
+
+DirectResult voodoo_player_stop_instance( VoodooPlayer *player,
+ const u8 instance_uuid[16] );
+
+DirectResult voodoo_player_wait_instance( VoodooPlayer *player,
+ const u8 instance_uuid[16] );
+
+DirectResult voodoo_player_get_instances( VoodooPlayer *player,
+ unsigned int max_num,
+ unsigned int *ret_num,
+ VoodooAppInstanceDescription *ret_instances );
+
+
+extern VoodooPlayer *voodoo_player;
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/server.c b/Source/DirectFB/lib/voodoo/server.c
new file mode 100755
index 0000000..0c543b6
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/server.c
@@ -0,0 +1,459 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <semaphore.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <direct/clock.h>
+#include <direct/debug.h>
+#include <direct/interface.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <voodoo/server.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+#include <voodoo/manager.h>
+
+
+typedef struct {
+ sem_t sem;
+
+ pid_t gfxpid;
+} ServerShared;
+
+typedef struct {
+ DirectLink link;
+
+ VoodooLink vl;
+ VoodooManager *manager;
+} Connection;
+
+typedef struct {
+ const char *name;
+ VoodooSuperConstruct func;
+ void *ctx;
+
+ IAny *interface;
+} Super;
+
+#define MAX_SUPER 8
+
+struct __V_VoodooServer {
+ int fd;
+
+ bool quit;
+ DirectLink *connections;
+
+ int num_super;
+ Super supers[MAX_SUPER];
+
+ ServerShared *shared;
+};
+
+/**************************************************************************************************/
+
+static DirectResult accept_connection( VoodooServer *server, int fd );
+
+/**************************************************************************************************/
+
+static const int one = 1;
+
+/**************************************************************************************************/
+
+DirectResult
+voodoo_server_create( VoodooServer **ret_server )
+{
+ DirectResult ret;
+ struct sockaddr_in addr;
+ int fd = -1;
+ VoodooServer *server = NULL;
+
+ D_ASSERT( ret_server != NULL );
+
+ /* Create the server socket. */
+ fd = socket( PF_INET, SOCK_STREAM, 0 );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Server: Could not create the socket via socket()!\n" );
+ goto error;
+ }
+
+ /* Allow reuse of local address. */
+ if (setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one) ) < 0)
+ D_PERROR( "Voodoo/Server: Could not set SO_REUSEADDR!\n" );
+
+ /* Bind the socket to the local port. */
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr( "0.0.0.0" );
+ addr.sin_port = htons( 2323 );
+
+ if (bind( fd, &addr, sizeof(addr) )) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Server: Could not bind() the socket!\n" );
+ goto error;
+ }
+
+ /* Start listening. */
+ if (listen( fd, 4 )) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Server: Could not listen() to the socket!\n" );
+ goto error;
+ }
+
+ /* Allocate server structure. */
+ server = D_CALLOC( 1, sizeof(VoodooServer) );
+ if (!server) {
+ ret = D_OOM();
+ D_WARN( "out of memory" );
+ goto error;
+ }
+
+ /* Initialize server structure. */
+ server->fd = fd;
+
+ {
+ int zfd;
+
+ zfd = open( "/dev/zero", O_RDWR );
+ if (zfd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Server: Failed to open /dev/zero!\n" );
+ goto error;
+ }
+
+ server->shared = mmap( NULL, sizeof(ServerShared), PROT_READ | PROT_WRITE, MAP_SHARED, zfd, 0 );
+
+ close( zfd );
+
+ if (server->shared == MAP_FAILED) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Server: Failed to mmap /dev/zero!\n" );
+ server->shared = NULL;
+ goto error;
+ }
+
+ if (sem_init( &server->shared->sem, 1, 1 )) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Server: Failed to create process shared semaphore!\n" );
+ goto error;
+ }
+ }
+
+ /* Return the new server. */
+ *ret_server = server;
+
+ return DR_OK;
+
+
+error:
+ if (server) {
+ if (server->shared)
+ munmap( server->shared, sizeof(ServerShared) );
+
+ D_FREE( server );
+ }
+
+ if (fd >= 0)
+ close( fd );
+
+ return ret;
+}
+
+DirectResult
+voodoo_server_register( VoodooServer *server,
+ const char *name,
+ VoodooSuperConstruct func,
+ void *ctx )
+{
+ Super *super;
+
+ D_ASSERT( server != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( func != NULL );
+
+ if (server->num_super == MAX_SUPER)
+ return DR_LIMITEXCEEDED;
+
+ super = &server->supers[server->num_super++];
+
+ super->name = name;
+ super->func = func;
+ super->ctx = ctx;
+
+ return DR_OK;
+}
+
+static inline Super *
+lookup_super( VoodooServer *server,
+ const char *name )
+{
+ int i;
+
+ D_ASSERT( server != NULL );
+ D_ASSERT( name != NULL );
+
+ for (i=0; i<server->num_super; i++) {
+ Super *super = &server->supers[i];
+
+ if (! strcmp( name, super->name ))
+ return super;
+ }
+
+ return NULL;
+}
+
+DirectResult
+voodoo_server_construct( VoodooServer *server,
+ VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance )
+{
+ DirectResult ret;
+ Super *super;
+ VoodooInstanceID instance;
+
+ D_ASSERT( server != NULL );
+ D_ASSERT( manager != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( ret_instance != NULL );
+
+ super = lookup_super( server, name );
+ if (!super) {
+ D_ERROR( "Voodoo/Server: Super interface '%s' is not available!\n", name );
+ return DR_UNSUPPORTED;
+ }
+
+ if (!strcmp( name, "IDirectFB" )) {
+ sem_wait( &server->shared->sem );
+
+ if (server->shared->gfxpid) {
+ D_INFO( "Voodoo/Server: Killing previous graphics process with pid %d\n", server->shared->gfxpid );
+ kill( server->shared->gfxpid, SIGTERM );
+ }
+
+ server->shared->gfxpid = getpid();
+
+ D_INFO( "Voodoo/Server: New graphics process has pid %d\n", server->shared->gfxpid );
+
+ sem_post( &server->shared->sem );
+ }
+
+ ret = super->func( server, manager, name, super->ctx, &instance );
+ if (ret) {
+ D_ERROR( "Voodoo/Server: "
+ "Creating super interface '%s' failed (%s)!\n", name, DirectResultString(ret) );
+ return ret;
+ }
+
+ *ret_instance = instance;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_server_run( VoodooServer *server,
+ bool forking )
+{
+ DirectLink *l, *n;
+ struct pollfd pf;
+ bool listener = true;
+
+ D_ASSERT( server != NULL );
+
+ while (!server->quit) {
+ /* Cleanup dead connections. */
+ direct_list_foreach_safe (l, n, server->connections) {
+ Connection *connection = (Connection*) l;
+
+ if (voodoo_manager_is_closed( connection->manager )) {
+ sem_wait( &server->shared->sem );
+
+ if (server->shared->gfxpid == getpid()) {
+ D_INFO( "Voodoo/Server: Closing graphics process with pid %d\n", server->shared->gfxpid );
+ server->shared->gfxpid = 0;
+ }
+
+ sem_post( &server->shared->sem );
+
+
+ voodoo_manager_destroy( connection->manager );
+
+ //connection->vl.Close( &connection->vl );
+
+ direct_list_remove( &server->connections, l );
+
+ D_INFO( "Voodoo/Server: Closed connection.\n" );
+
+ D_FREE( connection );
+
+ if (forking && !server->connections)
+ return DR_OK;
+ }
+ }
+
+ if (listener) {
+ int i;
+ int fd;
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+
+ pf.fd = server->fd;
+ pf.events = POLLIN;
+
+ switch (poll( &pf, 1, 200 )) {
+ default:
+ fd = accept( server->fd, &addr, &addrlen );
+ if (fd < 0) {
+ D_PERROR( "Voodoo/Server: Could not accept() incoming connection!\n" );
+ break;
+ }
+
+ if (forking) {
+ switch (fork()) {
+ case 0:
+ listener = false;
+
+ for (i=3; i<65535; i++) {
+ if (i != fd)
+ close( i );
+ }
+
+ accept_connection( server, fd );
+ break;
+
+ case -1:
+ D_PERROR( "Voodoo/Server: Could not fork()!\n" );
+ break;
+
+ default:
+ close( fd );
+ break;
+ }
+ }
+ else {
+ accept_connection( server, fd );
+ }
+ break;
+
+ case 0:
+ waitpid( -1, NULL, WNOHANG );
+
+ D_DEBUG( "Voodoo/Server: Timeout during poll()\n" );
+ break;
+
+ case -1:
+ if (errno != EINTR) {
+ D_PERROR( "Voodoo/Server: Could not poll() the socket!\n" );
+ server->quit = true;
+ }
+ break;
+ }
+ }
+ else
+ usleep( 200000 );
+ }
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_server_destroy( VoodooServer *server )
+{
+ DirectLink *l;
+
+ D_ASSERT( server != NULL );
+
+ close( server->fd );
+
+ /* Close all connections. */
+ direct_list_foreach (l, server->connections) {
+ Connection *connection = (Connection*) l;
+
+ voodoo_manager_destroy( connection->manager );
+
+ //connection->vl.Close( &connection->vl );
+
+ D_FREE( connection );
+ }
+
+ D_FREE( server );
+
+ return DR_OK;
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+accept_connection( VoodooServer *server, int fd )
+{
+ DirectResult ret;
+ int fds[2] = { fd, fd };
+ Connection *connection;
+
+ connection = D_CALLOC( 1, sizeof(Connection) );
+ if (!connection) {
+ D_WARN( "out of memory" );
+ return DR_NOLOCALMEMORY;
+ }
+
+ voodoo_link_init_fd( &connection->vl, fds );
+
+ ret = voodoo_manager_create( &connection->vl, NULL, server, &connection->manager );
+ if (ret) {
+ connection->vl.Close( &connection->vl );
+ D_FREE( connection );
+ return ret;
+ }
+
+ direct_list_prepend( &server->connections, &connection->link );
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/server.h b/Source/DirectFB/lib/voodoo/server.h
new file mode 100755
index 0000000..e00329f
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/server.h
@@ -0,0 +1,52 @@
+/*
+ (c) Copyright 2001-2007 The DirectFB Organization (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__SERVER_H__
+#define __VOODOO__SERVER_H__
+
+#include <voodoo/types.h>
+
+
+DirectResult voodoo_server_create ( VoodooServer **ret_server );
+
+DirectResult voodoo_server_register( VoodooServer *server,
+ const char *name,
+ VoodooSuperConstruct func,
+ void *ctx );
+
+DirectResult voodoo_server_run ( VoodooServer *server,
+ bool forking );
+
+DirectResult voodoo_server_destroy ( VoodooServer *server );
+
+DirectResult voodoo_server_construct( VoodooServer *server,
+ VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance );
+
+#endif
diff --git a/Source/DirectFB/lib/voodoo/types.h b/Source/DirectFB/lib/voodoo/types.h
new file mode 100755
index 0000000..ef9277c
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/types.h
@@ -0,0 +1,97 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VOODOO__TYPES_H__
+#define __VOODOO__TYPES_H__
+
+#include <direct/types.h>
+
+#include "compat.h"
+
+#ifdef WIN32
+// The following ifdef block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the VOODOO_EXPORTS
+// symbol defined on the command line. This symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// VOODOO_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+#ifdef VOODOO_EXPORTS
+#define VOODOO_API __declspec(dllexport)
+#else
+#define VOODOO_API __declspec(dllimport)
+#endif
+#else
+#define VOODOO_API
+#endif
+
+
+typedef u32 VoodooInstanceID;
+typedef u32 VoodooMethodID;
+typedef u32 VoodooMessageSerial;
+
+#define VOODOO_INSTANCE_NONE ((VoodooInstanceID) 0)
+
+
+typedef struct __V_VoodooMessageHeader VoodooMessageHeader;
+typedef struct __V_VoodooSuperMessage VoodooSuperMessage;
+typedef struct __V_VoodooRequestMessage VoodooRequestMessage;
+typedef struct __V_VoodooResponseMessage VoodooResponseMessage;
+
+
+typedef struct __V_VoodooClient VoodooClient;
+typedef struct __V_VoodooConfig VoodooConfig;
+typedef struct __V_VoodooLink VoodooLink;
+typedef struct __V_VoodooPlayer VoodooPlayer;
+typedef struct __V_VoodooServer VoodooServer;
+
+#ifdef __cplusplus
+class VoodooConnection;
+class VoodooManager;
+class VoodooPacket;
+#else
+typedef void* VoodooManager;
+#endif
+
+
+typedef DirectResult (*VoodooSuperConstruct)( VoodooServer *server,
+ VoodooManager *manager,
+ const char *name,
+ void *ctx,
+ VoodooInstanceID *ret_instance );
+
+typedef DirectResult (*VoodooDispatch) ( void *dispatcher,
+ void *real,
+ VoodooManager *manager,
+ VoodooRequestMessage *msg );
+
+
+#define MAX_MSG_SIZE (17 * 1024)
+#define VOODOO_PACKET_MAX (MAX_MSG_SIZE)
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/unix/interfaces_unix.c b/Source/DirectFB/lib/voodoo/unix/interfaces_unix.c
new file mode 100755
index 0000000..5c3b1f8
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/unix/interfaces_unix.c
@@ -0,0 +1,237 @@
+/*
+ (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/mem.h>
+
+#include <voodoo/play.h>
+
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <net/if.h>
+
+#include <sys/ioctl.h>
+
+
+
+DirectResult
+voodoo_play_get_broadcast( VoodooPlayAddress **ret_addr,
+ size_t *ret_num )
+{
+ size_t num = 0;
+ size_t i = 0;
+ VoodooPlayAddress *addr;
+
+ int ret;
+ int fd;
+ char *ptr, lastname[IFNAMSIZ];
+ struct ifreq req[16];
+ struct ifconf conf;
+
+ D_ASSERT( ret_addr != NULL );
+ D_ASSERT( ret_num != NULL );
+
+ conf.ifc_buf = (char*) req;
+ conf.ifc_len = sizeof(req);
+
+ fd = socket( AF_INET, SOCK_DGRAM, 0 );
+ if (fd < 0) {
+ D_PERROR( "Voodoo/Unix: socket( AF_INET, SOCK_DGRAM, 0 ) failed!\n" );
+ return DR_FAILURE;
+ }
+
+ ret = ioctl( fd, SIOCGIFCONF, &conf );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFCONF ) failed!\n" );
+ close( fd );
+ return DR_FAILURE;
+ }
+
+ lastname[0] = 0;
+
+ for (ptr = conf.ifc_buf; ptr < conf.ifc_buf + conf.ifc_len; ) {
+ struct ifreq ifrcopy, *ifr = (struct ifreq *)ptr;
+ struct sockaddr_in *saddr = (struct sockaddr_in*) &ifr->ifr_broadaddr;
+
+#ifdef MACOS
+ ptr += sizeof(ifr->ifr_name) + MAX(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); // for next one in buffer
+#else
+ ptr += sizeof(req[0]);
+#endif
+
+ if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
+ continue; /* already processed this interface */
+ }
+
+ memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
+
+ ifrcopy = *ifr;
+ ioctl( fd, SIOCGIFFLAGS, &ifrcopy);
+ if ((ifrcopy.ifr_flags & IFF_UP) == 0)
+ continue; // ignore if interface not up
+
+ ret = ioctl( fd, SIOCGIFBRDADDR, ifr );
+ if (ret)
+ continue;
+
+ if (!saddr->sin_addr.s_addr) {
+ ret = ioctl( fd, SIOCGIFDSTADDR, ifr );
+ if (ret)
+ continue;
+ }
+
+ num++;
+ }
+
+
+ addr = D_CALLOC( num, sizeof(VoodooPlayAddress) );
+ if (!addr) {
+ close( fd );
+ return D_OOM();
+ }
+
+
+ for (ptr = conf.ifc_buf; ptr < conf.ifc_buf + conf.ifc_len; ) {
+ char buf[100];
+ struct ifreq ifrcopy, *ifr = (struct ifreq *)ptr;
+ struct sockaddr_in *saddr = (struct sockaddr_in*) &ifr->ifr_broadaddr;
+
+#ifdef MACOS
+ ptr += sizeof(ifr->ifr_name) + MAX(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); // for next one in buffer
+#else
+ ptr += sizeof(req[0]);
+#endif
+
+ if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
+ continue; /* already processed this interface */
+ }
+
+ memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
+
+ ifrcopy = *ifr;
+ ioctl( fd, SIOCGIFFLAGS, &ifrcopy);
+ if ((ifrcopy.ifr_flags & IFF_UP) == 0) {
+ D_INFO( "Voodoo/Player: %-16s is not up.\n", ifrcopy.ifr_name );
+ continue; // ignore if interface not up
+ }
+
+ ret = ioctl( fd, SIOCGIFBRDADDR, ifr );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFBRDADDR ) %-16s failed!\n", ifr->ifr_name );
+ continue;
+ }
+
+ if (saddr->sin_addr.s_addr) {
+ inet_ntop( AF_INET, &saddr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s)\n", ifr->ifr_name, buf );
+ }
+ else {
+ ret = ioctl( fd, SIOCGIFDSTADDR, ifr );
+ if (ret) {
+ D_PERROR( "Voodoo/Player: ioctl( SIOCGIFDSTADDR ) failed!\n" );
+ continue;
+ }
+
+ inet_ntop( AF_INET, &saddr->sin_addr, buf, sizeof(buf) );
+
+ D_INFO( "Voodoo/Player: %-16s (%s) (P-t-P)\n", ifr->ifr_name, buf );
+ }
+
+ voodoo_play_from_inet_addr( &addr[i++], saddr->sin_addr.s_addr );
+ }
+
+ close( fd );
+
+ *ret_addr = addr;
+ *ret_num = num;
+
+ return DR_OK;
+}
+
+
+
+#if 0
+
+DirectResult
+voodoo_play_get_broadcast( VoodooPlayAddress **ret_addr,
+ size_t *ret_num )
+{
+ DirectResult ret = DR_OK;
+ VoodooPlayAddress *addr;
+
+ // Get local host name
+ char szHostName[128] = "";
+
+ if (gethostname(szHostName, sizeof(szHostName))) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Win32: gethostname() failed!\n" );
+ return ret;
+ }
+
+ // Get local IP addresses
+ struct hostent *pHost = 0;
+
+ pHost = gethostbyname(szHostName);
+ if (!pHost) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Win32: gethostbyname('%s') failed!\n", szHostName );
+ return ret;
+ }
+
+
+ size_t iCnt, iTotal = 0;
+
+ for (iCnt = 0; pHost->h_addr_list[iCnt]; ++iCnt)
+ iTotal++;
+
+
+ addr = D_CALLOC( iTotal, sizeof(VoodooPlayAddress) );
+ if (!addr)
+ return D_OOM();
+
+ for (iCnt = 0; pHost->h_addr_list[iCnt]; ++iCnt) {
+ struct sockaddr_in SocketAddress;
+
+ memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[iCnt], pHost->h_length);
+
+ voodoo_play_from_inet_addr( &addr[iCnt], SocketAddress.sin_addr.s_addr );
+ }
+
+ *ret_addr = addr;
+ *ret_num = iTotal;
+
+ return DR_OK;
+}
+
+#endif
+
diff --git a/Source/DirectFB/lib/voodoo/unix/link_unix.c b/Source/DirectFB/lib/voodoo/unix/link_unix.c
new file mode 100755
index 0000000..1b6690c
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/unix/link_unix.c
@@ -0,0 +1,567 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+//#include <aio.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/client.h>
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+#include <voodoo/manager.h>
+#include <voodoo/play.h>
+
+
+#define UNIX_PATH_MAX 108
+
+
+D_DEBUG_DOMAIN( Voodoo_Link, "Voodoo/Link", "Voodoo Link" );
+
+/**********************************************************************************************************************/
+
+#if !VOODOO_BUILD_NO_SETSOCKOPT
+static const int one = 1;
+static const int tos = IPTOS_LOWDELAY;
+#endif
+
+/**********************************************************************************************************************/
+
+#define DUMP_SOCKET_OPTION(fd,o) \
+do { \
+ int val = 0; \
+ unsigned int len = 4; \
+ \
+ if (getsockopt( fd, SOL_SOCKET, o, &val, &len )) \
+ D_PERROR( "Voodoo/Manager: getsockopt() for " #o " failed!\n" ); \
+ else \
+ D_DEBUG( "Voodoo/Manager: " #o " is %d\n", val ); \
+} while (0)
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ int fd[2];
+ int wakeup_fds[2];
+} Link;
+
+static void
+Close( VoodooLink *link )
+{
+ Link *l = link->priv;
+
+ D_INFO( "Voodoo/Link: Closing connection.\n" );
+
+ close( l->fd[0] );
+
+ if (l->fd[1] != l->fd[0])
+ close( l->fd[1] );
+
+ close( l->wakeup_fds[0] );
+ close( l->wakeup_fds[1] );
+
+ D_FREE( link->priv );
+ link->priv = NULL;
+}
+
+static ssize_t
+Read( VoodooLink *link,
+ void *buffer,
+ size_t count )
+{
+ Link *l = link->priv;
+
+ return recv( l->fd[0], buffer, count, 0 );
+}
+
+static ssize_t
+Write( VoodooLink *link,
+ const void *buffer,
+ size_t count )
+{
+ Link *l = link->priv;
+
+ return send( l->fd[1], buffer, count, 0 );
+}
+
+
+// FIXME: refactor, optionally using lio_listio
+static DirectResult
+SendReceive( VoodooLink *link,
+ VoodooChunk *sends,
+ size_t num_send,
+ VoodooChunk *recvs,
+ size_t num_recv )
+{
+ Link *l = link->priv;
+ size_t i;
+ ssize_t ret;
+ int select_result;
+
+ D_DEBUG_AT( Voodoo_Link, "%s( link %p, sends %p, num_send %zu, recvs %p, num_recv %zu )\n",
+ __func__, link, sends, num_send, recvs, num_recv );
+
+ while (true) {
+ fd_set fds_read;
+ fd_set fds_write;
+ struct timeval tv;
+
+ FD_ZERO( &fds_read );
+ FD_ZERO( &fds_write );
+
+ if (num_recv)
+ FD_SET( l->fd[0], &fds_read );
+
+ if (num_send)
+ FD_SET( l->fd[1], &fds_write );
+
+ FD_SET( l->wakeup_fds[0], &fds_read );
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ D_DEBUG_AT( Voodoo_Link, " -> select( %s%s )...\n", num_recv ? "R" : " ", num_send ? "W" : " " );
+ select_result = select( MAX(MAX(l->wakeup_fds[0],l->fd[0]),l->fd[1])+1, &fds_read, &fds_write, NULL, &tv );
+ switch (select_result) {
+ default:
+ if (FD_ISSET( l->fd[1], &fds_write )) {
+ D_DEBUG_AT( Voodoo_Link, " => WRITE\n" );
+
+ for (i=0; i<num_send; i++) {
+ while (sends[i].done != sends[i].length) {
+#if 1
+ ret = send( l->fd[1], sends[i].ptr, sends[i].length, MSG_DONTWAIT );
+ if (ret < 0) {
+ D_PERROR( "Voodoo/Link: Failed to send() data!\n" );
+ return DR_IO;
+ }
+ else {
+ sends[i].done += ret;
+/*
+ if (sends[i].done != sends[i].length)
+ D_WARN( "partial send of %d/%d bytes", ret, sends[i].length );
+ else
+ D_WARN( "full send of %d bytes", ret, sends[i].length );
+*/
+ return DR_OK;
+ }
+#else
+ struct aiocb cb;
+
+ memset( &cb, 0, sizeof(struct aiocb) );
+
+ cb.aio_fildes = l->fd[1];
+ cb.aio_buf = sends[i].ptr;
+ cb.aio_nbytes = sends[i].length;
+ cb.aio_offset = (intptr_t)-1;
+ cb.aio_sigevent.sigev_notify = SIGEV_NONE;
+
+
+ ret = aio_write( &cb );
+ if (ret < 0) {
+ D_PERROR( "Voodoo/Link: aio_write() failed!\n" );
+ return DR_IO;
+ }
+ else {
+ do {
+ const struct aiocb *cbs[] = { &cb };
+
+ ret = aio_suspend( cbs, 1, NULL );
+ if (ret < 0) {
+ D_PERROR( "Voodoo/Link: aio_suspend() failed!\n" );
+ return DR_IO;
+ }
+
+ ret = aio_error( &cb );
+ } while (ret == EINPROGRESS);
+
+ switch (ret) {
+ case 0:
+ ret = aio_return( &cb );
+ if (ret < 0) {
+ D_ERROR( "Voodoo/Link: aio_return() failed!\n -> %s\n", strerror(ret) );
+ return DR_IO;
+ }
+ break;
+
+ default:
+ D_ERROR( "Voodoo/Link: aio_error() failed!\n -> %s\n", strerror(ret) );
+ return DR_IO;
+ }
+
+ sends[i].done += ret;
+/*
+ if (sends[i].done != sends[i].length)
+ D_WARN( "partial send of %d/%d bytes", ret, sends[i].length );
+ else
+ D_WARN( "full send of %d bytes", ret, sends[i].length );
+*/
+ return DR_OK;
+ }
+#endif
+ }
+ }
+ }
+
+ if (FD_ISSET( l->fd[0], &fds_read )) {
+ D_DEBUG_AT( Voodoo_Link, " => READ\n" );
+
+ for (i=0; i<num_recv; i++) {
+ ret = recv( l->fd[0], recvs[i].ptr, recvs[i].length, MSG_DONTWAIT );
+ if (ret < 0) {
+ if (errno == EAGAIN) {
+ break;
+ }
+ D_PERROR( "Voodoo/Link: Failed to recv() data!\n" );
+ return DR_FAILURE;
+ }
+
+ if (!ret)
+ return DR_IO;
+
+
+ recvs[i].done = ret;
+
+ if (recvs[i].done < recvs[i].length)
+ break;
+ }
+ }
+
+ if (FD_ISSET( l->wakeup_fds[0], &fds_read )) {
+ D_DEBUG_AT( Voodoo_Link, " => WAKE UP\n" );
+
+ static char buf[1000];
+ read( l->wakeup_fds[0], buf, sizeof(buf) );
+ if (!FD_ISSET( l->fd[0], &fds_read ) && !FD_ISSET( l->fd[0], &fds_write ))
+ return DR_INTERRUPTED;
+ }
+
+ return DR_OK;
+
+ case 0:
+ D_DEBUG_AT( Voodoo_Link, " => TIMEOUT\n" );
+ return DR_TIMEOUT;
+
+ case -1:
+ D_ERROR( "Voodoo/Link: select() failed!\n" );
+ return DR_FAILURE;
+ }
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+WakeUp( VoodooLink *link )
+{
+ Link *l = link->priv;
+ char c = 0;
+
+ write( l->wakeup_fds[1], &c, 1 );
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+voodoo_link_init_connect( VoodooLink *link,
+ const char *hostname,
+ int port,
+ bool raw )
+{
+ DirectResult ret;
+ int err;
+ struct addrinfo hints;
+ struct addrinfo *addr;
+ char portstr[10];
+ Link *l;
+
+
+ memset( &hints, 0, sizeof(hints) );
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+
+ D_INFO( "Voodoo/Link: Looking up host '%s'...\n", hostname );
+
+ snprintf( portstr, sizeof(portstr), "%d", port );
+
+ err = getaddrinfo( hostname, portstr, &hints, &addr );
+ if (err) {
+ switch (err) {
+ case EAI_FAMILY:
+ D_ERROR( "Direct/Log: Unsupported address family!\n" );
+ return DR_UNSUPPORTED;
+
+ case EAI_SOCKTYPE:
+ D_ERROR( "Direct/Log: Unsupported socket type!\n" );
+ return DR_UNSUPPORTED;
+
+ case EAI_NONAME:
+ D_ERROR( "Direct/Log: Host not found!\n" );
+ return DR_FAILURE;
+
+ case EAI_SERVICE:
+ D_ERROR( "Direct/Log: Service is unreachable!\n" );
+ return DR_FAILURE;
+
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY:
+#endif
+ case EAI_NODATA:
+ D_ERROR( "Direct/Log: Host found, but has no address!\n" );
+ return DR_FAILURE;
+
+ case EAI_MEMORY:
+ return D_OOM();
+
+ case EAI_FAIL:
+ D_ERROR( "Direct/Log: A non-recoverable name server error occurred!\n" );
+ return DR_FAILURE;
+
+ case EAI_AGAIN:
+ D_ERROR( "Direct/Log: Temporary error, try again!\n" );
+ return DR_TEMPUNAVAIL;
+
+ default:
+ D_ERROR( "Direct/Log: Unknown error occured!?\n" );
+ return DR_FAILURE;
+ }
+ }
+
+
+ l = D_CALLOC( 1, sizeof(Link) );
+ if (!l)
+ return D_OOM();
+
+ /* Create the client socket. */
+ l->fd[0] = socket( addr->ai_family, SOCK_STREAM, 0 );
+ if (l->fd[0] < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Link: Socket creation failed!\n" );
+ freeaddrinfo( addr );
+ D_FREE( l );
+ return ret;
+ }
+ l->fd[1] = l->fd[0];
+
+#if !VOODOO_BUILD_NO_SETSOCKOPT
+// if (setsockopt( l->fd[0], SOL_IP, IP_TOS, &tos, sizeof(tos) ) < 0)
+// D_PERROR( "Voodoo/Manager: Could not set IP_TOS!\n" );
+
+ if (setsockopt( l->fd[0], SOL_TCP, TCP_NODELAY, &one, sizeof(one) ) < 0)
+ D_PERROR( "Voodoo/Manager: Could not set TCP_NODELAY!\n" );
+#endif
+
+ D_INFO( "Voodoo/Link: Connecting to '%s:%d'...\n", addr->ai_canonname, port );
+
+ /* Connect to the server. */
+ err = connect( l->fd[0], addr->ai_addr, addr->ai_addrlen );
+ freeaddrinfo( addr );
+
+ if (err) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Link: Socket connect failed!\n" );
+ close( l->fd[0] );
+ D_FREE( l );
+ return ret;
+ }
+
+ D_INFO( "Voodoo/Link: Connected.\n" );
+
+ DUMP_SOCKET_OPTION( l->fd[0], SO_SNDLOWAT );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_RCVLOWAT );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_SNDBUF );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_RCVBUF );
+
+ if (!raw) {
+ link->code = 0x80008676;
+
+ if (write( l->fd[1], &link->code, sizeof(link->code) ) != 4) {
+ D_ERROR( "Voodoo/Link: Coult not write initial four bytes!\n" );
+ close( l->fd[0] );
+ D_FREE( l );
+ return DR_IO;
+ }
+ }
+ D_INFO( "Voodoo/Link: Sent link code (%s).\n", raw ? "raw" : "packet" );
+
+ pipe( l->wakeup_fds );
+
+
+ link->priv = l;
+ link->Close = Close;
+ link->Read = Read;
+ link->Write = Write;
+ link->SendReceive = SendReceive;
+ link->WakeUp = WakeUp;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_link_init_local( VoodooLink *link,
+ const char *path,
+ bool raw )
+{
+ DirectResult ret;
+ int err;
+ struct sockaddr_un addr;
+ Link *l;
+
+ D_ASSERT( link != NULL );
+ D_ASSERT( path != NULL );
+
+ l = D_CALLOC( 1, sizeof(Link) );
+ if (!l)
+ return D_OOM();
+
+ /* Create the client socket. */
+ l->fd[0] = socket( AF_LOCAL, SOCK_STREAM, 0 );
+ if (l->fd[0] < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Link: Socket creation failed!\n" );
+ D_FREE( l );
+ return ret;
+ }
+ l->fd[1] = l->fd[0];
+
+#if !VOODOO_BUILD_NO_SETSOCKOPT
+// if (setsockopt( l->fd[0], SOL_IP, IP_TOS, &tos, sizeof(tos) ) < 0)
+// D_PERROR( "Voodoo/Manager: Could not set IP_TOS!\n" );
+
+ if (setsockopt( l->fd[0], SOL_TCP, TCP_NODELAY, &one, sizeof(one) ) < 0)
+ D_PERROR( "Voodoo/Manager: Could not set TCP_NODELAY!\n" );
+#endif
+
+ D_INFO( "Voodoo/Link: Connecting to '%s'...\n", path );
+
+
+ memset( &addr, 0, sizeof(addr) );
+
+ /* Bind the socket to the local port. */
+ addr.sun_family = AF_UNIX;
+
+ snprintf( addr.sun_path + 1, UNIX_PATH_MAX - 1, "%s", path );
+
+ /* Connect to the server. */
+ err = connect( l->fd[0], (struct sockaddr*) &addr, strlen(addr.sun_path+1)+1 + sizeof(addr.sun_family) );
+ if (err) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Link: Socket connect failed!\n" );
+ close( l->fd[0] );
+ D_FREE( l );
+ return ret;
+ }
+
+ D_INFO( "Voodoo/Link: Connected.\n" );
+
+ DUMP_SOCKET_OPTION( l->fd[0], SO_SNDLOWAT );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_RCVLOWAT );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_SNDBUF );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_RCVBUF );
+
+ if (!raw) {
+ link->code = 0x80008676;
+
+ if (write( l->fd[1], &link->code, sizeof(link->code) ) != 4) {
+ D_ERROR( "Voodoo/Link: Coult not write initial four bytes!\n" );
+ close( l->fd[0] );
+ D_FREE( l );
+ return DR_IO;
+ }
+ }
+ D_INFO( "Voodoo/Link: Sent link code (%s).\n", raw ? "raw" : "packet" );
+
+ pipe( l->wakeup_fds );
+
+
+ link->priv = l;
+ link->Close = Close;
+ link->Read = Read;
+ link->Write = Write;
+ link->SendReceive = SendReceive;
+ link->WakeUp = WakeUp;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_link_init_fd( VoodooLink *link,
+ int fd[2] )
+{
+ Link *l;
+
+ if (read( fd[0], &link->code, sizeof(link->code) ) != 4) {
+ D_ERROR( "Voodoo/Link: Coult not read initial four bytes!\n" );
+ return DR_IO;
+ }
+
+ l = D_CALLOC( 1, sizeof(Link) );
+ if (!l)
+ return D_OOM();
+
+ l->fd[0] = fd[0];
+ l->fd[1] = fd[1];
+
+ pipe( l->wakeup_fds );
+
+ link->priv = l;
+ link->Close = Close;
+ link->Read = Read;
+ link->Write = Write;
+ link->SendReceive = SendReceive;
+ link->WakeUp = WakeUp;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/unix/link_unix_1408limit.c b/Source/DirectFB/lib/voodoo/unix/link_unix_1408limit.c
new file mode 100755
index 0000000..790aa99
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/unix/link_unix_1408limit.c
@@ -0,0 +1,422 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/client.h>
+#include <voodoo/conf.h>
+#include <voodoo/internal.h>
+#include <voodoo/link.h>
+#include <voodoo/manager.h>
+#include <voodoo/play.h>
+
+
+D_DEBUG_DOMAIN( Voodoo_Link, "Voodoo/Link", "Voodoo Link" );
+
+/**********************************************************************************************************************/
+
+#if !VOODOO_BUILD_NO_SETSOCKOPT
+static const int one = 1;
+static const int tos = IPTOS_LOWDELAY;
+#endif
+
+/**********************************************************************************************************************/
+
+#define DUMP_SOCKET_OPTION(fd,o) \
+do { \
+ int val = 0; \
+ unsigned int len = 4; \
+ \
+ if (getsockopt( fd, SOL_SOCKET, o, &val, &len )) \
+ D_PERROR( "Voodoo/Manager: getsockopt() for " #o " failed!\n" ); \
+ else \
+ D_DEBUG( "Voodoo/Manager: " #o " is %d\n", val ); \
+} while (0)
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ int fd[2];
+ int wakeup_fds[2];
+} Link;
+
+static void
+Close( VoodooLink *link )
+{
+ Link *l = link->priv;
+
+ D_INFO( "Voodoo/Link: Closing connection.\n" );
+
+ close( l->fd[0] );
+
+ if (l->fd[1] != l->fd[0])
+ close( l->fd[1] );
+
+ D_FREE( link->priv );
+ link->priv = NULL;
+}
+
+static ssize_t
+Read( VoodooLink *link,
+ void *buffer,
+ size_t count )
+{
+ Link *l = link->priv;
+
+ return recv( l->fd[0], buffer, count, 0 );
+}
+
+static ssize_t
+Write( VoodooLink *link,
+ const void *buffer,
+ size_t count )
+{
+ Link *l = link->priv;
+
+ return send( l->fd[1], buffer, count, 0 );
+}
+
+
+// FIXME: refactor, optionally using lio_listio
+static DirectResult
+SendReceive( VoodooLink *link,
+ VoodooChunk *sends,
+ size_t num_send,
+ VoodooChunk *recvs,
+ size_t num_recv )
+{
+ Link *l = link->priv;
+ size_t i;
+ ssize_t ret;
+ int select_result;
+
+ D_DEBUG_AT( Voodoo_Link, "%s( link %p, sends %p, num_send %zu, recvs %p, num_recv %zu )\n",
+ __func__, link, sends, num_send, recvs, num_recv );
+
+ while (true) {
+ fd_set fds_read;
+ fd_set fds_write;
+ struct timeval tv;
+
+ FD_ZERO( &fds_read );
+ FD_ZERO( &fds_write );
+
+ if (num_recv)
+ FD_SET( l->fd[0], &fds_read );
+
+ if (num_send)
+ FD_SET( l->fd[1], &fds_write );
+
+ FD_SET( l->wakeup_fds[0], &fds_read );
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ D_DEBUG_AT( Voodoo_Link, " -> select( %s%s )...\n", num_recv ? "R" : " ", num_send ? "W" : " " );
+ select_result = select( MAX(MAX(l->wakeup_fds[0],l->fd[0]),l->fd[1])+1, &fds_read, &fds_write, NULL, &tv );
+ switch (select_result) {
+ default:
+ if (FD_ISSET( l->fd[1], &fds_write )) {
+ D_DEBUG_AT( Voodoo_Link, " => WRITE\n" );
+
+ for (i=0; i<num_send; i++) {
+ while (sends[i].done != sends[i].length) {
+ ret = send( l->fd[1], sends[i].ptr, sends[i].length, MSG_DONTWAIT );
+ if (ret < 0) {
+ //if (errno == EAGAIN) {
+ // break;
+ //}
+ D_PERROR( "Voodoo/Link: Failed to send() data!\n" );
+ return DR_FAILURE;
+ }
+ else {
+ sends[i].done += ret;
+/*
+ if (sends[i].done != sends[i].length)
+ D_WARN( "partial send of %d/%d bytes", ret, sends[i].length );
+ else
+ D_WARN( "full send of %d bytes", ret, sends[i].length );
+*/
+// return DR_OK;
+ break;
+ }
+ }
+ }
+ }
+
+ if (FD_ISSET( l->fd[0], &fds_read )) {
+ D_DEBUG_AT( Voodoo_Link, " => READ\n" );
+
+ for (i=0; i<num_recv; i++) {
+ ret = recv( l->fd[0], recvs[i].ptr, recvs[i].length, MSG_DONTWAIT );
+ if (ret < 0) {
+ if (errno == EAGAIN) {
+ break;
+ }
+ D_PERROR( "Voodoo/Link: Failed to recv() data!\n" );
+ return DR_FAILURE;
+ }
+
+ if (!ret)
+ return DR_IO;
+
+
+ recvs[i].done = ret;
+
+ if (recvs[i].done < recvs[i].length)
+ break;
+ }
+ }
+
+ if (FD_ISSET( l->wakeup_fds[0], &fds_read )) {
+ D_DEBUG_AT( Voodoo_Link, " => WAKE UP\n" );
+
+ static char buf[1000];
+ read( l->wakeup_fds[0], buf, sizeof(buf) );
+ if (!FD_ISSET( l->fd[0], &fds_read ) && !FD_ISSET( l->fd[0], &fds_write ))
+ return DR_INTERRUPTED;
+ }
+
+ return DR_OK;
+
+ case 0:
+ D_DEBUG_AT( Voodoo_Link, " => TIMEOUT\n" );
+ return DR_TIMEOUT;
+
+ case -1:
+ D_ERROR( "Voodoo/Link: select() failed!\n" );
+ return DR_FAILURE;
+ }
+ }
+
+ return DR_OK;
+}
+
+static DirectResult
+WakeUp( VoodooLink *link )
+{
+ Link *l = link->priv;
+ char c = 0;
+
+ write( l->wakeup_fds[1], &c, 1 );
+
+ return DR_OK;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+voodoo_link_init_connect( VoodooLink *link,
+ const char *hostname,
+ int port,
+ bool raw )
+{
+ DirectResult ret;
+ int err;
+ struct addrinfo hints;
+ struct addrinfo *addr;
+ char portstr[10];
+ Link *l;
+
+
+ memset( &hints, 0, sizeof(hints) );
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+
+ D_INFO( "Voodoo/Link: Looking up host '%s'...\n", hostname );
+
+ snprintf( portstr, sizeof(portstr), "%d", port );
+
+ err = getaddrinfo( hostname, portstr, &hints, &addr );
+ if (err) {
+ switch (err) {
+ case EAI_FAMILY:
+ D_ERROR( "Direct/Log: Unsupported address family!\n" );
+ return DR_UNSUPPORTED;
+
+ case EAI_SOCKTYPE:
+ D_ERROR( "Direct/Log: Unsupported socket type!\n" );
+ return DR_UNSUPPORTED;
+
+ case EAI_NONAME:
+ D_ERROR( "Direct/Log: Host not found!\n" );
+ return DR_FAILURE;
+
+ case EAI_SERVICE:
+ D_ERROR( "Direct/Log: Service is unreachable!\n" );
+ return DR_FAILURE;
+
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY:
+#endif
+ case EAI_NODATA:
+ D_ERROR( "Direct/Log: Host found, but has no address!\n" );
+ return DR_FAILURE;
+
+ case EAI_MEMORY:
+ return D_OOM();
+
+ case EAI_FAIL:
+ D_ERROR( "Direct/Log: A non-recoverable name server error occurred!\n" );
+ return DR_FAILURE;
+
+ case EAI_AGAIN:
+ D_ERROR( "Direct/Log: Temporary error, try again!\n" );
+ return DR_TEMPUNAVAIL;
+
+ default:
+ D_ERROR( "Direct/Log: Unknown error occured!?\n" );
+ return DR_FAILURE;
+ }
+ }
+
+
+ l = D_CALLOC( 1, sizeof(Link) );
+ if (!l)
+ return D_OOM();
+
+ /* Create the client socket. */
+ l->fd[0] = socket( addr->ai_family, SOCK_STREAM, 0 );
+ if (l->fd[0] < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Link: Socket creation failed!\n" );
+ freeaddrinfo( addr );
+ D_FREE( l );
+ return ret;
+ }
+ l->fd[1] = l->fd[0];
+
+#if !VOODOO_BUILD_NO_SETSOCKOPT
+ if (setsockopt( l->fd[0], SOL_IP, IP_TOS, &tos, sizeof(tos) ) < 0)
+ D_PERROR( "Voodoo/Manager: Could not set IP_TOS!\n" );
+
+ if (setsockopt( l->fd[0], SOL_TCP, TCP_NODELAY, &one, sizeof(one) ) < 0)
+ D_PERROR( "Voodoo/Manager: Could not set TCP_NODELAY!\n" );
+#endif
+
+ D_INFO( "Voodoo/Link: Connecting to '%s:%d'...\n", addr->ai_canonname, port );
+
+ /* Connect to the server. */
+ err = connect( l->fd[0], addr->ai_addr, addr->ai_addrlen );
+ freeaddrinfo( addr );
+
+ if (err) {
+ ret = errno2result( errno );
+ D_PERROR( "Voodoo/Link: Socket connect failed!\n" );
+ close( l->fd[0] );
+ D_FREE( l );
+ return ret;
+ }
+
+ D_INFO( "Voodoo/Link: Connected.\n" );
+
+ DUMP_SOCKET_OPTION( l->fd[0], SO_SNDLOWAT );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_RCVLOWAT );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_SNDBUF );
+ DUMP_SOCKET_OPTION( l->fd[0], SO_RCVBUF );
+
+ if (!raw) {
+ link->code = 0x80008676;
+
+ if (write( l->fd[1], &link->code, sizeof(link->code) ) != 4) {
+ D_ERROR( "Voodoo/Link: Coult not write initial four bytes!\n" );
+ close( l->fd[0] );
+ D_FREE( l );
+ return DR_IO;
+ }
+ }
+ D_INFO( "Voodoo/Link: Sent link code (%s).\n", raw ? "raw" : "packet" );
+
+ pipe( l->wakeup_fds );
+
+
+ link->priv = l;
+ link->Close = Close;
+ link->Read = Read;
+ link->Write = Write;
+ link->SendReceive = SendReceive;
+ link->WakeUp = WakeUp;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_link_init_fd( VoodooLink *link,
+ int fd[2] )
+{
+ Link *l;
+
+ if (read( fd[0], &link->code, sizeof(link->code) ) != 4) {
+ D_ERROR( "Voodoo/Link: Coult not read initial four bytes!\n" );
+ return DR_IO;
+ }
+
+ l = D_CALLOC( 1, sizeof(Link) );
+ if (!l)
+ return D_OOM();
+
+ l->fd[0] = fd[0];
+ l->fd[1] = fd[1];
+
+ pipe( l->wakeup_fds );
+
+ link->priv = l;
+ link->Close = Close;
+ link->Read = Read;
+ link->Write = Write;
+ link->SendReceive = SendReceive;
+ link->WakeUp = WakeUp;
+
+ return DR_OK;
+}
+
diff --git a/Source/DirectFB/lib/voodoo/voodoo.pc.in b/Source/DirectFB/lib/voodoo/voodoo.pc.in
new file mode 100755
index 0000000..8e29024
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/voodoo.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Voodoo
+Description: Interface based network transparency (like CORBA)
+Version: @VERSION@
+Requires: direct
+Libs: -L${libdir} -lvoodoo
+Cflags: -I@INCLUDEDIR@
diff --git a/Source/DirectFB/lib/voodoo/waitqueue.h b/Source/DirectFB/lib/voodoo/waitqueue.h
new file mode 100755
index 0000000..ab163ce
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/waitqueue.h
@@ -0,0 +1,117 @@
+/*
+ (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __DIRECT__OS__LINUX__GLIBC__WAITQUEUE_H__
+#define __DIRECT__OS__LINUX__GLIBC__WAITQUEUE_H__
+
+#include <pthread.h>
+
+#include <direct/util.h>
+
+#include "mutex.h"
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ pthread_cond_t cond;
+} DirectWaitQueue;
+
+/**********************************************************************************************************************/
+
+#define DIRECT_WAITQUEUE_INITIALIZER(name) { PTHREAD_COND_INITIALIZER }
+
+/**********************************************************************************************************************/
+
+static inline DirectResult
+direct_waitqueue_init( DirectWaitQueue *queue )
+{
+ if (pthread_cond_init( &queue->cond, NULL ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_waitqueue_wait( DirectWaitQueue *queue, DirectMutex *mutex )
+{
+ if (pthread_cond_wait( &queue->cond, &mutex->lock ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_waitqueue_wait_timeout( DirectWaitQueue *queue, DirectMutex *mutex, unsigned long micros )
+{
+ struct timeval now;
+ struct timespec timeout;
+ long int nano_seconds = micros * 1000;
+
+ gettimeofday( &now, NULL );
+
+ timeout.tv_sec = now.tv_sec;
+ timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;
+
+ timeout.tv_sec += timeout.tv_nsec / 1000000000;
+ timeout.tv_nsec %= 1000000000;
+
+ if (pthread_cond_timedwait( &queue->cond, &mutex->lock, &timeout ) == ETIMEDOUT)
+ return DR_TIMEOUT;
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_waitqueue_signal( DirectWaitQueue *queue )
+{
+ if (pthread_cond_signal( &queue->cond ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_waitqueue_broadcast( DirectWaitQueue *queue )
+{
+ if (pthread_cond_broadcast( &queue->cond ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+static inline DirectResult
+direct_waitqueue_deinit( DirectWaitQueue *queue )
+{
+ if (pthread_cond_destroy( &queue->cond ))
+ return errno2result( errno );
+
+ return DR_OK;
+}
+
+#endif
+