diff options
Diffstat (limited to 'Source/DirectFB/lib/fusion/shm')
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/Makefile.am | 31 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/Makefile.in | 565 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/fake.c | 163 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/heap.c | 802 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/pool.c | 954 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/pool.h | 69 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/shm.c | 337 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/shm.h | 48 | ||||
-rwxr-xr-x | Source/DirectFB/lib/fusion/shm/shm_internal.h | 264 |
9 files changed, 3233 insertions, 0 deletions
diff --git a/Source/DirectFB/lib/fusion/shm/Makefile.am b/Source/DirectFB/lib/fusion/shm/Makefile.am new file mode 100755 index 0000000..23ed4a5 --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/Makefile.am @@ -0,0 +1,31 @@ +## Makefile.am for DirectFB/lib/fusion/shm + +INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib + +AM_CPPFLAGS = \ + -DDATADIR=\"@DATADIR@\" \ + -DMODULEDIR=\"@MODULEDIR@\" + +if ENABLE_MULTI +SHMSOURCES = heap.c pool.c shm.c +else +SHMSOURCES = fake.c +endif + +EXTRA_DIST = fake.c + +noinst_LTLIBRARIES = libfusion_shm.la + +libfusion_shm_la_SOURCES = \ + $(SHMSOURCES) + +includedir = @INCLUDEDIR@/fusion/shm + +include_HEADERS = \ + pool.h \ + shm.h \ + shm_internal.h diff --git a/Source/DirectFB/lib/fusion/shm/Makefile.in b/Source/DirectFB/lib/fusion/shm/Makefile.in new file mode 100755 index 0000000..987fa8f --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/Makefile.in @@ -0,0 +1,565 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = lib/fusion/shm +DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libfusion_shm_la_LIBADD = +am__libfusion_shm_la_SOURCES_DIST = fake.c heap.c pool.c shm.c +@ENABLE_MULTI_FALSE@am__objects_1 = fake.lo +@ENABLE_MULTI_TRUE@am__objects_1 = heap.lo pool.lo shm.lo +am_libfusion_shm_la_OBJECTS = $(am__objects_1) +libfusion_shm_la_OBJECTS = $(am_libfusion_shm_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libfusion_shm_la_SOURCES) +DIST_SOURCES = $(am__libfusion_shm_la_SOURCES_DIST) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(includedir)" +includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @INCLUDEDIR@/fusion/shm +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib + +AM_CPPFLAGS = \ + -DDATADIR=\"@DATADIR@\" \ + -DMODULEDIR=\"@MODULEDIR@\" + +@ENABLE_MULTI_FALSE@SHMSOURCES = fake.c +@ENABLE_MULTI_TRUE@SHMSOURCES = heap.c pool.c shm.c +EXTRA_DIST = fake.c +noinst_LTLIBRARIES = libfusion_shm.la +libfusion_shm_la_SOURCES = \ + $(SHMSOURCES) + +include_HEADERS = \ + pool.h \ + shm.h \ + shm_internal.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/fusion/shm/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu lib/fusion/shm/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libfusion_shm.la: $(libfusion_shm_la_OBJECTS) $(libfusion_shm_la_DEPENDENCIES) + $(LINK) $(libfusion_shm_la_OBJECTS) $(libfusion_shm_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shm.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-includeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/lib/fusion/shm/fake.c b/Source/DirectFB/lib/fusion/shm/fake.c new file mode 100755 index 0000000..32e25cd --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/fake.c @@ -0,0 +1,163 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <config.h> + +#include <direct/debug.h> +#include <direct/mem.h> +#include <direct/messages.h> + +#include <fusion/shm/shm.h> +#include <fusion/shm/pool.h> + +#include <fusion/shm/shm_internal.h> + + +DirectResult +fusion_shm_pool_create( FusionWorld *world, + const char *name, + unsigned int max_size, + bool debug, + FusionSHMPoolShared **ret_pool ) +{ + FusionSHMPoolShared *pool; + +#if !DIRECT_BUILD_DEBUGS + debug = false; +#endif + + pool = D_CALLOC( 1, sizeof(FusionSHMPoolShared) ); + if (!pool) + return D_OOM(); + + pool->debug = debug; + + D_MAGIC_SET( pool, FusionSHMPoolShared ); + + *ret_pool = pool; + + return DR_OK; +} + +DirectResult +fusion_shm_pool_destroy( FusionWorld *world, + FusionSHMPoolShared *pool ) +{ + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + D_MAGIC_CLEAR( pool ); + + D_FREE( pool ); + + return DR_OK; +} + +DirectResult +fusion_shm_pool_attach( FusionSHM *shm, + FusionSHMPoolShared *pool ) +{ + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + pool->index++; + + return DR_OK; +} + +DirectResult +fusion_shm_pool_detach( FusionSHM *shm, + FusionSHMPoolShared *pool ) +{ + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + D_ASSERT( pool->index > 0 ); + + pool->index--; + + return DR_OK; +} + +DirectResult +fusion_shm_pool_allocate( FusionSHMPoolShared *pool, + int size, + bool clear, + bool lock, + void **ret_data ) +{ + void *data; + + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + data = clear ? D_CALLOC( 1, size ) : D_MALLOC( size ); + if (!data) + return DR_NOSHAREDMEMORY; + + *ret_data = data; + + return DR_OK; +} + +DirectResult +fusion_shm_pool_reallocate( FusionSHMPoolShared *pool, + void *data, + int size, + bool lock, + void **ret_data ) +{ + void *new_data; + + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + new_data = D_REALLOC( data, size ); + if (!new_data) + return DR_NOSHAREDMEMORY; + + *ret_data = new_data; + + return DR_OK; +} + +DirectResult +fusion_shm_pool_deallocate( FusionSHMPoolShared *pool, + void *data, + bool lock ) +{ + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + D_FREE( data ); + + return DR_OK; +} + +DirectResult +fusion_shm_enum_pools( FusionWorld *world, + FusionSHMPoolCallback callback, + void *ctx ) +{ + return DR_OK; +} + diff --git a/Source/DirectFB/lib/fusion/shm/heap.c b/Source/DirectFB/lib/fusion/shm/heap.c new file mode 100755 index 0000000..4a76229 --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/heap.c @@ -0,0 +1,802 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* Heap management adapted from libc + Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include <config.h> + +#include <unistd.h> + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> + +#include <direct/debug.h> +#include <direct/list.h> +#include <direct/mem.h> +#include <direct/memcpy.h> +#include <direct/messages.h> +#include <direct/util.h> + +#include <fusion/conf.h> +#include <fusion/shmalloc.h> +#include <fusion/fusion_internal.h> + +#include <fusion/shm/pool.h> +#include <fusion/shm/shm_internal.h> + + +D_DEBUG_DOMAIN( Fusion_SHMHeap, "Fusion/SHMHeap", "Fusion Shared Memory Heap" ); + +/**********************************************************************************************************************/ + +/* Aligned allocation. */ +static void * +align( shmalloc_heap *heap, size_t size ) +{ + void *result; + unsigned long adj; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %zu )\n", __FUNCTION__, heap, size ); + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + result = __shmalloc_brk( heap, size ); + + adj = (unsigned long) result % BLOCKSIZE; + if (adj != 0) { + adj = BLOCKSIZE - adj; + __shmalloc_brk( heap, adj ); + result = (char *) result + adj; + } + + return result; +} + +/* Get neatly aligned memory, initializing or + growing the heap info table as necessary. */ +static void * +morecore( shmalloc_heap *heap, size_t size ) +{ + void *result; + shmalloc_info *newinfo, *oldinfo; + size_t newsize; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %zu )\n", __FUNCTION__, heap, size ); + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + result = align( heap, size ); + if (result == NULL) + return NULL; + + /* Check if we need to grow the info table. */ + if ((size_t) BLOCK ((char *) result + size) > heap->heapsize) { + newsize = heap->heapsize; + + while ((size_t) BLOCK ((char *) result + size) > newsize) + newsize *= 2; + + newinfo = (shmalloc_info *) align( heap, newsize * sizeof (shmalloc_info) ); + if (newinfo == NULL) { + __shmalloc_brk( heap, -size ); + return NULL; + } + + direct_memcpy( newinfo, heap->heapinfo, + heap->heapsize * sizeof (shmalloc_info) ); + + memset (newinfo + heap->heapsize, + 0, (newsize - heap->heapsize) * sizeof (shmalloc_info)); + + oldinfo = heap->heapinfo; + + newinfo[BLOCK (oldinfo)].busy.type = 0; + newinfo[BLOCK (oldinfo)].busy.info.size = BLOCKIFY (heap->heapsize * sizeof (shmalloc_info)); + + heap->heapinfo = newinfo; + + _fusion_shfree( heap, oldinfo ); + + heap->heapsize = newsize; + } + + heap->heaplimit = BLOCK ((char *) result + size); + + return result; +} + +/**********************************************************************************************************************/ + +/* Allocate memory from the heap. */ +void * +_fusion_shmalloc( shmalloc_heap *heap, size_t size ) +{ + void *result; + size_t block, blocks, lastblocks, start; + register size_t i; + struct list *next; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %zu )\n", __FUNCTION__, heap, size ); + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + /* Some programs will call shmalloc (0). We let them pass. */ + if (size == 0) + return NULL; + + if (size < sizeof (struct list)) + size = sizeof (struct list); + + /* Determine the allocation policy based on the request size. */ + if (size <= BLOCKSIZE / 2) { + /* Small allocation to receive a fragment of a block. + Determine the logarithm to base two of the fragment size. */ + register size_t log = 1; + --size; + while ((size /= 2) != 0) + ++log; + + /* Look in the fragment lists for a + free fragment of the desired size. */ + next = heap->fraghead[log].next; + if (next != NULL) { + /* There are free fragments of this size. + Pop a fragment out of the fragment list and return it. + Update the block's nfree and first counters. */ + result = (void *) next; + next->prev->next = next->next; + if (next->next != NULL) + next->next->prev = next->prev; + block = BLOCK (result); + if (--(heap->heapinfo[block].busy.info.frag.nfree) != 0) + heap->heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) next->next - (char *) NULL) + % BLOCKSIZE) >> log; + + /* Update the statistics. */ + heap->chunks_used++; + heap->bytes_used += 1 << log; + heap->chunks_free--; + heap->bytes_free -= 1 << log; + } + else { + /* No free fragments of the desired size, so get a new block + and break it into fragments, returning the first. */ + result = _fusion_shmalloc( heap, BLOCKSIZE ); + if (result == NULL) + return NULL; +#if 1 /* Adapted from Mike */ + heap->fragblocks[log]++; +#endif + + /* Link all fragments but the first into the free list. */ + for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) { + next = (struct list *) ((char *) result + (i << log)); + next->next = heap->fraghead[log].next; + next->prev = &heap->fraghead[log]; + next->prev->next = next; + if (next->next != NULL) + next->next->prev = next; + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK (result); + heap->heapinfo[block].busy.type = log; + heap->heapinfo[block].busy.info.frag.nfree = i - 1; + heap->heapinfo[block].busy.info.frag.first = i - 1; + + heap->chunks_free += (BLOCKSIZE >> log) - 1; + heap->bytes_free += BLOCKSIZE - (1 << log); + heap->bytes_used -= BLOCKSIZE - (1 << log); + } + } + else { + /* Large allocation to receive one or more blocks. + Search the free list in a circle starting at the last place visited. + If we loop completely around without finding a large enough + space we will have to get more memory from the system. */ + blocks = BLOCKIFY (size); + start = block = heap->heapindex; + while (heap->heapinfo[block].free.size < blocks) { + block = heap->heapinfo[block].free.next; + if (block == start) { + /* Need to get more from the system. Check to see if + the new core will be contiguous with the final free + block; if so we don't need to get as much. */ + block = heap->heapinfo[0].free.prev; + lastblocks = heap->heapinfo[block].free.size; + if (heap->heaplimit != 0 && block + lastblocks == heap->heaplimit && + __shmalloc_brk( heap, 0 ) == ADDRESS (block + lastblocks) && + (morecore( heap, (blocks - lastblocks) * BLOCKSIZE) ) != NULL) { +#if 1 /* Adapted from Mike */ + + /* Note that morecore() can change the location of + the final block if it moves the info table and the + old one gets coalesced into the final block. */ + block = heap->heapinfo[0].free.prev; + heap->heapinfo[block].free.size += blocks - lastblocks; +#else + heap->heapinfo[block].free.size = blocks; +#endif + heap->bytes_free += (blocks - lastblocks) * BLOCKSIZE; + continue; + } + result = morecore( heap, blocks * BLOCKSIZE ); + if (result == NULL) + return NULL; + block = BLOCK (result); + heap->heapinfo[block].busy.type = 0; + heap->heapinfo[block].busy.info.size = blocks; + heap->chunks_used++; + heap->bytes_used += blocks * BLOCKSIZE; + return result; + } + } + + /* At this point we have found a suitable free list entry. + Figure out how to remove what we need from the list. */ + result = ADDRESS (block); + if (heap->heapinfo[block].free.size > blocks) { + /* The block we found has a bit left over, + so relink the tail end back into the free list. */ + heap->heapinfo[block + blocks].free.size + = heap->heapinfo[block].free.size - blocks; + heap->heapinfo[block + blocks].free.next + = heap->heapinfo[block].free.next; + heap->heapinfo[block + blocks].free.prev + = heap->heapinfo[block].free.prev; + heap->heapinfo[heap->heapinfo[block].free.prev].free.next + = heap->heapinfo[heap->heapinfo[block].free.next].free.prev + = heap->heapindex = block + blocks; + } + else { + /* The block exactly matches our requirements, + so just remove it from the list. */ + heap->heapinfo[heap->heapinfo[block].free.next].free.prev + = heap->heapinfo[block].free.prev; + heap->heapinfo[heap->heapinfo[block].free.prev].free.next + = heap->heapindex = heap->heapinfo[block].free.next; + heap->chunks_free--; + } + + heap->heapinfo[block].busy.type = 0; + heap->heapinfo[block].busy.info.size = blocks; + heap->chunks_used++; + heap->bytes_used += blocks * BLOCKSIZE; + heap->bytes_free -= blocks * BLOCKSIZE; + } + + return result; +} + +/* Resize the given region to the new size, returning a pointer + to the (possibly moved) region. This is optimized for speed; + some benchmarks seem to indicate that greater compactness is + achieved by unconditionally allocating and copying to a + new region. This module has incestuous knowledge of the + internals of both free and shmalloc. */ +void * +_fusion_shrealloc( shmalloc_heap *heap, void *ptr, size_t size ) +{ + void *result; + int type; + size_t block, blocks, oldlimit; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %p, %zu )\n", __FUNCTION__, heap, ptr, size ); + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + if (ptr == NULL) + return _fusion_shmalloc( heap, size ); + else if (size == 0) { + _fusion_shfree( heap, ptr ); + return NULL; + } + + block = BLOCK (ptr); + + type = heap->heapinfo[block].busy.type; + switch (type) { + case 0: + /* Maybe reallocate a large block to a small fragment. */ + if (size <= BLOCKSIZE / 2) { + result = _fusion_shmalloc( heap, size ); + if (result != NULL) { + direct_memcpy (result, ptr, size); + _fusion_shfree( heap, ptr ); + return result; + } + } + + /* The new size is a large allocation as well; + see if we can hold it in place. */ + blocks = BLOCKIFY (size); + if (blocks < heap->heapinfo[block].busy.info.size) { + /* The new size is smaller; return + excess memory to the free list. */ + heap->heapinfo[block + blocks].busy.type = 0; + heap->heapinfo[block + blocks].busy.info.size + = heap->heapinfo[block].busy.info.size - blocks; + heap->heapinfo[block].busy.info.size = blocks; + _fusion_shfree( heap, ADDRESS (block + blocks) ); + result = ptr; + } + else if (blocks == heap->heapinfo[block].busy.info.size) + /* No size change necessary. */ + result = ptr; + else { + /* Won't fit, so allocate a new region that will. + Free the old region first in case there is sufficient + adjacent free space to grow without moving. */ + blocks = heap->heapinfo[block].busy.info.size; + /* Prevent free from actually returning memory to the system. */ + oldlimit = heap->heaplimit; + heap->heaplimit = 0; + _fusion_shfree( heap, ptr ); + heap->heaplimit = oldlimit; + result = _fusion_shmalloc( heap, size ); + if (result == NULL) { + /* Now we're really in trouble. We have to unfree + the thing we just freed. Unfortunately it might + have been coalesced with its neighbors. */ + if (heap->heapindex == block) + (void) _fusion_shmalloc( heap, blocks * BLOCKSIZE ); + else { + void *previous = _fusion_shmalloc( heap, (block - heap->heapindex) * BLOCKSIZE ); + (void) _fusion_shmalloc( heap, blocks * BLOCKSIZE ); + _fusion_shfree( heap, previous ); + } + return NULL; + } + if (ptr != result) + direct_memmove (result, ptr, blocks * BLOCKSIZE); + } + break; + + default: + /* Old size is a fragment; type is logarithm + to base two of the fragment size. */ + if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) + /* The new size is the same kind of fragment. */ + result = ptr; + else { + /* The new size is different; allocate a new space, + and copy the lesser of the new size and the old. */ + result = _fusion_shmalloc( heap, size ); + if (result == NULL) + return NULL; + direct_memcpy (result, ptr, MIN (size, (size_t) 1 << type)); + _fusion_shfree( heap, ptr ); + } + break; + } + + return result; +} + +/* Return memory to the heap. */ +void +_fusion_shfree( shmalloc_heap *heap, void *ptr ) +{ + int type; + size_t block, blocks; + register size_t i; + struct list *prev, *next; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %p )\n", __FUNCTION__, heap, ptr ); + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + if (ptr == NULL) + return; + + block = BLOCK (ptr); + + type = heap->heapinfo[block].busy.type; + switch (type) { + case 0: + /* Get as many statistics as early as we can. */ + heap->chunks_used--; + heap->bytes_used -= heap->heapinfo[block].busy.info.size * BLOCKSIZE; + heap->bytes_free += heap->heapinfo[block].busy.info.size * BLOCKSIZE; + + /* Find the free cluster previous to this one in the free list. + Start searching at the last block referenced; this may benefit + programs with locality of allocation. */ + i = heap->heapindex; + if (i > block) + while (i > block) + i = heap->heapinfo[i].free.prev; + else { + do + i = heap->heapinfo[i].free.next; + while (i > 0 && i < block); + i = heap->heapinfo[i].free.prev; + } + + /* Determine how to link this block into the free list. */ + if (block == i + heap->heapinfo[i].free.size) { + /* Coalesce this block with its predecessor. */ + heap->heapinfo[i].free.size += heap->heapinfo[block].busy.info.size; + block = i; + } + else { + /* Really link this block back into the free list. */ + heap->heapinfo[block].free.size = heap->heapinfo[block].busy.info.size; + heap->heapinfo[block].free.next = heap->heapinfo[i].free.next; + heap->heapinfo[block].free.prev = i; + heap->heapinfo[i].free.next = block; + heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block; + heap->chunks_free++; + } + + /* Now that the block is linked in, see if we can coalesce it + with its successor (by deleting its successor from the list + and adding in its size). */ + if (block + heap->heapinfo[block].free.size == heap->heapinfo[block].free.next) { + heap->heapinfo[block].free.size + += heap->heapinfo[heap->heapinfo[block].free.next].free.size; + heap->heapinfo[block].free.next + = heap->heapinfo[heap->heapinfo[block].free.next].free.next; + heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block; + heap->chunks_free--; + } + + blocks = heap->heapinfo[block].free.size; + +/* FIXME: as this is used when kernel is detected as >= 2.6.19.2 only, this fallback definition should be ok for now */ +#ifndef MADV_REMOVE +#define MADV_REMOVE 9 +#endif + /* Punch a hole into the tmpfs file to really free RAM. */ + if (fusion_config->madv_remove) + madvise( ADDRESS(block), blocks * BLOCKSIZE, MADV_REMOVE ); + + /* Now see if we can truncate the end. */ + if (blocks >= FINAL_FREE_BLOCKS && block + blocks == heap->heaplimit + && __shmalloc_brk( heap, 0 ) == ADDRESS (block + blocks)) + { + register size_t bytes = blocks * BLOCKSIZE; + heap->heaplimit -= blocks; + __shmalloc_brk( heap, -bytes ); + heap->heapinfo[heap->heapinfo[block].free.prev].free.next = heap->heapinfo[block].free.next; + heap->heapinfo[heap->heapinfo[block].free.next].free.prev = heap->heapinfo[block].free.prev; + block = heap->heapinfo[block].free.prev; + heap->chunks_free--; + heap->bytes_free -= bytes; + } + + /* Set the next search to begin at this block. */ + heap->heapindex = block; + break; + + default: + /* Do some of the statistics. */ + heap->chunks_used--; + heap->bytes_used -= 1 << type; + heap->chunks_free++; + heap->bytes_free += 1 << type; + + /* Get the address of the first free fragment in this block. */ + prev = (struct list *) ((char *) ADDRESS (block) + + (heap->heapinfo[block].busy.info.frag.first << type)); + +#if 1 /* Adapted from Mike */ + if ((int)heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1 + && heap->fragblocks[type] > 1) +#else + if ((int)heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) +#endif + { + /* If all fragments of this block are free, remove them + from the fragment list and free the whole block. */ +#if 1 /* Adapted from Mike */ + heap->fragblocks[type]--; +#endif + next = prev; + for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) + next = next->next; + prev->prev->next = next; + if (next != NULL) + next->prev = prev->prev; + heap->heapinfo[block].busy.type = 0; + heap->heapinfo[block].busy.info.size = 1; + + /* Keep the statistics accurate. */ + heap->chunks_used++; + heap->bytes_used += BLOCKSIZE; + heap->chunks_free -= BLOCKSIZE >> type; + heap->bytes_free -= BLOCKSIZE; + + _fusion_shfree( heap, ADDRESS (block) ); + } + else if (heap->heapinfo[block].busy.info.frag.nfree != 0) { + /* If some fragments of this block are free, link this + fragment into the fragment list after the first free + fragment of this block. */ + next = (struct list *) ptr; + next->next = prev->next; + next->prev = prev; + prev->next = next; + if (next->next != NULL) + next->next->prev = next; + heap->heapinfo[block].busy.info.frag.nfree++; + } + else { + /* No fragments of this block are free, so link this + fragment into the fragment list and announce that + it is the first free fragment of this block. */ + prev = (struct list *) ptr; + heap->heapinfo[block].busy.info.frag.nfree = 1; + heap->heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) ptr - (char *) NULL) + % BLOCKSIZE >> type); + prev->next = heap->fraghead[type].next; + prev->prev = &heap->fraghead[type]; + prev->prev->next = prev; + if (prev->next != NULL) + prev->next->prev = prev; + } + break; + } +} + +/**********************************************************************************************************************/ + +DirectResult +__shmalloc_init_heap( FusionSHM *shm, + const char *filename, + void *addr_base, + int space, + int *ret_fd, + int *ret_size ) +{ + DirectResult ret; + int size; + FusionSHMShared *shared; + int heapsize = (space + BLOCKSIZE-1) / BLOCKSIZE; + int fd = -1; + shmalloc_heap *heap = NULL; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %d, %p, %p )\n", + __FUNCTION__, shm, filename, addr_base, space, ret_fd, ret_size ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_ASSERT( filename != NULL ); + D_ASSERT( addr_base != NULL ); + D_ASSERT( ret_fd != NULL ); + D_ASSERT( ret_size != NULL ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + D_ASSERT( shared->tmpfs[0] != 0 ); + + size = BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( heapsize * sizeof(shmalloc_info) ); + + + D_DEBUG_AT( Fusion_SHMHeap, " -> opening shared memory file '%s'...\n", filename ); + + /* open the virtual file */ + fd = open( filename, O_RDWR | O_CREAT | O_TRUNC, 0660 ); + if (fd < 0) { + ret = errno2result(errno); + D_PERROR( "Fusion/SHM: Could not open shared memory file '%s'!\n", filename ); + goto error; + } + + if (fusion_config->shmfile_gid != (gid_t)-1) { + /* chgrp the SH_FILE dev entry */ + if (fchown( fd, -1, fusion_config->shmfile_gid ) != 0) + D_WARN( "Fusion/SHM: Changing owner on %s failed... continuing on.", filename ); + } + + fchmod( fd, 0660 ); + ftruncate( fd, size ); + + D_DEBUG_AT( Fusion_SHMHeap, " -> mmaping shared memory file... (%d bytes)\n", size ); + + /* map it shared */ + heap = mmap( addr_base, size + space, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 ); + if (heap == MAP_FAILED) { + ret = errno2result(errno); + D_PERROR( "Fusion/SHM: Could not mmap shared memory file '%s'!\n", filename ); + goto error; + } + + if (heap != addr_base) { + D_ERROR( "Fusion/SHM: mmap() returned address (%p) differs from requested (%p)\n", heap, addr_base ); + ret = DR_FUSION; + goto error; + } + + D_DEBUG_AT( Fusion_SHMHeap, " -> done.\n" ); + + heap->size = size; + heap->heapsize = heapsize; + heap->heapinfo = (void*) heap + BLOCKALIGN(sizeof(shmalloc_heap)); + heap->heapbase = (char*) heap->heapinfo; + + D_MAGIC_SET( heap, shmalloc_heap ); + + *ret_fd = fd; + *ret_size = size; + + return DR_OK; + + +error: + if (heap) + munmap( heap, size ); + + if (fd != -1) { + close( fd ); + unlink( filename ); + } + + return ret; +} + +DirectResult +__shmalloc_join_heap( FusionSHM *shm, + const char *filename, + void *addr_base, + int size, + int *ret_fd ) +{ + DirectResult ret; + FusionSHMShared *shared; + int fd = -1; + shmalloc_heap *heap = NULL; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %d, %p )\n", + __FUNCTION__, shm, filename, addr_base, size, ret_fd ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_ASSERT( filename != NULL ); + D_ASSERT( addr_base != NULL ); + D_ASSERT( size >= sizeof(shmalloc_heap) ); + D_ASSERT( ret_fd != NULL ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + D_ASSERT( shared->tmpfs[0] != 0 ); + + D_DEBUG_AT( Fusion_SHMHeap, " -> opening shared memory file '%s'...\n", filename ); + + /* open the virtual file */ + fd = open( filename, O_RDWR ); + if (fd < 0) { + ret = errno2result(errno); + D_PERROR( "Fusion/SHM: Could not open shared memory file '%s'!\n", filename ); + goto error; + } + + D_DEBUG_AT( Fusion_SHMHeap, " -> mmaping shared memory file... (%d bytes)\n", size ); + + /* map it shared */ + heap = mmap( addr_base, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 ); + if (heap == MAP_FAILED) { + ret = errno2result(errno); + D_PERROR( "Fusion/SHM: Could not mmap shared memory file '%s'!\n", filename ); + goto error; + } + + if (heap != addr_base) { + D_ERROR( "Fusion/SHM: mmap() returned address (%p) differs from requested (%p)\n", heap, addr_base ); + ret = DR_FUSION; + goto error; + } + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + D_DEBUG_AT( Fusion_SHMHeap, " -> done.\n" ); + + *ret_fd = fd; + + return DR_OK; + + +error: + if (heap) + munmap( heap, size ); + + if (fd != -1) + close( fd ); + + return ret; +} + +void * +__shmalloc_brk( shmalloc_heap *heap, int increment ) +{ + FusionSHMShared *shm; + FusionWorld *world; + FusionSHMPool *pool; + FusionSHMPoolShared *shared; + + D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %d )\n", __FUNCTION__, heap, increment ); + + D_MAGIC_ASSERT( heap, shmalloc_heap ); + + shared = heap->pool; + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + + shm = shared->shm; + D_MAGIC_ASSERT( shm, FusionSHMShared ); + + world = _fusion_world( shm->world ); + D_MAGIC_ASSERT( world, FusionWorld ); + + pool = &world->shm.pools[shared->index]; + D_MAGIC_ASSERT( pool, FusionSHMPool ); + + if (increment) { + int new_size = heap->size + increment; + + if (new_size > shared->max_size) { + D_WARN( "maximum shared memory size exceeded!" ); + fusion_dbg_print_memleaks( shared ); + return NULL; + } + + if (ftruncate( pool->fd, new_size ) < 0) { + D_PERROR( "Fusion/SHM: ftruncating shared memory file failed!\n" ); + return NULL; + } + + heap->size = new_size; + } + + return shared->addr_base + heap->size - increment; +} + diff --git a/Source/DirectFB/lib/fusion/shm/pool.c b/Source/DirectFB/lib/fusion/shm/pool.c new file mode 100755 index 0000000..030314f --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/pool.c @@ -0,0 +1,954 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <config.h> + +#include <unistd.h> +#include <sys/mman.h> + +#include <direct/debug.h> +#include <direct/list.h> +#include <direct/mem.h> +#include <direct/messages.h> + +#include <fusion/shmalloc.h> +#include <fusion/fusion_internal.h> + +#include <fusion/shm/pool.h> +#include <fusion/shm/shm_internal.h> + + +D_DEBUG_DOMAIN( Fusion_SHMPool, "Fusion/SHMPool", "Fusion Shared Memory Pool" ); + +/**********************************************************************************************************************/ + +static DirectResult init_pool ( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared, + const char *name, + unsigned int max_size, + bool debug ); + +static DirectResult join_pool ( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ); + +static void leave_pool ( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ); + +static void shutdown_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ); + +/**********************************************************************************************************************/ + +DirectResult +fusion_shm_pool_create( FusionWorld *world, + const char *name, + unsigned int max_size, + bool debug, + FusionSHMPoolShared **ret_pool ) +{ + int i; + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_MAGIC_ASSERT( world, FusionWorld ); + D_MAGIC_ASSERT( world->shared, FusionWorldShared ); + D_ASSERT( name != NULL ); + D_ASSERT( max_size > 0 ); + D_ASSERT( ret_pool != NULL ); + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p [%d], '%s', %d, %p, %sdebug )\n", __FUNCTION__, + world, world->shared->world_index, name, max_size, ret_pool, debug ? "" : "non-" ); + +#if !DIRECT_BUILD_DEBUGS + debug = false; +#endif + + shm = &world->shm; + + D_MAGIC_ASSERT( shm, FusionSHM ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + if (max_size < 8192) { + D_ERROR( "Fusion/SHMPool: Maximum size (%d) should be 8192 at least!\n", max_size ); + return DR_INVARG; + } + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + goto error; + + if (shared->num_pools == FUSION_SHM_MAX_POOLS) { + D_ERROR( "Fusion/SHMPool: Maximum number of pools (%d) already reached!\n", FUSION_SHM_MAX_POOLS ); + ret = DR_LIMITEXCEEDED; + goto error; + } + + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (!shared->pools[i].active) + break; + + D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); + D_MAGIC_ASSUME( &shm->pools[i], FusionSHMPool ); + } + + D_ASSERT( i < FUSION_SHM_MAX_POOLS ); + + D_DEBUG_AT( Fusion_SHMPool, " -> index %d\n", i ); + + memset( &shm->pools[i], 0, sizeof(FusionSHMPool) ); + memset( &shared->pools[i], 0, sizeof(FusionSHMPoolShared) ); + + shared->pools[i].index = i; + + ret = init_pool( shm, &shm->pools[i], &shared->pools[i], name, max_size, debug ); + if (ret) + goto error; + + shared->num_pools++; + + fusion_skirmish_dismiss( &shared->lock ); + + *ret_pool = &shared->pools[i]; + + D_DEBUG_AT( Fusion_SHMPool, " -> %p\n", *ret_pool ); + + return DR_OK; + + +error: + fusion_skirmish_dismiss( &shared->lock ); + + return ret; +} + +DirectResult +fusion_shm_pool_destroy( FusionWorld *world, + FusionSHMPoolShared *pool ) +{ + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, world, pool ); + + D_MAGIC_ASSERT( world, FusionWorld ); + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + shm = &world->shm; + + D_MAGIC_ASSERT( shm, FusionSHM ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + D_ASSERT( shared == pool->shm ); + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + return ret; + + ret = fusion_skirmish_prevail( &pool->lock ); + if (ret) { + fusion_skirmish_dismiss( &shared->lock ); + return ret; + } + + D_ASSERT( pool->active ); + D_ASSERT( pool->index >= 0 ); + D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS ); + D_ASSERT( pool->pool_id == shm->pools[pool->index].pool_id ); + D_ASSERT( pool == &shared->pools[pool->index] ); + + D_MAGIC_ASSERT( &shm->pools[pool->index], FusionSHMPool ); + + shutdown_pool( shm, &shm->pools[pool->index], pool ); + + shared->num_pools--; + + fusion_skirmish_dismiss( &shared->lock ); + + return DR_OK; +} + +DirectResult +fusion_shm_pool_attach( FusionSHM *shm, + FusionSHMPoolShared *pool ) +{ + DirectResult ret; + FusionSHMShared *shared; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, shm, pool ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + D_ASSERT( shared == pool->shm ); + + ret = fusion_skirmish_prevail( &pool->lock ); + if (ret) { + return ret; + } + + D_ASSERT( pool->active ); + D_ASSERT( pool->index >= 0 ); + D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS ); + D_ASSERT( pool == &shared->pools[pool->index] ); + D_ASSERT( !shm->pools[pool->index].attached ); + + ret = join_pool( shm, &shm->pools[pool->index], pool ); + + fusion_skirmish_dismiss( &pool->lock ); + + return ret; +} + +DirectResult +fusion_shm_pool_detach( FusionSHM *shm, + FusionSHMPoolShared *pool ) +{ + DirectResult ret; + FusionSHMShared *shared; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, shm, pool ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + D_ASSERT( shared == pool->shm ); + + ret = fusion_skirmish_prevail( &pool->lock ); + if (ret) { + fusion_skirmish_dismiss( &shared->lock ); + return ret; + } + + D_ASSERT( pool->active ); + D_ASSERT( pool->index >= 0 ); + D_ASSERT( pool->index < FUSION_SHM_MAX_POOLS ); + D_ASSERT( pool->pool_id == shm->pools[pool->index].pool_id ); + D_ASSERT( pool == &shared->pools[pool->index] ); + D_ASSERT( shm->pools[pool->index].attached ); + + D_MAGIC_ASSERT( &shm->pools[pool->index], FusionSHMPool ); + + leave_pool( shm, &shm->pools[pool->index], pool ); + + fusion_skirmish_dismiss( &pool->lock ); + + return DR_OK; +} + +DirectResult +fusion_shm_pool_allocate( FusionSHMPoolShared *pool, + int size, + bool clear, + bool lock, + void **ret_data ) +{ + DirectResult ret; + void *data; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %d, %sclear, %p )\n", __FUNCTION__, + pool, size, clear ? "" : "un", ret_data ); + + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + D_ASSERT( size > 0 ); + D_ASSERT( ret_data != NULL ); + + if (lock) { + ret = fusion_skirmish_prevail( &pool->lock ); + if (ret) + return ret; + } + + __shmalloc_brk( pool->heap, 0 ); + + data = _fusion_shmalloc( pool->heap, size ); + if (!data) { + if (lock) + fusion_skirmish_dismiss( &pool->lock ); + return DR_NOSHAREDMEMORY; + } + + if (clear) + memset( data, 0, size ); + + *ret_data = data; + + if (lock) + fusion_skirmish_dismiss( &pool->lock ); + + return DR_OK; +} + +DirectResult +fusion_shm_pool_reallocate( FusionSHMPoolShared *pool, + void *data, + int size, + bool lock, + void **ret_data ) +{ + DirectResult ret; + void *new_data; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %d, %p )\n", + __FUNCTION__, pool, data, size, ret_data ); + + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + D_ASSERT( data != NULL ); + D_ASSERT( data >= pool->addr_base ); + D_ASSERT( data < pool->addr_base + pool->max_size ); + D_ASSERT( size > 0 ); + D_ASSERT( ret_data != NULL ); + + if (lock) { + ret = fusion_skirmish_prevail( &pool->lock ); + if (ret) + return ret; + } + + __shmalloc_brk( pool->heap, 0 ); + + new_data = _fusion_shrealloc( pool->heap, data, size ); + if (!new_data) { + if (lock) + fusion_skirmish_dismiss( &pool->lock ); + return DR_NOSHAREDMEMORY; + } + + *ret_data = new_data; + + if (lock) + fusion_skirmish_dismiss( &pool->lock ); + + return DR_OK; +} + +DirectResult +fusion_shm_pool_deallocate( FusionSHMPoolShared *pool, + void *data, + bool lock ) +{ + DirectResult ret; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p )\n", __FUNCTION__, pool, data ); + + D_MAGIC_ASSERT( pool, FusionSHMPoolShared ); + + D_ASSERT( data != NULL ); + D_ASSERT( data >= pool->addr_base ); + D_ASSERT( data < pool->addr_base + pool->max_size ); + + if (lock) { + ret = fusion_skirmish_prevail( &pool->lock ); + if (ret) + return ret; + } + + __shmalloc_brk( pool->heap, 0 ); + + _fusion_shfree( pool->heap, data ); + + if (lock) + fusion_skirmish_dismiss( &pool->lock ); + + return DR_OK; +} + +/**********************************************************************************************************************/ + +#if FUSION_BUILD_KERNEL + +static DirectResult +init_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared, + const char *name, + unsigned int max_size, + bool debug ) +{ + DirectResult ret; + int fd; + int size; + FusionWorld *world; + FusionSHMPoolNew pool_new = { .pool_id = 0 }; + FusionSHMPoolAttach pool_attach = { .pool_id = 0 }; + FusionEntryInfo info; + char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n", + __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); + D_ASSERT( name != NULL ); + D_ASSERT( max_size > sizeof(shmalloc_heap) ); + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + D_ASSERT( pool != NULL ); + D_ASSERT( shared != NULL ); + + /* Fill out information for new pool. */ + pool_new.max_size = max_size; + + pool_new.max_size += BLOCKALIGN(sizeof(shmalloc_heap)) + + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); + + /* Create the new pool. */ + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_NEW, &pool_new )) { + if (errno == EINTR) + continue; + + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_NEW failed!\n" ); + return DR_FUSION; + } + + /* Set the pool info. */ + info.type = FT_SHMPOOL; + info.id = pool_new.pool_id; + + snprintf( info.name, sizeof(info.name), "%s", name ); + + ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info ); + + + /* Set pool to attach to. */ + pool_attach.pool_id = pool_new.pool_id; + + /* Attach to the pool. */ + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) { + if (errno == EINTR) + continue; + + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" ); + + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { + if (errno != EINTR) { + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); + break; + } + } + + return DR_FUSION; + } + + + /* Generate filename. */ + snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, + fusion_world_index( shm->world ), pool_new.pool_id ); + + /* Initialize the heap. */ + ret = __shmalloc_init_heap( shm, buf, pool_new.addr_base, max_size, &fd, &size ); + if (ret) { + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { + if (errno != EINTR) { + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); + break; + } + } + + return ret; + } + + + /* Initialize local data. */ + pool->attached = true; + pool->shm = shm; + pool->shared = shared; + pool->pool_id = pool_new.pool_id; + pool->fd = fd; + pool->filename = D_STRDUP( buf ); + + /* Initialize shared data. */ + shared->active = true; + shared->debug = debug; + shared->shm = shm->shared; + shared->max_size = pool_new.max_size; + shared->pool_id = pool_new.pool_id; + shared->addr_base = pool_new.addr_base; + shared->heap = pool_new.addr_base; + shared->heap->pool = shared; + + fusion_skirmish_init( &shared->lock, name, world ); + + + D_MAGIC_SET( pool, FusionSHMPool ); + D_MAGIC_SET( shared, FusionSHMPoolShared ); + + + shared->name = SHSTRDUP( shared, name ); + + return DR_OK; +} + +static DirectResult +join_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ) +{ + DirectResult ret; + int fd; + FusionWorld *world; + FusionSHMPoolAttach pool_attach = { .pool_id = 0 }; + char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + +#if !DIRECT_BUILD_DEBUGS + if (shared->debug) { + D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" ); + return DR_UNSUPPORTED; + } +#endif + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + + /* Set pool to attach to. */ + pool_attach.pool_id = shared->pool_id; + + /* Attach to the pool. */ + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_ATTACH, &pool_attach )) { + if (errno == EINTR) + continue; + + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_ATTACH failed!\n" ); + return DR_FUSION; + } + + + /* Generate filename. */ + snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, + fusion_world_index( shm->world ), shared->pool_id ); + + /* Join the heap. */ + ret = __shmalloc_join_heap( shm, buf, pool_attach.addr_base, shared->max_size, &fd ); + if (ret) { + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) { + if (errno != EINTR) { + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" ); + break; + } + } + + return ret; + } + + + /* Initialize local data. */ + pool->attached = true; + pool->shm = shm; + pool->shared = shared; + pool->pool_id = shared->pool_id; + pool->fd = fd; + pool->filename = D_STRDUP( buf ); + + + D_MAGIC_SET( pool, FusionSHMPool ); + + return DR_OK; +} + +static void +leave_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ) +{ + FusionWorld *world; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( pool, FusionSHMPool ); + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DETACH, &shared->pool_id )) { + if (errno != EINTR) { + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DETACH failed!\n" ); + break; + } + } + + if (munmap( shared->addr_base, shared->max_size )) + D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); + + if (pool->fd != -1 && close( pool->fd )) + D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename ); + + pool->attached = false; + + D_FREE( pool->filename ); + + D_MAGIC_CLEAR( pool ); +} + +static void +shutdown_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ) +{ + FusionWorld *world; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( pool, FusionSHMPool ); + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + SHFREE( shared, shared->name ); + + fusion_dbg_print_memleaks( shared ); + + while (ioctl( world->fusion_fd, FUSION_SHMPOOL_DESTROY, &shared->pool_id )) { + if (errno != EINTR) { + D_PERROR( "Fusion/SHM: FUSION_SHMPOOL_DESTROY failed!\n" ); + break; + } + } + + if (munmap( shared->addr_base, shared->max_size )) + D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); + + if (pool->fd != -1 && close( pool->fd )) + D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename ); + + if (unlink( pool->filename )) + D_PERROR( "Fusion/SHM: Could not unlink shared memory file '%s'!\n", pool->filename ); + + shared->active = false; + + pool->attached = false; + + D_FREE( pool->filename ); + + D_MAGIC_CLEAR( pool ); + + fusion_skirmish_destroy( &shared->lock ); + + D_MAGIC_CLEAR( shared ); +} + +#else /* FUSION_BUILD_KERNEL */ + +static DirectResult +init_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared, + const char *name, + unsigned int max_size, + bool debug ) +{ + DirectResult ret; + int fd; + int size; + long page_size; + int pool_id; + unsigned int pool_max_size; + void *pool_addr_base = NULL; + FusionWorld *world; + char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p, '%s', %d, %sdebug )\n", + __FUNCTION__, shm, pool, shared, name, max_size, debug ? "" : "non-" ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); + D_ASSERT( name != NULL ); + D_ASSERT( max_size > sizeof(shmalloc_heap) ); + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + D_ASSERT( pool != NULL ); + D_ASSERT( shared != NULL ); + + page_size = direct_pagesize(); + + pool_id = ++world->shared->pool_ids; + + pool_max_size = max_size + BLOCKALIGN(sizeof(shmalloc_heap)) + + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); + + pool_addr_base = world->shared->pool_base; + world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(page_size - 1)) + page_size; + /* Exceeded limit? */ + if (world->shared->pool_base > world->shared->pool_max) + return DR_NOSHAREDMEMORY; + + /* Generate filename. */ + snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, + fusion_world_index( world ), pool_id ); + + /* Initialize the heap. */ + ret = __shmalloc_init_heap( shm, buf, pool_addr_base, max_size, &fd, &size ); + if (ret) + return ret; + + /* Initialize local data. */ + pool->attached = true; + pool->shm = shm; + pool->shared = shared; + pool->pool_id = pool_id; + pool->fd = fd; + pool->filename = D_STRDUP( buf ); + + /* Initialize shared data. */ + shared->active = true; + shared->debug = debug; + shared->shm = shm->shared; + shared->max_size = pool_max_size; + shared->pool_id = pool_id; + shared->addr_base = pool_addr_base; + shared->heap = pool_addr_base; + shared->heap->pool = shared; + + fusion_skirmish_init( &shared->lock, name, world ); + + + D_MAGIC_SET( pool, FusionSHMPool ); + D_MAGIC_SET( shared, FusionSHMPoolShared ); + + + shared->name = SHSTRDUP( shared, name ); + + return DR_OK; +} + +static DirectResult +join_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ) +{ + DirectResult ret; + int fd; + FusionWorld *world; + char buf[FUSION_SHM_TMPFS_PATH_NAME_LEN + 32]; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( shm->shared, FusionSHMShared ); + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + +#if !DIRECT_BUILD_DEBUGS + if (shared->debug) { + D_ERROR( "Fusion/SHM: Can't join debug enabled pool with pure-release library!\n" ); + return DR_UNSUPPORTED; + } +#endif + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + /* Generate filename. */ + snprintf( buf, sizeof(buf), "%s/fusion.%d.%d", shm->shared->tmpfs, + fusion_world_index( shm->world ), shared->pool_id ); + + /* Join the heap. */ + ret = __shmalloc_join_heap( shm, buf, shared->addr_base, shared->max_size, &fd ); + if (ret) + return ret; + + /* Initialize local data. */ + pool->attached = true; + pool->shm = shm; + pool->shared = shared; + pool->pool_id = shared->pool_id; + pool->fd = fd; + pool->filename = D_STRDUP( buf ); + + + D_MAGIC_SET( pool, FusionSHMPool ); + + return DR_OK; +} + +static void +leave_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ) +{ + FusionWorld *world; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( pool, FusionSHMPool ); + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + if (munmap( shared->addr_base, shared->max_size )) + D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); + + if (pool->fd != -1 && close( pool->fd )) + D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename ); + + pool->attached = false; + + D_FREE( pool->filename ); + + D_MAGIC_CLEAR( pool ); +} + +static void +shutdown_pool( FusionSHM *shm, + FusionSHMPool *pool, + FusionSHMPoolShared *shared ) +{ + FusionWorld *world; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %p, %p )\n", __FUNCTION__, shm, pool, shared ); + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( pool, FusionSHMPool ); + D_MAGIC_ASSERT( shared, FusionSHMPoolShared ); + + world = shm->world; + + D_MAGIC_ASSERT( world, FusionWorld ); + + SHFREE( shared, shared->name ); + + fusion_dbg_print_memleaks( shared ); + + if (munmap( shared->addr_base, shared->max_size )) + D_PERROR( "Fusion/SHM: Could not munmap shared memory file '%s'!\n", pool->filename ); + + if (pool->fd != -1 && close( pool->fd )) + D_PERROR( "Fusion/SHM: Could not close shared memory file '%s'!\n", pool->filename ); + + if (unlink( pool->filename )) + D_PERROR( "Fusion/SHM: Could not unlink shared memory file '%s'!\n", pool->filename ); + + shared->active = false; + + pool->attached = false; + + D_FREE( pool->filename ); + + D_MAGIC_CLEAR( pool ); + + fusion_skirmish_destroy( &shared->lock ); + + D_MAGIC_CLEAR( shared ); +} + +#endif /* FUSION_BUILD_KERNEL */ + +/**********************************************************************************************************************/ + +#if FUSION_BUILD_KERNEL +void +_fusion_shmpool_process( FusionWorld *world, + int pool_id, + FusionSHMPoolMessage *msg ) +{ + int i; + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_DEBUG_AT( Fusion_SHMPool, "%s( %p, %d, %p )\n", __FUNCTION__, world, pool_id, msg ); + + D_MAGIC_ASSERT( world, FusionWorld ); + + shm = &world->shm; + + D_MAGIC_ASSERT( shm, FusionSHM ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + return; + + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (shm->pools[i].attached) { + D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); + + if (shm->pools[i].pool_id == pool_id) { + switch (msg->type) { + case FSMT_REMAP: + break; + + case FSMT_UNMAP: + D_UNIMPLEMENTED(); + break; + } + + break; + } + } + } + + fusion_skirmish_dismiss( &shared->lock ); +} +#endif /* FUSION_BUILD_KERNEL */ diff --git a/Source/DirectFB/lib/fusion/shm/pool.h b/Source/DirectFB/lib/fusion/shm/pool.h new file mode 100755 index 0000000..b809a5a --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/pool.h @@ -0,0 +1,69 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __FUSION__SHM__POOL_H__ +#define __FUSION__SHM__POOL_H__ + +#include <fusion/types.h> + + +DirectResult fusion_shm_pool_create ( FusionWorld *world, + const char *name, + unsigned int max_size, + bool debug, + FusionSHMPoolShared **ret_pool ); + +DirectResult fusion_shm_pool_destroy ( FusionWorld *world, + FusionSHMPoolShared *pool ); + + +DirectResult fusion_shm_pool_attach ( FusionSHM *shm, + FusionSHMPoolShared *pool ); + +DirectResult fusion_shm_pool_detach ( FusionSHM *shm, + FusionSHMPoolShared *pool ); + + +DirectResult fusion_shm_pool_allocate ( FusionSHMPoolShared *pool, + int size, + bool clear, + bool lock, + void **ret_data ); + +DirectResult fusion_shm_pool_reallocate( FusionSHMPoolShared *pool, + void *data, + int size, + bool lock, + void **ret_data ); + +DirectResult fusion_shm_pool_deallocate( FusionSHMPoolShared *pool, + void *data, + bool lock ); + +#endif + diff --git a/Source/DirectFB/lib/fusion/shm/shm.c b/Source/DirectFB/lib/fusion/shm/shm.c new file mode 100755 index 0000000..21c7f42 --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/shm.c @@ -0,0 +1,337 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <config.h> + +#include <string.h> +#include <unistd.h> + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/vfs.h> + +#include <direct/debug.h> +#include <direct/list.h> +#include <direct/signals.h> +#include <direct/messages.h> +#include <direct/util.h> + +#include <fusion/conf.h> +#include <fusion/fusion_internal.h> + +#include <fusion/shm/pool.h> +#include <fusion/shm/shm.h> +#include <fusion/shm/shm_internal.h> + + +/**********************************************************************************************************************/ + +static int +find_tmpfs( char *name, int len ) +{ + int largest = 0; + char buffer[1024]; + FILE *mounts_handle; + + mounts_handle = fopen( "/proc/mounts", "r" ); + if (!mounts_handle) + return 0; + + while (fgets( buffer, sizeof(buffer), mounts_handle )) { + char *mount_point; + char *mount_fs; + char *pointer = buffer; + + strsep( &pointer, " " ); + + mount_point = strsep( &pointer, " " ); + mount_fs = strsep( &pointer, " " ); + + if (mount_fs && mount_point && !access( mount_point, W_OK ) && + (!strcmp( mount_fs, "tmpfs" ) || !strcmp( mount_fs, "shmfs" ) || !strcmp( mount_fs, "ramfs" ))) + { + struct statfs stat; + int bytes; + + if (statfs( mount_point, &stat )) { + D_PERROR( "Fusion/SHM: statfs on '%s' failed!\n", mount_point ); + continue; + } + + bytes = stat.f_blocks * stat.f_bsize; + + if (bytes > largest || (bytes == largest && !strcmp(mount_point,"/dev/shm"))) { + largest = bytes; + + direct_snputs( name, mount_point, len ); + } + } + } + + fclose( mounts_handle ); + + return largest; +} + +/**********************************************************************************************************************/ + +DirectResult +fusion_shm_init( FusionWorld *world ) +{ + int i; + int num; + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_MAGIC_ASSERT( world, FusionWorld ); + D_MAGIC_ASSERT( world->shared, FusionWorldShared ); + + shm = &world->shm; + shared = &world->shared->shm; + + /* Initialize local data. */ + memset( shm, 0, sizeof(FusionSHM) ); + + shm->world = world; + shm->shared = shared; + + /* Initialize shared data. */ + if (fusion_master( world )) { + memset( shared, 0, sizeof(FusionSHMShared) ); + + if (fusion_config->tmpfs) { + snprintf( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, fusion_config->tmpfs ); + } + else if (!find_tmpfs( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN )) { + D_ERROR( "Fusion/SHM: Could not find tmpfs mount point, falling back to /dev/shm!\n" ); + snprintf( shared->tmpfs, FUSION_SHM_TMPFS_PATH_NAME_LEN, "/dev/shm" ); + } + + shared->world = world->shared; + + /* Initialize shared lock. */ + ret = fusion_skirmish_init( &shared->lock, "Fusion SHM", world ); + if (ret) { + D_DERROR( ret, "Fusion/SHM: Failed to create skirmish!\n" ); + return ret; + } + + /* Initialize static pool array. */ + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) + shared->pools[i].index = i; + + D_MAGIC_SET( shm, FusionSHM ); + D_MAGIC_SET( shared, FusionSHMShared ); + } + else { + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + return ret; + + D_MAGIC_SET( shm, FusionSHM ); + + for (i=0, num=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (shared->pools[i].active) { + D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); + + ret = fusion_shm_pool_attach( shm, &shared->pools[i] ); + if (ret) { + for (--i; i>=0; i--) { + if (shared->pools[i].active) + fusion_shm_pool_detach( shm, &shared->pools[i] ); + } + + fusion_skirmish_dismiss( &shared->lock ); + + D_MAGIC_CLEAR( shm ); + + return ret; + } + + num++; + } + } + + D_ASSERT( num == shared->num_pools ); + + fusion_skirmish_dismiss( &shared->lock ); + } + + return DR_OK; +} + +DirectResult +fusion_shm_deinit( FusionWorld *world ) +{ + int i; + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_MAGIC_ASSERT( world, FusionWorld ); + + shm = &world->shm; + + D_MAGIC_ASSERT( shm, FusionSHM ); + + shared = shm->shared; + + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + return ret; + + /* Deinitialize shared data. */ + if (fusion_master( world )) { + D_ASSUME( shared->num_pools == 0 ); + + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (shared->pools[i].active) { + D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); + D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); + + D_WARN( "destroying remaining '%s'", shared->pools[i].name ); + + fusion_shm_pool_destroy( world, &shared->pools[i] ); + } + } + + /* Destroy shared lock. */ + fusion_skirmish_destroy( &shared->lock ); + + D_MAGIC_CLEAR( shared ); + } + else { + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (shared->pools[i].active) { + D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); + D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); + + fusion_shm_pool_detach( shm, &shared->pools[i] ); + } + } + + fusion_skirmish_dismiss( &shared->lock ); + } + + D_MAGIC_CLEAR( shm ); + + return DR_OK; +} + +DirectResult +fusion_shm_attach_unattached( FusionWorld *world ) +{ + int i; + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_MAGIC_ASSERT( world, FusionWorld ); + D_MAGIC_ASSERT( world->shared, FusionWorldShared ); + + shm = &world->shm; + shared = &world->shared->shm; + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + return ret; + + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (!shared->pools[i].active) + continue; + + D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); + + if (!shm->pools[i].attached) { + ret = fusion_shm_pool_attach( shm, &shared->pools[i] ); + if (ret) + D_DERROR( ret, "fusion_shm_pool_attach( '%s' ) failed!\n", shared->pools[i].name ); + } + else + D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); + } + + fusion_skirmish_dismiss( &shared->lock ); + + return DR_OK; +} + +DirectResult +fusion_shm_enum_pools( FusionWorld *world, + FusionSHMPoolCallback callback, + void *ctx ) +{ + int i; + DirectResult ret; + FusionSHM *shm; + FusionSHMShared *shared; + + D_MAGIC_ASSERT( world, FusionWorld ); + D_MAGIC_ASSERT( world->shared, FusionWorldShared ); + D_ASSERT( callback != NULL ); + + shm = &world->shm; + shared = &world->shared->shm; + + D_MAGIC_ASSERT( shm, FusionSHM ); + D_MAGIC_ASSERT( shared, FusionSHMShared ); + + ret = fusion_skirmish_prevail( &shared->lock ); + if (ret) + return ret; + + for (i=0; i<FUSION_SHM_MAX_POOLS; i++) { + if (!shared->pools[i].active) + continue; + + if (!shm->pools[i].attached) { + D_BUG( "not attached to pool" ); + continue; + } + + D_MAGIC_ASSERT( &shm->pools[i], FusionSHMPool ); + D_MAGIC_ASSERT( &shared->pools[i], FusionSHMPoolShared ); + + if (callback( &shm->pools[i], ctx ) == DENUM_CANCEL) + break; + } + + fusion_skirmish_dismiss( &shared->lock ); + + return DR_OK; +} + diff --git a/Source/DirectFB/lib/fusion/shm/shm.h b/Source/DirectFB/lib/fusion/shm/shm.h new file mode 100755 index 0000000..6764d17 --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/shm.h @@ -0,0 +1,48 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __FUSION__SHM__SHM_H__ +#define __FUSION__SHM__SHM_H__ + +#include <fusion/types.h> + +typedef DirectEnumerationResult (*FusionSHMPoolCallback)( FusionSHMPool *pool, + void *ctx ); + +DirectResult fusion_shm_init ( FusionWorld *world ); + +DirectResult fusion_shm_deinit( FusionWorld *world ); + +DirectResult fusion_shm_attach_unattached( FusionWorld *world ); + +DirectResult fusion_shm_enum_pools( FusionWorld *world, + FusionSHMPoolCallback callback, + void *ctx ); + +#endif + diff --git a/Source/DirectFB/lib/fusion/shm/shm_internal.h b/Source/DirectFB/lib/fusion/shm/shm_internal.h new file mode 100755 index 0000000..3e282a5 --- /dev/null +++ b/Source/DirectFB/lib/fusion/shm/shm_internal.h @@ -0,0 +1,264 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>, + Andreas Hundt <andi@fischlustig.de>, + Sven Neumann <neo@directfb.org>, + Ville Syrjälä <syrjala@sci.fi> and + Claudio Ciccani <klan@users.sf.net>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __FUSION__SHM__SHM_INTERNAL_H__ +#define __FUSION__SHM__SHM_INTERNAL_H__ + +#include <limits.h> + +#include <direct/list.h> + +#include <fusion/build.h> +#include <fusion/lock.h> + + +#define FUSION_SHM_MAX_POOLS 24 +#define FUSION_SHM_TMPFS_PATH_NAME_LEN 64 + + +typedef struct __shmalloc_heap shmalloc_heap; + + +/* + * Local pool data. + */ +struct __Fusion_FusionSHMPool { + int magic; + + bool attached; /* Indicates usage of this entry in the static pool array. */ + + FusionSHM *shm; /* Back pointer to local SHM data. */ + + FusionSHMPoolShared *shared; /* Pointer to shared pool data. */ + + int pool_id; /* The pool's ID within the world. */ + + int fd; /* File descriptor of shared memory file. */ + char *filename; /* Name of the shared memory file. */ +}; + +/* + * Shared pool data. + */ +struct __Fusion_FusionSHMPoolShared { + int magic; + + bool debug; /* Debug allocations in this pool? */ + + int index; /* Index within the static pool array. */ + bool active; /* Indicates usage of this entry in the static pool array. */ + + FusionSHMShared *shm; /* Back pointer to shared SHM data. */ + + int max_size; /* Maximum possible size of the shared memory. */ + int pool_id; /* The pool's ID within the world. */ + void *addr_base; /* Virtual starting address of shared memory. */ + + FusionSkirmish lock; /* Lock for this pool. */ + + shmalloc_heap *heap; /* The actual heap information ported from libc5. */ + + char *name; /* Name of the pool (allocated in the pool). */ + + DirectLink *allocs; /* Used for debugging. */ +}; + + +/* + * Local SHM data. + */ +struct __Fusion_FusionSHM { + int magic; + + FusionWorld *world; /* Back pointer to local world data. */ + + FusionSHMShared *shared; /* Pointer to shared SHM data. */ + + FusionSHMPool pools[FUSION_SHM_MAX_POOLS]; /* Local data of all pools. */ + + DirectSignalHandler *signal_handler; +}; + +/* + * Shared SHM data. + */ +struct __Fusion_FusionSHMShared { + int magic; + + FusionWorldShared *world; /* Back pointer to shared world data. */ + + FusionSkirmish lock; /* Lock for list of pools. */ + + int num_pools; /* Number of active pools. */ + FusionSHMPoolShared pools[FUSION_SHM_MAX_POOLS]; /* Shared data of all pools. */ + + char tmpfs[FUSION_SHM_TMPFS_PATH_NAME_LEN]; +}; + + + +/* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ +#define INT_BIT (CHAR_BIT * sizeof(int)) +#define BLOCKLOG (INT_BIT > 16 ? 12 : 9) +#define BLOCKSIZE (1 << BLOCKLOG) +#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) +#define BLOCKALIGN(SIZE) (((SIZE) + BLOCKSIZE - 1) & ~(BLOCKSIZE - 1)) + +/* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ +#define FINAL_FREE_BLOCKS 8 + +/* Address to block number and vice versa. */ +#define BLOCK(A) (((char *) (A) - heap->heapbase) / BLOCKSIZE + 1) +#define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + heap->heapbase)) + + +/* Data structure giving per-block information. */ +typedef union { + + /* Heap information for a busy block. */ + struct { + + /* Zero for a large block, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + + union { + struct { + size_t nfree; /* Free fragments in a fragmented block. */ + size_t first; /* First free fragment of the block. */ + } frag; + + /* Size (in blocks) of a large cluster. */ + size_t size; + } info; + } busy; + + /* Heap information for a free block + (that may be the first of a free cluster). */ + struct { + size_t size; /* Size (in blocks) of a free cluster. */ + size_t next; /* Index of next free cluster. */ + size_t prev; /* Index of previous free cluster. */ + } free; +} shmalloc_info; + +/* Doubly linked lists of free fragments. */ +struct list { + struct list *next; + struct list *prev; +}; + + +#define SHMEMDESC_FUNC_NAME_LENGTH 48 +#define SHMEMDESC_FILE_NAME_LENGTH 24 + +/* Used for debugging. */ +typedef struct { + DirectLink link; + + const void *mem; + size_t bytes; + char func[SHMEMDESC_FUNC_NAME_LENGTH]; + char file[SHMEMDESC_FILE_NAME_LENGTH]; + unsigned int line; + + FusionID fid; +} SHMemDesc; + + +struct __shmalloc_heap { + int magic; + + /* Pointer to first block of the heap. */ + char *heapbase; + + /* Block information table indexed by block number giving per-block information. */ + shmalloc_info *heapinfo; + + /* Number of info entries. */ + size_t heapsize; + + /* Current search index for the heap table. */ + size_t heapindex; + + /* Limit of valid info table indices. */ + size_t heaplimit; + +#if 1 /* Adapted from Mike */ + /* Count of large blocks allocated for each fragment size. */ + int fragblocks[BLOCKLOG]; +#endif + + /* Free list headers for each fragment size. */ + struct list fraghead[BLOCKLOG]; + + /* Instrumentation. */ + size_t chunks_used; + size_t bytes_used; + size_t chunks_free; + size_t bytes_free; + + /* Total size of heap in bytes. */ + int size; + + /* Back pointer to shared memory pool. */ + FusionSHMPoolShared *pool; +}; + + +void *_fusion_shmalloc (shmalloc_heap *heap, size_t __size); + +void *_fusion_shrealloc (shmalloc_heap *heap, void *__ptr, size_t __size); + +void _fusion_shfree (shmalloc_heap *heap, void *__ptr); + + +DirectResult __shmalloc_init_heap( FusionSHM *shm, + const char *filename, + void *addr_base, + int space, + int *ret_fd, + int *ret_size ); + +DirectResult __shmalloc_join_heap( FusionSHM *shm, + const char *filename, + void *addr_base, + int size, + int *ret_fd ); + +void *__shmalloc_brk ( shmalloc_heap *heap, + int increment ); + + +#endif + |