From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/lib/direct/Makefile.am | 138 ++ Source/DirectFB/lib/direct/Makefile.in | 769 +++++++ Source/DirectFB/lib/direct/armasm_memcpy.S | 421 ++++ Source/DirectFB/lib/direct/armasm_memcpy.h | 32 + Source/DirectFB/lib/direct/build.h.in | 51 + Source/DirectFB/lib/direct/clock.c | 135 ++ Source/DirectFB/lib/direct/clock.h | 45 + Source/DirectFB/lib/direct/conf.c | 348 +++ Source/DirectFB/lib/direct/conf.h | 92 + Source/DirectFB/lib/direct/debug.c | 430 ++++ Source/DirectFB/lib/direct/debug.h | 287 +++ Source/DirectFB/lib/direct/direct.c | 197 ++ Source/DirectFB/lib/direct/direct.h | 49 + Source/DirectFB/lib/direct/direct.pc.in | 13 + Source/DirectFB/lib/direct/fastlz.c | 97 + Source/DirectFB/lib/direct/fastlz.h | 52 + Source/DirectFB/lib/direct/flz.c | 555 +++++ Source/DirectFB/lib/direct/flz.h | 100 + Source/DirectFB/lib/direct/hash.c | 268 +++ Source/DirectFB/lib/direct/hash.h | 61 + Source/DirectFB/lib/direct/interface.c | 474 ++++ Source/DirectFB/lib/direct/interface.h | 215 ++ .../DirectFB/lib/direct/interface_implementation.h | 91 + Source/DirectFB/lib/direct/list.c | 35 + Source/DirectFB/lib/direct/list.h | 224 ++ Source/DirectFB/lib/direct/log.c | 414 ++++ Source/DirectFB/lib/direct/log.h | 89 + Source/DirectFB/lib/direct/mem.c | 350 +++ Source/DirectFB/lib/direct/mem.h | 84 + Source/DirectFB/lib/direct/memcpy.c | 265 +++ Source/DirectFB/lib/direct/memcpy.h | 51 + Source/DirectFB/lib/direct/messages.c | 215 ++ Source/DirectFB/lib/direct/messages.h | 173 ++ Source/DirectFB/lib/direct/modules.c | 463 ++++ Source/DirectFB/lib/direct/modules.h | 95 + Source/DirectFB/lib/direct/ppc_asm.h | 115 + Source/DirectFB/lib/direct/ppcasm_memcpy.S | 77 + Source/DirectFB/lib/direct/ppcasm_memcpy.h | 7 + .../DirectFB/lib/direct/ppcasm_memcpy_cachable.S | 180 ++ Source/DirectFB/lib/direct/serial.h | 118 + Source/DirectFB/lib/direct/signals.c | 480 ++++ Source/DirectFB/lib/direct/signals.h | 70 + Source/DirectFB/lib/direct/stream.c | 2286 ++++++++++++++++++++ Source/DirectFB/lib/direct/stream.h | 129 ++ Source/DirectFB/lib/direct/system.c | 68 + Source/DirectFB/lib/direct/system.h | 40 + Source/DirectFB/lib/direct/thread.c | 795 +++++++ Source/DirectFB/lib/direct/thread.h | 168 ++ Source/DirectFB/lib/direct/trace.c | 676 ++++++ Source/DirectFB/lib/direct/trace.h | 98 + Source/DirectFB/lib/direct/tree.c | 307 +++ Source/DirectFB/lib/direct/tree.h | 67 + Source/DirectFB/lib/direct/types.h | 169 ++ Source/DirectFB/lib/direct/utf8.c | 36 + Source/DirectFB/lib/direct/utf8.h | 80 + Source/DirectFB/lib/direct/util.c | 519 +++++ Source/DirectFB/lib/direct/util.h | 330 +++ 57 files changed, 14193 insertions(+) create mode 100755 Source/DirectFB/lib/direct/Makefile.am create mode 100755 Source/DirectFB/lib/direct/Makefile.in create mode 100755 Source/DirectFB/lib/direct/armasm_memcpy.S create mode 100755 Source/DirectFB/lib/direct/armasm_memcpy.h create mode 100755 Source/DirectFB/lib/direct/build.h.in create mode 100755 Source/DirectFB/lib/direct/clock.c create mode 100755 Source/DirectFB/lib/direct/clock.h create mode 100755 Source/DirectFB/lib/direct/conf.c create mode 100755 Source/DirectFB/lib/direct/conf.h create mode 100755 Source/DirectFB/lib/direct/debug.c create mode 100755 Source/DirectFB/lib/direct/debug.h create mode 100755 Source/DirectFB/lib/direct/direct.c create mode 100755 Source/DirectFB/lib/direct/direct.h create mode 100755 Source/DirectFB/lib/direct/direct.pc.in create mode 100755 Source/DirectFB/lib/direct/fastlz.c create mode 100755 Source/DirectFB/lib/direct/fastlz.h create mode 100755 Source/DirectFB/lib/direct/flz.c create mode 100755 Source/DirectFB/lib/direct/flz.h create mode 100755 Source/DirectFB/lib/direct/hash.c create mode 100755 Source/DirectFB/lib/direct/hash.h create mode 100755 Source/DirectFB/lib/direct/interface.c create mode 100755 Source/DirectFB/lib/direct/interface.h create mode 100755 Source/DirectFB/lib/direct/interface_implementation.h create mode 100755 Source/DirectFB/lib/direct/list.c create mode 100755 Source/DirectFB/lib/direct/list.h create mode 100755 Source/DirectFB/lib/direct/log.c create mode 100755 Source/DirectFB/lib/direct/log.h create mode 100755 Source/DirectFB/lib/direct/mem.c create mode 100755 Source/DirectFB/lib/direct/mem.h create mode 100755 Source/DirectFB/lib/direct/memcpy.c create mode 100755 Source/DirectFB/lib/direct/memcpy.h create mode 100755 Source/DirectFB/lib/direct/messages.c create mode 100755 Source/DirectFB/lib/direct/messages.h create mode 100755 Source/DirectFB/lib/direct/modules.c create mode 100755 Source/DirectFB/lib/direct/modules.h create mode 100755 Source/DirectFB/lib/direct/ppc_asm.h create mode 100755 Source/DirectFB/lib/direct/ppcasm_memcpy.S create mode 100755 Source/DirectFB/lib/direct/ppcasm_memcpy.h create mode 100755 Source/DirectFB/lib/direct/ppcasm_memcpy_cachable.S create mode 100755 Source/DirectFB/lib/direct/serial.h create mode 100755 Source/DirectFB/lib/direct/signals.c create mode 100755 Source/DirectFB/lib/direct/signals.h create mode 100755 Source/DirectFB/lib/direct/stream.c create mode 100755 Source/DirectFB/lib/direct/stream.h create mode 100755 Source/DirectFB/lib/direct/system.c create mode 100755 Source/DirectFB/lib/direct/system.h create mode 100755 Source/DirectFB/lib/direct/thread.c create mode 100755 Source/DirectFB/lib/direct/thread.h create mode 100755 Source/DirectFB/lib/direct/trace.c create mode 100755 Source/DirectFB/lib/direct/trace.h create mode 100755 Source/DirectFB/lib/direct/tree.c create mode 100755 Source/DirectFB/lib/direct/tree.h create mode 100755 Source/DirectFB/lib/direct/types.h create mode 100755 Source/DirectFB/lib/direct/utf8.c create mode 100755 Source/DirectFB/lib/direct/utf8.h create mode 100755 Source/DirectFB/lib/direct/util.c create mode 100755 Source/DirectFB/lib/direct/util.h (limited to 'Source/DirectFB/lib/direct') 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 + +#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 , + Andreas Hundt , + Sven Neumann and + Ville Syrjälä . + + 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include + +#ifdef CLOCK_MONOTONIC +#include +#endif +#include +#include + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +#include +#include +#include + + +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= Skip memcpy() probing (help = show list)\n" + " [no-]quiet Disable text output except debug messages or direct logs\n" + " [no-]quiet= 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= Write all messages to a file\n" + " log-udp=: Send all messages via UDP to host:port\n" + " fatal-level= Abort on NONE, ASSERT (default) or ASSUME (incl. assert)\n" + " [no-]fatal-break Abort on BREAK (default)\n" + " dont-catch=[[,]...] 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= suppress loading this module\n" + " module-dir= 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#if HAVE_SIGNAL_H +#include +#else +#include +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +#include +#include + +#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, + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +/**********************************************************************************************************************/ + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include +#include +#include +#include + + +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; isize; 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; isize; 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#ifndef USE_KOS +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; iname, + 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; iinterface == 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + +/* + * 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include + + 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +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:'!\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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + + +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 : + */ +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + + +#if DIRECT_BUILD_DEBUGS /* Build with debug support? */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +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; ibytes, 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; imem == 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; imem == 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +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 +#include + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + + +#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 + +#include + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef PIC +#define DYNAMIC_LINKING +#endif + +#ifdef DYNAMIC_LINKING +#include +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include + + +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 + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; isighandler && !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, + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 +#include + +#include + +/* + * Create a stream wrapper. + * + * 'filename' can be a plain file name or one of the following: + * http://[:]/ + * unsv://[:]/ + * ftp://[:]/ + * rtsp://[:]/ + * tcp://: + * udp://: + * file:/ + * fd:/ + * 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +#include +#include + +#if DIRECT_BUILD_GETTID && defined(HAVE_LINUX_UNISTD_H) +#include +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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, ¶m )) + 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, ¶m ); + + 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 ""; +} + +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 ""; +} + +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 ""; +} +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef PIC +#define DYNAMIC_LINKING +#endif + + +#if DIRECT_BUILD_TRACE + +#ifdef DYNAMIC_LINKING +#include +#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; itid = 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= '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; ilevel) + 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +/*********************************************************************************************************************** +** 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include +#include + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + Balanced binary tree ported from glib by Sven Neumann + . + + 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 + + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +/* + * Define the bool type by including stdbool.h (preferably)... + */ +#if DIRECT_BUILD_STDBOOL +# include +/* + * ...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 + +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 + +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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + + + 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CLOCK_MONOTONIC +#include +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#ifdef _POSIX_PRIORITY_SCHEDULING +#include +#endif + +#include + +#include +#include + + +#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 -- cgit