[runtime] Remove checks for mono_use_imt because always true.
compile
mono.h
mono-*.tar.*
-mono.spec
-mono-core.spec
tmpinst-dir.stamp
msvc/scripts/inputs/
+++ /dev/null
-Miguel de Icaza (miguel@ximian.com)
-Paolo Molaro (lupus@ximian.com)
-Dietmar Maurer (dietmar@ximian.com)
README.md \
LICENSE \
autogen.sh \
- build-mingw32.sh \
mkinstalldirs \
mono-uninstalled.pc.in \
winconfig.h \
- mono-core.spec \
external
DISTCHECK_CONFIGURE_FLAGS = EXTERNAL_MCS=false EXTERNAL_RUNTIME=false
d=`cd $(distdir)/mcs && pwd`; cd $(mcs_topdir) && $(MAKE) distdir=$$d dist-recursive
rm -rf `find $(top_distdir)/external -path '*\.git'`
rm -f `find $(top_distdir)/external -path '*\.exe'`
- rm -f `find $(top_distdir)/external -path '*\.dll' -not -path '*/binary-reference-assemblies/v4\.0*'`
+ rm -f `find $(top_distdir)/external -path '*\.dll' -not -path '*/binary-reference-assemblies/*'`
cp mcs/class/lib/basic/System.Configuration.dll mcs/class/lib/monolite/
cp mcs/class/lib/basic/System.Security.dll mcs/class/lib/monolite/
# Disable this for now because it is very slow and causes wrench to timeout:
implementation of Microsoft's .NET Framework based on the ECMA
standards for C# and the Common Language Runtime.
+[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mono/mono?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
1. [Compilation and Installation](#compilation-and-installation)
2. [Using Mono](#using-mono)
3. [Directory Roadmap](#directory-roadmap)
Community supported architectures:
-| debian-ppc64el | centos-s390x |
-|-----------------------------|---------------------------|
-| [![debian-ppc64el][11]][12] | [![centos-s390x][13]][14] |
+| centos-s390x |
+|---------------------------|
+| [![centos-s390x][11]][12] |
[1]: http://jenkins.mono-project.com/job/test-mono-mainline/label=debian-amd64/badge/icon
[2]: http://jenkins.mono-project.com/job/test-mono-mainline/label=debian-amd64/
[8]: http://jenkins.mono-project.com/job/test-mono-mainline/label=debian-armhf/
[9]: https://ci.appveyor.com/api/projects/status/1e61ebdfpbiei58v/branch/master?svg=true
[10]: https://ci.appveyor.com/project/ajlennon/mono-817/branch/master
-[11]: http://jenkins.mono-project.com/job/test-mono-mainline-communityarchitectures/label=debian-ppc64el/badge/icon
-[12]: http://jenkins.mono-project.com/job/test-mono-mainline-communityarchitectures/label=debian-ppc64el/
-[13]: http://jenkins.mono-project.com/job/test-mono-mainline-communityarchitectures/label=centos-s390x/badge/icon
-[14]: http://jenkins.mono-project.com/job/test-mono-mainline-communityarchitectures/label=centos-s390x/
+[11]: http://jenkins.mono-project.com/job/test-mono-mainline-communityarchitectures/label=nealef-s390x-1/badge/icon
+[12]: http://jenkins.mono-project.com/job/test-mono-mainline-communityarchitectures/label=nealef-s390x-1/
Compilation and Installation
============================
* `scripts/` - Scripts used to invoke Mono and the corresponding program.
-* `../olive/` - Incubation code from [Olive](https://github.com/mono/olive).
-
- * If the directory ../olive is present (as an
-independent checkout) from the Mono module, that
-directory is automatically configured to share the
-same prefix than this module gets.
-
Contributing to Mono
====================
+++ /dev/null
-README.vsnet Last updated: 2006-02-01
-
-
-SVN includes a Visual Studio .NET 2005 solution, mono.sln, and some
-projects files to build most of the unmanaged parts in Mono.
-
-The "mono.sln" solution file contains the VC projects files for:
-
- * Embedded Samples
- * test-invoke.vcproj
- * test-metadata.vcproj
- * teste.vcproj
- * Libraries
- * libgc.vcproj
- * libmono.vcproj
- * Tools
- * genmdesc.vcproj
- * monoburg.vcproj
- * monodiet.vcproj
- * monodis.vcproj
- * monograph.vcproj
- * pedump.vcproj
- * mono.vcproj
-
-
-REQUIREMENTS
-
-* A working (i.e. where you could succesfully build mono) cygwin
-(http://www.cygwin.com/) setup! This is required to:
- * generate some files (via monoburg and genmdesc);
- * build the class libraries; and
- * test for regressions.
-
-* Visual Studio .NET 2005. Previous Visual Studio versions may work or
-requires, hopefully minimal, changes.
-
-* VSDependencies.zip must be decompressed under the /mono/ directory
-(otherwise you will need to edit all the projects files). This file can
-be downloaded from http://www.go-mono.com/archive/VSDependencies.zip
-
-
-LOCAL CHANGES
-
-Sadly solution/projects files aren't easy to move from computers to
-computers (well unless everyone follow the same naming convention) so
-you'll likely have to changes some options in order to compile the
-solution.
-
- * each executed assembly (i.e. the EXE) must be able to find a
- working mscorlib.dll (and all the other required assemblies).
- This can be done in different ways. My preference is to use the
- project "properties pages" in the "Configuration Properties
- \Debugging\Environment" options and set MONO_PATH to the class
- libraries directory build by cygwin (local) or on Linux
- (remote).
-
- e.g. MONO_PATH=z:\svn\mcs\class\lib\default\
- allows me to use the class libs build under Linux, while
- MONO_PATH=C:\cygwin\opt\mono\lib\mono\1.0
- use the one built from cygwin (after a make install)
-
-Some useful informations to adapt the solution/project files...
-
- * My cygwin root dir is: c:\cygwin\
- * My username is: poupou
- * My mono install prefix is: /opt/mono
-
-
-BUILDING
-
-Once everything is installed (and edited) you can right-click on the
-"mono" solution (in the "Solution Explorer"), select "Clean
-Solution" (for the first time) then "Build Solution".
-
-
-KNOWN ISSUES
-
-[1] Most, BUT NOT ALL, the regressions tests pass under this build. The
-failures seems limited to some mathematical differences and to code
-relying on the stack walking functions. The hacks to replace the GCC
-functions (__builtin_frame_address and __builtin_return_address) are
-incomplete;
-
-[2] The solution doesn't provide complete (i.e. from scratch) build. It
-requires a working cygwin environment to create some files (e.g. via
-genmdesc, monoburg). This isn't so bad as without cygwin you wouldn't be
-able to test Mono properly (see REQUIREMENTS);
-
-[3] Only the Debug target is configured properly (that would be easy to
-fix, but would require turning off some optimizations like omitting
-stack frames). Anyway there are other issues [1] to fix before switching
-to Release and IMHO the _biggest_ advantage to VS.NET is it's debugger/
-debugging tools;
-
-[4] The C compiler emits _lots_ of warning during compilation. Some
-warnings have been turned off for some projects (there was so much that
-it slowed down compilation). You can bring them back (or hide more of
-them) using the project "properties pages" windows, "Configuration
-Properties\C/C++\Advanced\Disable Specific Warnings";
-
-[5] Visual Studio 2005 should have all the latest header files required,
-but if not (or if you're using an older version of VS) then install MS
-Platform SDK (Windows Server 2003 is the latest) to ensure you have the
-latest Windows header files. You can download it from:
-http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm
-
-[6] Not everyone has VS.NET so it is possible you may have to add some
-(new) files to the build from time to time. See "more informations" for
-reporting those changes.
-
-[7] Probably a lot more I didn't discover... or has changed since.
-
-
-MORE INFORMATION
-
-Please email <mono-devel-list@lists.ximian.com> if you have any problem
-and/or if there's something wrong/missing in the instructions.
-
-An online version of this file is available at
-http://www.mono-project.com/Compiling_Mono_VSNET
+++ /dev/null
-#!/bin/bash -e
-CURDIR="`pwd`"
-MINGW=i386-mingw32msvc
-CROSS_DIR=/opt/cross/$MINGW
-EXTRA_CROSS_DIR=
-INSTALL_DESTDIR="$CURDIR/mono-win32"
-PROFILES="default net_2_0 net_3_5 net_4_0 net_4_5 moonlight"
-TEMPORARY_PKG_CONFIG_DIR=/tmp/$RANDOM-pkg-config-$RANDOM
-ORIGINAL_PATH="$PATH"
-
-export CPPFLAGS_FOR_EGLIB CFLAGS_FOR_EGLIB CPPFLAGS_FOR_LIBGC CFLAGS_FOR_LIBGC
-
-function cleanup ()
-{
- if [ -d "$TEMPORARY_PKG_CONFIG_DIR" ]; then
- rm -rf "$TEMPORARY_PKG_CONFIG_DIR"
- fi
-}
-
-function check_pkg_config_dir ()
-{
- local DIR="$1"
- local DIR_PREFIX="$2"
-
- if [ ! -d "$DIR" ]; then
- return
- fi
-
- install -d -m 755 "$TEMPORARY_PKG_CONFIG_DIR"
- for pc in "$DIR"/*.pc; do
- if [ -f $pc ]; then
- pcname="`basename $pc`"
- sed -e "s;^prefix=.*;prefix=$DIR_PREFIX;g" < $pc > "$TEMPORARY_PKG_CONFIG_DIR"/$pcname
- fi;
- done
-
- if [ -z "$CROSS_PKG_CONFIG_DIR" ]; then
- CROSS_PKG_CONFIG_DIR="$TEMPORARY_PKG_CONFIG_DIR"
- fi
-}
-
-function show_build_info ()
-{
- cat <<EOF
-Installation prefix: $MONO_PREFIX
- CPPFLAGS: ${CPPFLAGS:=not set}
- LDFLAGS: ${LDFLAGS:=not set}
- MONO_PATH: ${MONO_PATH:=not set}
-EOF
-}
-
-function setup ()
-{
- local pcname
-
- CROSS_BIN_DIR="$CROSS_DIR/bin"
- CROSS_DLL_DIR="$CROSS_DIR/bin"
- PATH=$CROSS_BIN_DIR:$PATH
-
- MONO_VERSION=`grep AC_INIT configure.ac | cut -d ',' -f 2|tr -d '\[ \]'`
-
- if [ -d ./.git ]; then
- MONO_GIT_COMMIT="`git log -1 --format=format:%t`"
- MONO_GIT_BRANCH="`git branch|grep '\*'|cut -d ' ' -f 2|tr -d '\)'|tr -d '\('`"
- MONO_RELEASE="$MONO_VERSION-$MONO_GIT_BRANCH-$MONO_GIT_COMMIT"
- else
- MONO_RELEASE="$MONO_VERSION"
- fi
-
- MONO_PREFIX="$MONO_PREFIX/mono-$MONO_RELEASE"
-
- NOCONFIGURE=yes
- export NOCONFIGURE
-
- check_pkg_config_dir "$CROSS_DIR/lib/pkgconfig" "$CROSS_DIR"
-
- if [ -n "$EXTRA_CROSS_DIR" -a -d "$EXTRA_CROSS_DIR" ]; then
- if [ -d "$EXTRA_CROSS_DIR/bin" ]; then
- PATH="$EXTRA_CROSS_DIR/bin":$PATH
- fi
-
- check_pkg_config_dir "$EXTRA_CROSS_DIR/lib/pkgconfig" "$EXTRA_CROSS_DIR"
-
- if [ -d "$EXTRA_CROSS_DIR/include" ]; then
- if [ -z "$CPPFLAGS" ]; then
- CPPFLAGS="-I \"$EXTRA_CROSS_DIR/include\""
- else
- CPPFLAGS="-I \"$EXTRA_CROSS_DIR/include\" $CFLAGS"
- fi
- fi
-
- if [ -d "$EXTRA_CROSS_DIR/lib" ]; then
- if [ -z "$LDFLAGS" ]; then
- LDFLAGS="-I \"$EXTRA_CROSS_DIR/lib\""
- else
- LDFLAGS="-I \"$EXTRA_CROSS_DIR/lib\" $LDFLAGS"
- fi
- fi
-
- if [ -d "$EXTRA_CROSS_DIR/share/aclocal" ]; then
- if [ -z "$MONO_PATH" ]; then
- MONO_PATH="\"$EXTRA_CROSS_DIR\""
- else
- MONO_PATH="\"$EXTRA_CROSS_DIR\":$MONO_PATH"
- fi
- fi
- fi
-
- export PATH MONO_PATH CPPFLAGS
- show_build_info
-}
-
-function build ()
-{
- if [ -f ./Makefile ]; then
- make distclean
- fi
-
- if [ -d ./autom4te.cache ]; then
- rm -rf ./autom4te.cache
- fi
-
- if [ -f ./config.status ]; then
- for f in `find -name config.status -type f`; do
- rm $f
- done
- fi
-
- ./autogen.sh
-
- BUILD="`./config.guess`"
-
- if [ ! -d "$CURDIR/build-cross-windows" ]; then
- mkdir "$CURDIR/build-cross-windows"
- fi
-
- cd "$CURDIR/build-cross-windows"
- rm -rf *
- ../configure --prefix=$MONO_PREFIX --with-crosspkgdir=$CROSS_PKG_CONFIG_DIR --build=$BUILD --target=$MINGW --host=$MINGW --enable-parallel-mark --program-transform-name="" --with-tls=none --disable-mcs-build --disable-embed-check --enable-win32-dllmain=yes --with-libgc-threads=win32 --with-profile4=yes
- make
- cd "$CURDIR"
-
- if [ ! -d "$CURDIR/build-cross-windows-mcs" ]; then
- mkdir "$CURDIR/build-cross-windows-mcs"
- fi
-
- rm -rf autom4te.cache
- unset PATH
- PATH="$ORIGINAL_PATH"
- export PATH
- cd "$CURDIR/build-cross-windows-mcs"
- rm -rf *
- ../configure --prefix=$MONO_PREFIX --enable-parallel-mark
- make
-}
-
-function doinstall ()
-{
- if [ -d "$INSTALL_DIR" ]; then
- rm -rf "$INSTALL_DIR"
- fi
- cd "$CURDIR/build-cross-windows"
- make DESTDIR="$INSTALL_DESTDIR" USE_BATCH_FILES=yes install
-
- if test -d $CURDIR/mcs; then
- mcsdir=$CURDIR/mcs
- else
- mcsdir=$CURDIR/../mcs
- fi
-
- cd "$mcsdir/mcs"
- for p in $PROFILES; do
- make DESTDIR="$INSTALL_DESTDIR" PROFILE=$p install || echo "mcs profile $p installation failed"
- done
-
- cd "$mcsdir/class"
- for p in $PROFILES; do
- make DESTDIR="$INSTALL_DESTDIR" PROFILE=$p install || echo "class library profile $p installation failed"
- done
-
- cd "$mcsdir/tools"
- for p in $PROFILES; do
- make DESTDIR="$INSTALL_DESTDIR" PROFILE=$p install || echo "tools profile $p installation failed"
- done
-
- cd "$CURDIR/mono-win32"
- rm -f "$CURDIR/mono-win32-$MONO_RELEASE".zip
- zip -9r "$CURDIR/mono-win32-$MONO_RELEASE".zip .
-
-}
-
-function usage ()
-{
- cat <<EOF
-Usage: build-mingw32.sh [OPTIONS]
-
-where OPTIONS are:
-
- -d DIR Sets the location of directory where MINGW is installed [$CROSS_DIR]
- -e DIR Sets the location of directory where additional cross develoment packages are installed [${EXTRA_CROSS_DIR:=none}]
- -m MINGW Sets the MINGW target name to be passed to configure [$MINGW]
- -p PREFIX Prefix at which Mono is to be installed. Build will append the 'mono-X.Y' string to that path
-EOF
-
- exit 1
-}
-
-trap cleanup 0
-
-pushd . > /dev/null
-
-while getopts "d:m:e:p:" opt; do
- case "$opt" in
- d) CROSS_DIR="$OPTARG" ;;
- m) MINGW="$OPTARG" ;;
- e) EXTRA_CROSS_DIR="$OPTARG" ;;
- p) MONO_PREFIX="$OPTARG" ;;
- *) usage ;;
- esac
-done
-
-setup
-build
-doinstall
-show_build_info
-
-popd > /dev/null
platform_darwin=no
case "$host" in
*-mingw*|*-*-cygwin*)
- AC_DEFINE(HOST_WIN32,1,[Host Platform is Win32])
AC_DEFINE(DISABLE_PORTABILITY,1,[Disable the io-portability layer])
AC_DEFINE(PLATFORM_NO_SYMLINKS,1,[This platform does not support symlinks])
host_win32=yes
mono_cv_clang=no
if test "x$cross_compiling" = "xno"; then
- target_win32=yes
if test "x$host" == "x$build" -a "x$host" == "x$target"; then
- AC_DEFINE(TARGET_WIN32,1,[Target OS is Win32])
+ target_win32=yes
fi
else
target_win32=yes
- AC_DEFINE(TARGET_WIN32,1,[Target OS is Win32/MinGW])
- AC_DEFINE(MINGW_CROSS_COMPILE,1,[Cross-compiling using MinGW])
fi
HOST_CC="gcc"
# Windows XP SP2 is required
AC_DEFINE(NEED_LINK_UNLINK, 1, [Define if Unix sockets cannot be created in an anonymous namespace])
fi
+if test x$host_win32 = xyes; then
+ AC_DEFINE(HOST_WIN32, 1, [Host Platform is Win32])
+fi
+
+if test x$target_win32 = xyes; then
+ AC_DEFINE(TARGET_WIN32, 1, [Target Platform is Win32])
+fi
+
AC_SUBST(extra_runtime_ldflags)
AM_CONDITIONAL(HOST_WIN32, test x$host_win32 = xyes)
AM_CONDITIONAL(TARGET_WIN32, test x$target_win32 = xyes)
AM_ICONV()
AC_CHECK_HEADERS(sys/filio.h sys/sockio.h netdb.h utime.h sys/utime.h semaphore.h sys/un.h linux/rtc.h sys/syscall.h sys/mkdev.h sys/uio.h sys/param.h sys/sysctl.h libproc.h)
-AC_CHECK_HEADERS(sys/param.h sys/socket.h sys/ipc.h sys/sem.h sys/utsname.h alloca.h ucontext.h pwd.h sys/select.h netinet/tcp.h netinet/in.h unistd.h sys/types.h link.h asm/sigcontext.h sys/inotify.h arpa/inet.h)
+AC_CHECK_HEADERS(sys/param.h sys/socket.h sys/ipc.h sys/sem.h sys/utsname.h alloca.h ucontext.h pwd.h sys/select.h netinet/tcp.h netinet/in.h unistd.h sys/types.h link.h asm/sigcontext.h sys/inotify.h arpa/inet.h complex.h)
AC_CHECK_HEADERS([linux/netlink.h linux/rtnetlink.h],
[], [], [#include <stddef.h>
#include <sys/socket.h>
AC_SUBST([mcs_topdir])
AC_SUBST([mcs_topdir_from_srcdir])
-# Where's the 'olive' source tree?
-if test -d $srcdir/olive; then
- olivedir=olive
-else
- olivedir=../olive
-fi
-
-if test -d $srcdir/$olivedir; then
-olive_topdir='$(top_srcdir)/'$olivedir
-fi
-
# gettext: prepare the translation directories.
# we do not configure the full gettext, as we consume it dynamically from C#
AM_PO_SUBDIRS
with_tls=pthread
target_mach=no
;;
+ x86_64-ps4-freebsd)
+ TARGET=AMD64;
+ arch_target=amd64;
+ AC_DEFINE(TARGET_AMD64, 1, [...])
+ AC_DEFINE(TARGET_PS4, 1, [...])
+ CPPFLAGS="$CPPFLAGS"
+ sgen_supported=true
+ # Can't use tls, since it depends on the runtime detection of tls offsets
+ # in mono-compiler.h
+ with_tls=pthread
+ target_mach=no
+ target_win32=no
+ ;;
aarch64*-linux-*)
TARGET=ARM64;
arch_target=arm64;
AC_OUTPUT([
Makefile
-mono-core.spec
mono-uninstalled.pc
scripts/mono-find-provides
scripts/mono-find-requires
fi
- # if we have an olive folder, override the default settings
- if test -d $olivedir; then
-
- if test x$cross_compiling = xno && test x$enable_olive_build != xno; then
-
- test -w $srcdir/$olivedir/build || chmod +w $srcdir/$olivedir/build
-
- echo "prefix=$prefix" > $srcdir/$olivedir/build/config.make
- echo "exec_prefix=$exec_prefix" >> $srcdir/$olivedir/build/config.make
- echo 'mono_libdir=${exec_prefix}/lib' >> $srcdir/$olivedir/build/config.make
- echo 'MCS_FLAGS = $(PLATFORM_DEBUG_FLAGS)' >> $srcdir/$olivedir/build/config.make
- echo "RUNTIME = $mono_build_root/runtime/mono-wrapper" >> $srcdir/$olivedir/build/config.make
- echo "MONO_VERSION = $myver" >> $srcdir/$olivedir/build/config.make
- fi
- fi
-
)
libgdiplus_msg=${libgdiplus_loc:-assumed to be installed}
EXTRA_DIST = \
abc-removal.txt \
api-style.css \
- assembly-bundle \
check-exports \
check-coverage \
convert.cs \
docs.make \
documented \
embedded-api \
- exceptions \
exdoc \
file-share-modes \
gc-issues \
jit-imt \
jit-thoughts \
jit-trampolines \
- local-regalloc.txt \
- magic.diff \
mini-doc.txt \
mono-api-metadata.html \
mono-file-formats.config\
mono-file-formats.source\
- mono_handle_d \
mono-tools.config \
mono-tools.source \
monoapi.source \
- new-regalloc \
object-layout \
- opcode-decomp.txt \
precise-gc \
produce-lists \
public \
public-api \
README \
- release-notes-1.0.html \
remoting \
ssapre.txt \
- stack-alignment \
stack-overflow.txt \
threading \
toc.xml \
TODO \
- tree-mover.txt \
unmanaged-calls
dist-hook:
+++ /dev/null
-
- HOWTO bundle assemblies inside the mono runtime.
- Paolo Molaro (lupus@ximian.com)
-
-* Intent
-
- Bundling assemblies inside the mono runtime may be useful for a number
- of reasons:
-
- * creating a standalone complete runtime that can be more easily
- distributed
-
- * having an application run against a known set of assemblies
- that has been tested
-
- Of course, there are drawbacks, too: if there has been fixes
- to the assemblies, replacing them means recompiling the
- runtime as well and if there are other mono apps, unless they
- use the same mono binary, there will be less opportunities for
- the operating system to optimize memory usage. So use this
- feature only when really needed.
-
-* Creating the Bundle
-
- To bundle a set of assemblies, you need to create a file that
- lists the assembly names and the relative files. Empty lines
- and lines starting with # are ignored:
-
- == cut cut ==
- # Sample bundle template
- mscorlib: /path/to/mscorlib/assembly.dll
- myapp: /path/to/myapp.exe
- == cut cut ==
-
- Next you need to build the mono runtime using a special configure option:
-
- ./configure --with-bundle=/path/to/bundle/template
-
- The path to the template should be an absolute path.
-
- The script metadata/make-bundle.pl will take the specifie
- assemblies and embed them inside the runtime where the loading
- routines can find them before searching for them on disk.
-
-* Open Issues
-
- There are still two issues to solve:
-
- * config files: sometimes they are needed but they are
- not yet bundled inside the library ()
-
- * building with the included libgc makes it not
- possible to build a mono binary statically linked to
- libmono: this needs to be fixed to make bundles
- really useful.
-
-
catch handler: catch hanlders are always called from the stack unwinding
code. The exception object is passed in a local variable (cfg->exvar).
-
-gcc support for Exceptions
-==========================
-
-gcc supports exceptions in files compiled with the -fexception option. gcc
-generates DWARF exceptions tables in that case, so it is possible to unwind the
-stack. The method to read those exception tables is contained in libgcc.a, and
-in newer versions of glibc (glibc 2.2.5 for example), and it is called
-__frame_state_for(). Another usable glibc function is backtrace_symbols() which
-returns the function name corresponding to a code address.
-
-We dynamically check if those features are available using g_module_symbol(),
-and we use them only when available. If not available we use the LMF as
-fallback.
-
-Using gcc exception information prevents us from saving the LMF at each native
-call, so this is a way to speed up native calls. This is especially valuable
-for internal calls, because we can make sure that all internal calls are
-compiled with -fexceptions (we compile the whole mono runtime with that
-option).
-
-All native function are able to call function without exception tables, and so
-we are unable to restore all caller saved registers if an exception is raised
-in such function. Well, its possible if the previous function already saves all
-registers. So we only omit the the LMF if a function has an exception table
-able to restore all caller saved registers.
-
-One problem is that gcc almost never saves all caller saved registers, because
-it is just unnecessary in normal situations. But there is a trick forcing gcc
-to save all register, we just need to call __builtin_unwind_init() at the
-beginning of a function. That way gcc generates code to save all caller saved
-register on the stack.
-
-
-
-
-
\ No newline at end of file
+++ /dev/null
-
-* Proposal for the local register allocator
-
- The local register allocator deals with allocating registers
- for temporaries inside a single basic block, while the global
- register allocator is concerned with method-wide allocation of
- variables.
- The global register allocator uses callee-saved register for it's
- purpouse so that there is no need to save and restore these registers
- at call sites.
-
- There are a number of issues the local allocator needs to deal with:
- *) some instructions expect operands in specific registers (for example
- the shl instruction on x86, or the call instruction with thiscall
- convention, or the equivalent call instructions on other architectures,
- such as the need to put output registers in %oX on sparc)
- *) some instructions deliver results only in specific registers (for example
- the div instruction on x86, or the call instructionson on almost all
- the architectures).
- *) it needs to know what registers may be clobbered by an instruction
- (such as in a method call)
- *) it should avoid excessive reloads or stores to improve performance
-
- While which specific instructions have limitations is architecture-dependent,
- the problem shold be solved in an arch-independent way to reduce code duplication.
- The register allocator will be 'driven' by the arch-dependent code, but it's
- implementation should be arch-independent.
-
- To improve the current local register allocator, we need to
- keep more state in it than the current setup that only keeps busy/free info.
-
- Possible state information is:
-
- free: the resgister is free to use and it doesn't contain useful info
- freeable: the register contains data loaded from a local (there is
- also info about _which_ local it contains) as a result from previous
- instructions (like, there was a store from the register to the local)
- moveable: it contains live data that is needed in a following instruction, but
- the contents may be moved to a different register
- busy: the register contains live data and it is placed there because
- the following instructions need it exactly in that register
- allocated: the register is used by the global allocator
-
- The local register allocator will have the following interfaces:
-
- int get_register ();
- Searches for a register in the free state. If it doesn't find it,
- searches for a freeable register. Sets the status to moveable.
- Looking for a 'free' register before a freeable one should allow for
- removing a few redundant loads (though I'm still unsure if such
- things should be delegated entirely to the peephole pass).
-
- int get_register_force (int reg);
- Returns 'reg' if it is free or freeable. If it is moveable, it moves it
- to another free or freeable register.
- Sets the status of 'reg' to busy.
-
- void set_register_freeable (int reg);
- Sets the status of 'reg' to freeable.
-
- void set_register_free (int reg);
- Sets the status of 'reg' to free.
-
- void will_clobber (int reg);
- Spills the register to the stack. Sets the status to freeable.
- After the clobbering has occurred, set the status to free.
-
- void register_unspill (int reg);
- Un-spills register reg and sets the status to moveable.
-
- FIXME: how is the 'local' information represented? Maybe a MonoInst* pointer.
-
- Note: the register allocator will insert instructions in the basic block
- during it's operation.
-
-* Examples
-
- Given the tree (on x86 the right argument to shl needs to be in ecx):
-
- store (local1, shl (local1, call (some_arg)))
-
- At the start of the basic block, the registers are set to the free state.
- The sequence of instructions may be:
- instruction register status -> [%eax %ecx %edx]
- start free free free
- eax = load local1 mov free free
- /* call clobbers eax, ecx, edx */
- spill eax free free free
- call mov free free
- /* now eax contains the right operand of the shl */
- mov %eax -> %ecx free busy free
- un-spill mov busy free
- shl %cl, %eax mov free free
-
- The resulting x86 code is:
- mov $fffc(%ebp), %eax
- mov %eax, $fff0(%ebp)
- push some_arg
- call func
- mov %eax, %ecx
- mov $fff0(%ebp), %eax
- shl %cl, %eax
-
- Note that since shl could operate directly on memory, we could have:
-
- push some_arg
- call func
- mov %eax, %ecx
- shl %cl, $fffc(%ebp)
-
- The above example with loading the operand in a register is just to complicate
- the example and show that the algorithm should be able to handle it.
-
- Let's take another example with the this-call call convention (the first argument
- is passed in %ecx).
- In this case, will_clobber() will be called only on %eax and %edx, while %ecx
- will be allocated with get_register_force ().
- Note: when a register is allocated with get_register_force(), it should be set
- to a different state as soon as possible.
-
- store (local1, shl (local1, this-call (local1)))
-
- instruction register status -> [%eax %ecx %edx]
- start free free free
- eax = load local1 mov free free
- /* force load in %ecx */
- ecx = load local1 mov busy free
- spill eax free busy free
- call mov free free
- /* now eax contains the right operand of the shl */
- mov %eax -> %ecx free busy free
- un-spill mov busy free
- shl %cl, %eax mov free free
-
- What happens when a register that we need to allocate with get_register_force ()
- contains an operand for the next instruction?
-
- instruction register status -> [%eax %ecx %edx]
- eax = load local0 mov free free
- ecx = load local1 mov mov free
- get_register_force (ecx) here.
- We have two options:
- mov %ecx, %edx
- or:
- spill %ecx
- The first option is way better (and allows the peephole pass to
- just load the value in %edx directly, instead of loading first to %ecx).
- This doesn't work, though, if the instruction clobbers the %edx register
- (like in a this-call). So, we first need to clobber the registers
- (so the state of %ecx changes to freebale and there is no issue
- with get_register_force ()).
- What if an instruction both clobbers a register and requires it as
- an operand? Lets' take the x86 idiv instruction as an example: it
- requires the dividend in edx:eax and returns the result in eax,
- with the modulus in edx.
-
- store (local1, div (local1, local2))
-
- instruction register status -> [%eax %ecx %edx]
- eax = load local0 mov free free
- will_clobber eax, edx free mov free
- force mov %ecx, %eax busy free free
- set %edx busy free busy
- idiv mov free free
-
- Note: edx is set to free after idiv, because the modulus is not needed
- (if it was a rem, eax would have been freed).
- If we load the divisor before will_clobber(), we'll have to spill
- eax and reload it later. If we load it just after the idiv, there is no issue.
- In any case, the algorithm should give the correct results and allow the operation.
-
- Working recursively on the isntructions there shouldn't be huge issues
- with this algorithm (though, of course, it's not optimal and it may
- introduce excessive spills or register moves). The advantage over the current
- local reg allocator is that:
- 1) the number of spills/moves would be smaller anyway
- 2) a separate peephole pass could be able to eliminate reg moves
- 3) we'll be able to remove the 'forced' spills we currently do with
- the return value of method calls
-
-* Issues
-
- How to best integrate such a reg allocator with the burg stuff.
-
- Think about a call os sparc with two arguments: they got into %o0 and %o1
- and each of them sets the register as busy. But what if the values to put there
- are themselves the result of a call? %o0 is no problem, but for all the
- next argument n the above algorithm would spill all the 0...n-1 registers...
-
-* Papers
-
- More complex solutions to the local register allocator problem:
- http://dimacs.rutgers.edu/TechnicalReports/abstracts/1997/97-33.html
-
- Combining register allocation and instruction scheduling:
- http://citeseer.nj.nec.com/motwani95combining.html
-
- More on LRA euristics:
- http://citeseer.nj.nec.com/liberatore97hardness.html
-
- Linear-time optimal code scheduling for delayedload architectures
- http://www.cs.wisc.edu/~fischer/cs701.f01/inst.sched.ps.gz
-
- Precise Register Allocation for Irregular Architectures
- http://citeseer.nj.nec.com/kong98precise.html
-
- Allocate registers first to subtrees that need more of them.
- http://www.upb.de/cs/ag-kastens/compii/folien/comment401-409.2.pdf
+++ /dev/null
-=pod
-
-=head1 Internal design document for the mono_handle_d
-
-This document is designed to hold the design of the mono_handle_d and
-not as an api reference.
-
-=head2 Primary goal and purpose
-
-The mono_handle_d is a process which takes care of the (de)allocation
-of scratch shared memory and handles (of files, threads, mutexes,
-sockets etc. see L<WapiHandleType>) and refcounts of the
-filehandles. It is designed to be run by a user and to be fast, thus
-minimal error checking on input is done and will most likely crash if
-given a faulty package. No effort has been, or should be, made to have
-the daemon talking to machine of different endianness/size of int.
-
-=head2 How to start the daemon
-
-To start the daemon you either run the mono_handle_d executable or try
-to attach to the shared memory segment via L<_wapi_shm_attach> which
-will start a daemon if one does not exist.
-
-=head1 Internal details
-
-The daemon works by opening a socket and listening to clients. These
-clients send packages over the socket complying to L<struct
-WapiHandleRequest>.
-
-=head2 Possible requests
-
-=over
-
-=item WapiHandleRequest_New
-
-Find a handle in the shared memory segment that is free and allocate
-it to the specified type. To destroy use
-L</WapiHandleRequest_Close>. A L<WapiHandleResponse> with
-.type=WapiHandleResponseType_New will be sent back with .u.new.handle
-set to the handle that was allocated. .u.new.type is the type that was
-requested.
-
-=item WapiHandleRequestType_Open
-
-Increase the ref count of an already created handle. A
-L<WapiHandleResponse> with .type=WapiHandleResponseType_Open will be sent
-back with .u.new.handle set to the handle, .u.new.type is set to the
-type of handle this is.
-
-=item WapiHandleRequestType_Close
-
-Decrease the ref count of an already created handle. A
-L<WapiHandleResponse> with .type=WapiHandleResponseType_Close will be
-sent back with .u.close.destroy set to TRUE if ref count for this
-client reached 0.
-
-=item WapiHandleRequestType_Scratch
-
-Allocate a shared memory area of size .u.scratch.length in bytes. A
-L<WapiHandleResponse> with .type=WapiHandleResponseType_Scratch will be
-sent back with .u.scratch.idx set to the index into the shared
-memory's scratch area where to memory begins. (works just like
-malloc(3))
-
-=item WapiHandleRequestType_Scratch
-
-Deallocate a shared memory area, this must have been allocated before
-deallocating. A L<WapiHandleResponse> with
-.type=WapiHandleResponseType_ScratchFree will be sent back (works just
-like free(3))
-
-=back
-
-=head1 Why a daemon
-
-From an email:
-
-Dennis: I just have one question about the daemon... Why does it
-exist? Isn't it better performancewise to just protect the shared area
-with a mutex when allocation a new handle/shared mem segment or
-changing refcnt? It will however be a less resilient to clients that
-crash (the deamon cleans up ref'd handles if socket closes)
-
-Dick: It's precisely because with a mutex the shared memory segment
-can be left in a locked state. Also, it's not so easy to clean up
-shared memory without it (you can't just mark it deleted when creating
-it, because you can't attach any more readers to the same segment
-after that). I did some minimal performance testing, and I don't
-think the daemon is particularly slow.
-
-
-=head1 Authors
-
-Documentaion: Dennis Haney
-
-Implementation: Dick Porter
-
-=cut
+++ /dev/null
-We need to switch to a new register allocator.
-The current one is split in a global and a local register allocator.
-The global one can assign only callee-saves registers and happens
-on the tree-based internal representation: it assigns local variables
-to hardware registers.
-The local one happens on the linear representation on a per basic
-block basis and assigns hard registers to virtual registers (which
-hold temporary values during expression executions) and it deals also
-with the platform-specific issues (fixed registers, call conventions).
-
-Moving to a different register will help solve some of the performance
-issues introduced by the above split, make the register more easily
-portable and solve some of the issues generated by dealing with trees.
-
-The general design ideas are below.
-
-The new allocator should have a global view of all the method, so it can be
-able to assign variables also to some of the volatile registers if possible,
-even across basic blocks (this would improve performance).
-
-The allocator would be driven by per-arch declarative data, so porting
-should be easier: an architecture needs to specify register classes,
-call convention and instructions requirements (similar to the gcc code).
-
-The allocator should operate on the linear representation, this way it's
-easier and faster to track usages more correctly. We need to assign virtual
-registers on a per-method basis instead of per basic block. We can assign
-virtual registers to variables, too. Note that since we fix the stack offset
-of local vars only after this step (which happens after the burg rules are run),
-some of the burg rules that try to optimize the code won't apply anymore:
-the peephole code may need to be enhanced to do the optimizations instead.
-
-We need to handle floating point registers in the global allocator, too.
-
-The new allocator also needs to keep track precisely of which registers
-contain references or managed pointers to allow us to move to a precise GC.
-
-It may be worth to use a single increasing set of integers for the virtual
-registers, with the class of the register stored separately (unless the
-current local allocator which keeps interger and fp registers separate).
-
-Since this is a large task, we need to do it in steps as much as possible.
-The first is to run the register allocator _after_ the burg rules: this
-requires a rewrite of the liveness code, too, to use linear indexes instead
-of basic-block/tree number combinations. This can be done by:
-*) allocating virtual regs to all the locals that can be register allocated
-*) running the burg rules (some may require adjustments): the local virtual
-registers are assigned starting from global-virt-regs+1, instead of the current
-hardware-regs+1, so we can tell apart global and local virt regs.
-*) running the liveness/whatever code is needed to allocate the global registers
-*) allocate the rest of the local variables to stack slots
-*) continue with the current local allocator
-
-This work could take 2-3 weeks.
-
-The next step is to define the kind of declarative data an architecture needs
-and assigning virtual regs to all the registers and making the allocator
-assign from the volatile registers, too.
-Note that some of the code that is currently emitted in the arch-specific
-code, will need to be emitted as instructions that the reg allocator
-can inspect: think of a method that returns the first argument which is
-received in a register: the current code copies it to either a local slot or
-to a global reg in the prolog an copies it back to the return register
-int he basic block, but since neither the regallocator nor the peephole code
-knows about the prolog code, the first store cannot be optimized away.
-The gcc code has some example of how to specify register classes in a
-declarative way.
-
+++ /dev/null
-
-* How to handle complex IL opcodes in an arch-independent way
-
- Many IL opcodes are very simple: add, ldind etc.
- Such opcodes can be implemented with a single cpu instruction
- in most architectures (on some, a group of IL instructions
- can be converted to a single cpu op).
- There are many IL opcodes, though, that are more complex, but
- can be expressed as a series of trees or a single tree of
- simple operations. Such simple operations are architecture-independent.
- It makes sense to decompose such complex IL instructions in their
- simpler equivalent so that we gain in several ways:
- *) porting effort is easier, because only the simple instructions
- need to be implemented in arch-specific code
- *) we could apply BURG rules to the trees and do pattern matching
- on them to optimize the expressions according to the host cpu
-
- The issue is: where do we do such conversion from coarse opcodes to
- simple expressions?
-
-* Doing the conversion in method_to_ir ()
-
- Some of these conversions can certainly be done in method_to_ir (),
- but it's not always easy to decide which are better done there and
- which in a different pass.
- For example, let's take ldlen: in the mono implementation, ldlen
- can be simply implemented with a load from a fixed position in the
- array object:
-
- len = [reg + maxlen_offset]
-
- However, ldlen carries also semantics information: the result is the
- length of the array, and since in the CLR arrays are of fixed size,
- this information can be useful to later do bounds check removal.
- If we convert this opcode in method_to_ir () we lost some useful
- information for further optimizations.
-
- In some other ways, decomposing an opcode in method_to_ir() may
- allow for better optimizations later on (need to come up with an
- example here ...).
-
-* Doing the conversion in inssel.brg
-
- Some conversion may be done inside the burg rules: this has the
- disadvantage that the instruction selector is not run again on
- the resulting expression tree and we could miss some optimization
- (this is what effectively happens with the coarse opcodes in the old
- jit). This may also interfere with an efficient local register allocator.
- It may be possible to add an extension in monoburg that allows a rule
- such as:
-
- recheck: LDLEN (reg) {
- create an expression tree representing LDLEN
- and return it
- }
-
- When the monoburg label process gets back a recheck, it will run
- the labeling again on the resulting expression tree.
- If this is possible at all (and in an efficient way) is a
- question for dietmar:-)
- It should be noted, though, that this may not always work, since
- some complex IL opcodes may require a series of expression trees
- and handling such cases in monoburg could become quite hairy.
- For example, think of opcode that need to do multiple actions on the
- same object: this basically means a DUP...
- On the other end, if a complex opcode needs a DUP, monoburg doesn't
- actually need to create trees if it emits the instructions in
- the correct sequence and maintains the right values in the registers
- (usually the values that need a DUP are not changed...). How
- this integrates with the current register allocator is not clear, since
- that assigns registers based on the rule, but the instructions emitted
- by the rules may be different (this already happens with the current JIT
- where a MULT is replaced with lea etc...).
-
-* Doing it in a separate pass.
-
- Doing the conversion in a separate pass over the instructions
- is another alternative. This can be done right after method_to_ir ()
- or after the SSA pass (since the IR after the SSA pass should look
- almost like the IR we get back from method_to_ir ()).
-
- This has the following advantages:
- *) monoburg will handle only the simple opcodes (makes porting easier)
- *) the instruction selection will be run on all the additional trees
- *) it's easier to support coarse opcodes that produce multiple expression
- trees (and apply the monoburg selector on all of them)
- *) the SSA optimizer will see the original opcodes and will be able to use
- the semantic info associated with them
-
- The disadvantage is that this is a separate pass on the code and
- it takes time (how much has not been measured yet, though).
-
- With this approach, we may also be able to have C implementations
- of some of the opcodes: this pass would insert a function call to
- the C implementation (for example in the cases when first porting
- to a new arch and implemenating some stuff may be too hard in asm).
-
-* Extended basic blocks
-
- IL code needs a lot of checks, bounds checks, overflow checks,
- type checks and so on. This potentially increases by a lot
- the number of basic blocks in a control flow graph. However,
- all such blocks end up with a throw opcode that gives control to the
- exception handling mechanism.
- After method_to_ir () a MonoBasicBlock can be considered a sort
- of extended basic block where the additional exits don't point
- to basic blocks in the same procedure (at least when the method
- doesn't have exception tables).
- We need to make sure the passes following method_to_ir () can cope
- with such kinds of extended basic blocks (especially the passes
- that we need to apply to all the methods: as a start, we could
- skip SSA optimizations for methods with exception clauses...)
-
+++ /dev/null
-With this change, we bundle Reactive Extensions from Microsoft.
-
-Steps to do:
-
-- Until we add submodule, check out Rx sources from http://rx.codeplex.com:
-
- $ cd external
- $ git clone git://github.com/atsushieno/rx.git
- $ cd rx
- $ git checkout rx-oss-v1.0
- $ cd ../..
-
- Note that the original repo at rx.codeplex.com will *fail* on Linux!
- codeplex.codeplex.com/workitem/26133
- Also note that rx.codeplex.com is huge and takes very long time to checkout.
-
-- expand rx-mono-changes-3.tar.bz2
-
- $ tar jxvf rx-mono-changes-3.tar.bz2
-
-- Apply changes to mcs/class/Makefile:
-
- $ cd mcs/class
- $ patch -i add-rx-libs.patch -p3
- $ cd ../..
-
-Then it should be done.
-
-Note that this does not include Mono.Reactive.Testing into the build yet -
-this library depends on nunit.framework.dll but it wouldn't be built before
-this assembly is built. This needs to be resolved.
-
-** Current Status
-
-- We don't have Microsoft.Reactive.Testing.dll. Instead, I created an
- alternative Mono.Reactive.Testing.dll which *mostly* uses MS sources for
- that assembly but uses NUnit.Framework instead.
-
- To make it happen, I added a small script that automatically replaces
- MSTest dependency parts with that for NUnit (replacer.sh under rx tree).
-
- (We'll also have to rename namespaces and have more source changes, but
- so far it is to get things runnable.)
-
-- To check the build sanity, I imported unit tests (as explained above)
- and it is supposed to run by "make run-test" in Mono.Reactive.Testing
- directory (the tests were all in one place in MS tests, so I made it
- in Mono.Reactive.Testing directory instead).
-
+++ /dev/null
-<h1>Mono 1.0 Release Notes</h1>
-
-<h2>What does Mono Include</h2>
-
-<h2>Missing functionality</h2>
-
- <p>COM support.
-
- <p>EnterpriseServices are non-existant.
-
- <p>Windows.Forms is only available as a preview, it is not
- completed nor stable.
-
-<h3>Assembly: System.Drawing</h3>
-
- <p>System.Drawing.Printing is not supported.
\ No newline at end of file
+++ /dev/null
-Size and alignment requirements of stack values
-===============================================
-
-P ... System.IntPtr
-I1 ... System.Int8
-I2 ... System.Int16
-I4 ... System.Int32
-I8 ... System.Int64
-F ... System.Single
-D ... System.Double
-LD ... native long double
-
------------------------------------------------------------
-ARCH | P | I1 | I2 | I4 | I8 | F | D | LD |
------------------------------------------------------------
-X86 | 4/4 | 4/4 | 4/4 | 4/4 | 8/4 | 4/4 | 8/4 |12/4 |
------------------------------------------------------------
-X86/W32 | 4/4 | 4/4 | 4/4 | 4/4 | 8/4 | 4/4 | 8/4 |12/4 |
------------------------------------------------------------
-ARM | 4/4 | 4/4 | 4/4 | 4/4 | 8/4 | 4/4 | 8/4 | 8/4 |
------------------------------------------------------------
-M68K | 4/4 | 4/4 | 4/4 | 4/4 | 8/4 | 4/4 | 8/4 |12/4 |
------------------------------------------------------------
-ALPHA | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 |
------------------------------------------------------------
-SPARC | 4/4 | 4/4 | 4/4 | 4/4 | 8/8 | 4/4 | 8/8 |16/8 |
------------------------------------------------------------
-SPARC64 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 |16/16|
------------------------------------------------------------
-MIPS | 4/4 | 4/4 | 4/4 | 4/4 | ?/? | 4/4 | 8/8 | 8/8 |
------------------------------------------------------------
- | | | | | | | | |
------------------------------------------------------------
+++ /dev/null
-
-Purpose
-
-Especially when inlining is active, it can happen that temporary
-variables add pressure to the register allocator, producing bad
-code.
-
-The idea is that some of these temporaries can be totally eliminated
-my moving the MonoInst tree that defines them directly to the use
-point in the code (so the name "tree mover").
-
-Please note that this is *not* an optimization: it is mostly a
-workaround to issues we have in the regalloc.
-Actually, with the new linear IR this will not be possible at all
-(there will be no more trees in the code!).
-Anyway, this workaround turns out to be useful in the current state
-of things...
-
------------------------------------------------------------------------
-
-Base logic
-
-If a local is defined by a value which is a proper expression (a tree
-of MonoInst, not just another local or a constant), and this definition
-is used only once, the tree can be moved directly to the use location,
-and the definition eliminated.
-Of course, none of the variables used in the tree must be defined in
-the code path between the definition and the use, and the tree must be
-free of side effects.
-We do not handle the cases when the tree is just a local or a constant
-because they are handled by copyprop and consprop, respectively.
-
-To make things simpler, we restrict the tree move to the case when:
-- the definition and the use are in the same BB, and
-- the use is followed by another definition in the same BB (it is not
- possible that the 1st value is used again), or alternatively there
- is no BB in the whole CFG that contains a use of this local before a
- definition (so, again, there is no code path that can lead to a
- subsequent use).
-
-To handle this, we maintain an ACT array (Available Copy Tree, similar
-to the ACP), where we store the "state" of every local.
-Ideally, every local can be in the following state:
-[E] Undefined (by a tree, it could be in the ACP but we don't care).
-[D] Defined (by a tree), and waiting for a use.
-[U] Used, with a tree definition available in the same BB, but still
- without a definition following the use (always in the same BB).
-Of course state [E] (empty) is the initial one.
-
-Besides, there are two sort of "meta states", or flags:
-[W] Still waiting for a use or definition in this BB (we have seen no
- occurrence of the local yet).
-[X] Used without being previously defined in the same BB (note that if
- there is a definition that precedes the use in the same BB, even if
- the definition is not a tree or is not available because of side
- effects or because the tree value has changed the local is not in
- state [X]).
-Also note that state [X] is a sort of "global" condition, which if set
-in one BB will stay valid for the whole CFG, even if the local will
-otherwise change state. The idea of flagging a local as [X] is that if
-there is a definition/use pair that reaches the end of a BB, it could
-be that there is a CFG path that then leads to the BB flagging it as
-[X] (which contains a use), so the tree cannot be moved.
-So state [X] will always be set, and never examined in all the state
-transitions we will describe.
-In practice, we use flag [W] to set state [X]: if, when traversing a
-BB, we find a use for a local in state [W], then that local is flagged
-[X].
-
-
-For each BB, we initialize all states to [E] and [W], and then we
-traverse the code one inst at a time, and update the variable states
-in the ACT in the following ways:
-
-[Definition]
- - Flag [W] is cleared.
- - All "affected trees" are killed (go from state [D] to [E]).
- The "affected trees" are the trees which contain (use) the defined
- local, and the rationale is that the tree value changed, so the
- tree is no longer available.
- - If the local was in state [U], *that* tree move is marked "safe"
- (because *this* definition makes us sure that the previous tree
- cannot be used again in any way).
- The idea is that "safe" moves can happen even if the local is
- flagged [X], because the second definition "covers" the use.
- The tree move is then saved in the "todo" list (and the affecting
- nodes are cleared).
- - If the local was defined by a tree, it goes to state [D], the tree
- is recorded, and all the locals used in it are marked as "affecting
- this tree" (of course these markers are lists, because each local
- could affect more than one tree).
-
-[IndirectDefinition]
- - All potentially affected trees (in state [D]) are killed.
-
-[Use]
- - If the local is still [W], it is flagged [X] (the [W] goes away).
- - If the local is in state [D], it goes to state [U].
- The tree move must not yet be recorded in the "todo" list, it still
- stays in the ACT slot belonging to this local.
- Anyway, the "affecting" nodes are updated, because now a definition
- of a local used in this tree will affect only "indirect" (or also
- "propagated") moves, but not *this* move (see below).
- - If the local is in state [U], then the tree cannot be moved (it is
- used two times): the move is canceled, and the state goes [E].
- - If the local is in state [E], the use is ignored.
-
-[IndirectUse]
- - All potentially affected trees (in state [D] or [U]) are killed.
-
-[SideEffect]
- - Tree is marked as "unmovable".
-
-Then, at the end of the BB, for each ACT slot:
- - If state is [U], the tree move is recorded in the "todo" list, but
- flagged "unsafe".
- - Anyway, state goes to [E], the [W] flag is set, and all "affecting"
- lists are cleared (we get ready to traverse the next BB).
-Finally, when all BBs has been scanned, we traverse the "todo" list,
-moving all "safe" entries, and moving "unsafe" ones only if their ACT
-slot is not flagged [X].
-
-So far, so good.
-But there are two issues that make things harder :-(
-
-The first is the concept of "indirect tree move".
-It can happen that a tree is scheduled for moving, and its destination
-is a use that is located in a second tree, which could also be moved.
-The main issue is that a definition of a variable of the 1st tree on
-the path between the definition and the use of the 2nd one must prevent
-the move.
-But which move? The 1st or the 2nd?
-Well, any of the two!
-The point is, the 2nd move must be prevented *only* if the 1st one
-happens: if it is aborted (for an [X] flag or any other reason), the
-2nd move is OK, and vice versa...
-We must handle this in the following way:
-- The ACT must still remember if a slot is scheduled for moving in
- this BB, and if it is, all the locals used in the tree.
- We say that the slot is in state [M].
- Note that [M] is (like [X] and [W]) a sort of "meta state": a local
- is flagged [M] when it goes to state [U], and the flag is cleared
- when the tree move is cancelled
-- A tree that uses a local whose slot is in state [M] is also using all
- the locals used by the tree in state [M], but the use is "indirect".
- These use nodes are also included in the "affecting" lists.
-- The definition of a variable used in an "indirect" way has the
- effect of "linking" the two involved tree moves, saying that only one
- of the two can happen in practice, but not both.
-- When the 2nd tree is scheduled for moving, the 1st one is *still* in
- state [M], because a third move could "carry it forward", and all the
- *three* moves should be mutually exclusive (to be safe!).
-
-The second tricky complication is the "tree forwarding" that can happen
-when copyprop is involved.
-It is conceptually similar to the "indirect tree move".
-Only, the 2nd tree is not really a tree, it is just the local defined
-in the 1st tree move.
-It can happen that copyprop will propagate the definition.
-We cannot make treeprop do the same job of copyprop, because copyprop
-has less constraints, and is therefore more powerful in its scope.
-The main issue is that treeprop cannot propagate a tree to *two* uses,
-while copyprop is perfectly capable of propagating one definition to
-two (or more) different places.
-So we must let copyprop do its job otherwise we'll miss optimizations,
-but we must also make it play safe with treeprop.
-Let's clarify with an example:
- a = v1 + v2; //a is defined by a tree, state [D], uses v2 and v2
- b = a; //a is used, state [U] with move scheduled, and
- //b is defined by a, ACP[b] is a, and b is in state [DC]
- c = b + v3; // b is used, goes to state [U]
-The real trouble is that copyprop happens *immediately*, while treeprop
-is deferred to the end of the CFG traversal.
-So, in the 3rd statement, the "b" is immediately turned into an "a" by
-copyprop, regardless of what treeprop will do.
-Anyway, if we are careful, this is not so bad.
-First of all, we must "accept" the fact that in the 3rd statement the
-"b" is in fact an "a", as treeprop must happen *after* copyprop.
-The real problem is that "a" is used twice: in the 2nd and 3rd lines.
-In our usual setup, the 2nd line would set it to [U], and the 3rd line
-would kill the move (and set "a" to [E]).
-I have tried to play tricks, and reason as of copyprop didn't happen,
-but everything becomes really messy.
-Instead, we should note that the 2nd line is very likely to be dead.
-At least in this BB, copyprop will turn all "b"s into "a"s as long as
-it can, and when it cannot, it will be because either "a" or "b" have
-been redefined, which would be after the tree move anyway.
-So, the reasoning gets different: let's pretend that "b" will be dead.
-This will make the "a" use in the 2nd statement useless, so there we
-can "reset" "a" to [D], but also take note that if "b" will end up
-not being dead, the tree move associated to this [D] must be aborted.
-We can detect this in the following way:
-- Either "b" is used before being defined in this BB, or
-- It will be flagged "unsafe".
-Both things are very easy to check.
-The only quirk is that the "affecting" lists must not be cleared when
-a slot goes to state [U], because a "propagation" could put it back
-to state [D] (where those lists are needed, because it can be killed
-by a definition to a used slot).
-
------------------------------------------------------------------------
-
-Implementation notes
-
-All the implementation runs inside the existing mono_local_cprop
-function, and a separate memory pool is used to hold the temporary
-data.
-
-A struct, MonoTreeMover, contains the pointers to the pool, the ACT,
-the list of scheduled moves and auxiliary things.
-This struct is allocated if the tree move pass is requested, and is
-then passed along to all the involved functions, which are therefore
-aware of the tree mover state.
-
-The ACT is an array of slots, obviously one per local.
-Each slot is of type MonoTreeMoverActSlot, and contains the used and
-affected locals, a pointer to the pending tree move and the "waiting"
-and "unsafe" flags.
-
-The "affecting" lists a built from "dependency nodes", of type
-MonoTreeMoverDependencyNode.
-Each of the nodes contains the used and affected local, and is in
-two lists: the locals used by a slot, and the locals affected by a
-slot (obviously a different one).
-So, each node means: "variable x is used in tree t, so a definition
-of x affects tree t".
-The "affecting" lists are doubly linked, to allow for O(1) deletion.
-The "used" lists are simply linked, but when they are mantained there
-is always a pointer to the last element to allow for O(1) list moving.
-When a used list is dismissed (which happens often, any time a node is
-killed), its nodes are unlinked from their respective affecting lists
-and are then put in a "free" list in the MonoTreeMover to be reused.
-
-Each tree move is represented by a struct (MonoTreeMoverTreeMove),
-which contains:
-- the definition and use points,
-- the "affected" moves (recall the concept of "indirect tree move"),
-- the "must be dead" slots (recall "tree forwarding"). and
-- a few utility flags.
-The tree moves stays in the relevant ACT slot until it is ready to be
-scheduled for moving, at which point it is put in a list in the
-MonoTreeMover.
-The tree moves structs are reused when they are killed, so there is
-also a "free" list for them in the MonoTreeMover.
-
-The tree mover code has been added to all the relevant functions that
-participate in consprop and copyprop, particularly:
-- mono_cprop_copy_values takes care of variable uses (transitions from
- states [D] to [U] and [U] to [E] because of killing),
-- mono_cprop_invalidate_values takes care of side effects (indirect
- accesses, calls...),
-- mono_local_cprop_bb sets up and cleans the traversals for each BB,
- and for each MonoInst it takes care of variable definitions.
-To each of them has been added a MonoTreeMover parameter, which is not
-NULL if the tree mover is running.
-After mono_local_cprop_bb has run for all BBs, the MonoTreeMover has
-the list of all the pending moves, which must be walked to actually
-perform the moves (when possible, because "unsafe" flags, "affected"
-moves and "must be dead" slots can still have their effects, which
-must be handled now because they are fully known only at the end of
-the CFG traversal).
-Subproject commit d589df6e8a206e28b84304a75917006a0e076c29
+Subproject commit 061a13cc772ef15f4d5528eb84fea4d51d4bda1d
-Subproject commit ada5da770505b718b60e4e40b837ffcbd758e17e
+Subproject commit 8f6de34a64fb52c25c07bacf0ac5ee824c5153ed
available on a typical dotnet framework installation, notice that this
does not include all of the Mono libraries, only the System.* ones. This
is a convenient shortcut for those porting code.
-.TP
-.I \-pkg:olive
-Use this to reference the "Olive" libraries (the 3.0 and 3.5 extended
-libraries).
-.TP
-.I \-pkg:silver
-References the assemblies for creating Moonlight/Silverlight
-applications.
-.TP
-.I \-pkg:silverdesktop
-Use this option to create Moonlight/Silverlight applications that
-target the desktop. This option allows developers to consume the
-Silverlight APIs with the full 2.0 profile API available to them,
-unlike
-.I smcs
-it gives full access to all the APIs that are part of Mono. The only
-downside is that applications created with silverdesktop will not run
-on the browser. Typically these applications will be launched
-with the
-.I mopen
-command line tool.
-.TP
-For more details see the PACKAGE section in this document
.ne
.RE
.TP
.TP
\fB(no-)lazy-sweep\fR
Enables or disables lazy sweep for the Mark&Sweep collector. If
-enabled, the sweep phase of the garbage collection is done piecemeal
-whenever the need arises, typically during nursery collections. Lazy
-sweeping is enabled by default.
+enabled, the sweeping of individual major heap blocks is done
+piecemeal whenever the need arises, typically during nursery
+collections. Lazy sweeping is enabled by default.
+.TP
+\fB(no-)concurrent-sweep\fR
+Enables or disables concurrent sweep for the Mark&Sweep collector. If
+enabled, the iteration of all major blocks to determine which ones can
+be freed and which ones have to be kept and swept, is done
+concurrently with the running program. Concurrent sweeping is enabled
+by default.
.TP
\fBstack-mark=\fImark-mode\fR
Specifies how application threads should be scanned. Options are
.Sp
The default is "win32".
.TP
+\fBMONO_THREAPOOL\fR
+This environment variable can be used to choose the implementation of
+the ThreadPool used at runtime. By default this uses the long term
+Mono threadpool implementation. But a new "microsoft" value switches
+the threadpool implementation to Microsoft's CoreCLR/ReferenceSource implementation.
+.TP
\fBMONO_TLS_SESSION_CACHE_TIMEOUT\fR
The time, in seconds, that the SSL/TLS session cache will keep it's entry to
avoid a new negotiation between the client and a server. Negotiation are very
xammac_SUBDIRS := build class
mobile_SUBDIRS := build class
mobile_static_SUBDIRS := build class
-net_4_0_SUBDIRS := build class
+binary_reference_assemblies_SUBDIRS := build class
net_4_5_SUBDIRS := build mcs class nunit24 ilasm tools tests errors docs
xbuild_12_SUBDIRS := build class tools/xbuild
xbuild_14_SUBDIRS := build class tools/xbuild
# fun specialty targets
-PROFILES = net_4_5 net_4_0 xbuild_12 xbuild_14
+PROFILES = net_4_5 binary_reference_assemblies xbuild_12 xbuild_14
.PHONY: all-profiles $(STD_TARGETS:=-profiles)
all-profiles $(STD_TARGETS:=-profiles): %-profiles: profiles-do--%
_boot_ = all clean install
$(_boot_:%=profile-do--xbuild_14--%): profile-do--xbuild_14--%: profile-do--net_4_5--%
$(_boot_:%=profile-do--xbuild_12--%): profile-do--xbuild_12--%: profile-do--net_4_5--%
-$(_boot_:%=profile-do--net_4_0--%): profile-do--net_4_0--%: profile-do--build--%
+$(_boot_:%=profile-do--binary_reference_assemblies--%): profile-do--binary_reference_assemblies--%: profile-do--build--%
$(_boot_:%=profile-do--net_4_5--%): profile-do--net_4_5--%: profile-do--build--%
$(_boot_:%=profile-do--monodroid--%): profile-do--monodroid--%: profile-do--build--%
$(_boot_:%=profile-do--monotouch--%): profile-do--monotouch--%: profile-do--build--%
PROFILES = \
basic \
build \
- net_4_0 \
+ binary_reference_assemblies \
net_4_5 \
xbuild_12 \
xbuild_14
--- /dev/null
+# -*- makefile -*-
+
+profile-check:
+ @:
+
+NO_BUILD = yes
+NO_TEST = yes
+++ /dev/null
-# -*- makefile -*-
-
-profile-check:
- @:
-
-FRAMEWORK_VERSION = 4.0
-XBUILD_VERSION = 4.0
-
-LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)
-
-NO_BUILD = yes
-NO_TEST = yes
mobile_static_SUBDIRS := $(mobile_static_dirs)
mobile_SUBDIRS := $(mobile_dynamic_dirs)
xammac_SUBDIRS := $(xammac_dirs)
-net_4_0_SUBDIRS := reference-assemblies
+binary_reference_assemblies_SUBDIRS := reference-assemblies
net_4_5_SUBDIRS := $(net_4_5_dirs) $(xbuild_4_0_dirs)
net_4_5_PARALLEL_SUBDIRS := $(net_4_5_parallel_dirs) aot-compiler
xbuild_12_SUBDIRS := $(xbuild_4_0_dirs)
throw new ArgumentOutOfRangeException ("inputCount", "< 0");
// ordered to avoid possible integer overflow
if (inputOffset > inputBuffer.Length - inputCount)
- throw new ArgumentException ("inputBuffer", Locale.GetText ("Overflow"));
+ throw new ArgumentException (Locale.GetText ("Overflow"), "inputBuffer");
}
public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
// ordered to avoid possible integer overflow
if (outputOffset > outputBuffer.Length - inputCount)
- throw new ArgumentException ("outputBuffer", Locale.GetText ("Overflow"));
+ throw new ArgumentException (Locale.GetText ("Overflow"), "outputBuffer");
return InternalTransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
}
EXTRA_DISTFILES =
-VALID_PROFILE := $(filter net_4_5 monotouch monodroid, $(PROFILE))
-ifndef VALID_PROFILE
-LIBRARY_NAME = dummy-SMDiagnostics.dll
-NO_INSTALL = yes
-NO_SIGN_ASSEMBLY = yes
-NO_TEST = yes
-endif
-
include ../../build/library.make
y.output
+/gen_OdbcConnection.cs
+/gen_OdbcParameter.cs
+/gen_OdbcParameterCollection.cs
+/gen_OleDbConnection.cs
+/gen_OleDbParameter.cs
+/gen_OleDbParameterCollection.cs
\ No newline at end of file
../../../external/referencesource/System.Data/System/Data/Common/MultipartIdentifier.cs
../../../external/referencesource/System.Data/System/Data/Common/NameValuePair.cs
../../../external/referencesource/System.Data/System/Data/Common/NameValuePermission.cs
-../../../external/referencesource/System.Data/System/Data/Common/NativeMethods.cs
../../../external/referencesource/System.Data/System/Data/Common/ObjectStorage.cs
../../../external/referencesource/System.Data/System/Data/Common/RowUpdatedEventArgs.cs
../../../external/referencesource/System.Data/System/Data/Common/RowUpdatingEventArgs.cs
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
-EXTRA_DISTFILES =
-
-VALID_PROFILE := $(filter net_4_5 monotouch monodroid xammac, $(PROFILE))
-ifndef VALID_PROFILE
-LIBRARY_NAME = dummy-System.ServiceModel.Internals.dll
-NO_INSTALL = yes
-NO_SIGN_ASSEMBLY = yes
-NO_TEST = yes
-endif
-
include ../../build/library.make
{
internal sealed class MonoSocketRuntimeWorkItem : IThreadPoolWorkItem
{
- Socket.SocketAsyncResult socket_async_result;
+ SocketAsyncResult socket_async_result;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern void ExecuteWorkItem();
// this version does not throw.
internal void InternalShutdown (SocketShutdown how)
{
- if (!connected || disposed)
+ if (!is_connected || is_disposed)
return;
int error;
- Shutdown_internal (socket, how, out error);
+ Shutdown_internal (safe_handle, how, out error);
}
internal IAsyncResult UnsafeBeginConnect (EndPoint remoteEP, AsyncCallback callback, object state)
internal void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue, bool silent)
{
- if (disposed && closed) {
+ if (is_disposed && is_closed) {
if (silent)
return;
throw new ObjectDisposedException (GetType ().ToString ());
int error;
- SetSocketOption_internal (socket, optionLevel, optionName, null,
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, null,
null, optionValue, out error);
if (!silent && error != 0)
{
}
- bool closii;
-
- /*protected override void Dispose (bool disposing)
- {
- lock (this) {
- if (!closii) {
-
- closii = true;
- int error = 0;
- Socket.Blocking_internal (handle, false, out error);
- //AbortRegisteredThreads ();
- Socket.Close_internal (handle, out error);
- //Console.Error.WriteLine ("Closed "+ handle);
- }
- }
- base.Dispose (disposing);
- }*/
-
protected override bool ReleaseHandle ()
{
int error = 0;
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Sridhar Kulkarni (sridharkulkarni@gmail.com)
// Brian Nickel (brian.nickel@gmail.com)
+// Ludovic Henry (ludovic@xamarin.com)
//
// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
// http://www.myelin.co.nz
{
public partial class Socket : IDisposable
{
- private bool islistening;
- private bool useoverlappedIO;
- private const int SOCKET_CLOSED = 10004;
+ const int SOCKET_CLOSED_CODE = 10004;
+ const string TIMEOUT_EXCEPTION_MSG = "A connection attempt failed because the connected party did not properly respond" +
+ "after a period of time, or established connection failed because connected host has failed to respond";
- private static readonly string timeout_exc_msg = "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond";
+ /*
+ * These two fields are looked up by name by the runtime, don't change
+ * their name without also updating the runtime code.
+ */
+ static int ipv4_supported = -1;
+ static int ipv6_supported = -1;
- static void AddSockets (List<Socket> sockets, IList list, string name)
+ /* true if we called Close_internal */
+ bool is_closed;
+
+ bool is_listening;
+ bool use_overlapped_io;
+
+ int linger_timeout;
+
+ /* the field "safe_handle" is looked up by name by the runtime */
+ SafeSocketHandle safe_handle;
+
+ AddressFamily address_family;
+ SocketType socket_type;
+ ProtocolType protocol_type;
+
+ /*
+ * This EndPoint is used when creating new endpoints. Because
+ * there are many types of EndPoints possible,
+ * seed_endpoint.Create(addr) is used for creating new ones.
+ * As such, this value is set on Bind, SentTo, ReceiveFrom,
+ * Connect, etc.
+ */
+ internal EndPoint seed_endpoint = null;
+
+ internal Queue<SocketAsyncWorker> readQ = new Queue<SocketAsyncWorker> (2);
+ internal Queue<SocketAsyncWorker> writeQ = new Queue<SocketAsyncWorker> (2);
+
+ internal bool is_blocking = true;
+ internal bool is_bound;
+
+ /* When true, the socket was connected at the time of the last IO operation */
+ internal bool is_connected;
+
+ internal bool is_disposed;
+ internal bool connect_in_progress;
+
+#region Constructors
+
+ static Socket ()
{
- if (list != null) {
- foreach (Socket sock in list) {
- if (sock == null) // MS throws a NullRef
- throw new ArgumentNullException ("name", "Contains a null element");
- sockets.Add (sock);
+ if (ipv4_supported == -1) {
+ try {
+ Socket tmp = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ tmp.Close();
+
+ ipv4_supported = 1;
+ } catch {
+ ipv4_supported = 0;
}
}
- sockets.Add (null);
+ if (ipv6_supported == -1) {
+ // We need to put a try/catch around ConfigurationManager methods as will always throw an exception
+ // when run in a mono embedded application. This occurs as embedded applications do not have a setup
+ // for application config. The exception is not thrown when called from a normal .NET application.
+ //
+ // We, then, need to guard calls to the ConfigurationManager. If the config is not found or throws an
+ // exception, will fall through to the existing Socket / API directly below in the code.
+ //
+ // Also note that catching ConfigurationErrorsException specifically would require library dependency
+ // System.Configuration, and wanted to avoid that.
+#if !NET_2_1
+#if CONFIGURATION_DEP
+ try {
+ SettingsSection config;
+ config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
+ if (config != null)
+ ipv6_supported = config.Ipv6.Enabled ? -1 : 0;
+ } catch {
+ ipv6_supported = -1;
+ }
+#else
+ try {
+ NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
+ if (config != null)
+ ipv6_supported = config.ipv6Enabled ? -1 : 0;
+ } catch {
+ ipv6_supported = -1;
+ }
+#endif
+#endif
+ if (ipv6_supported != 0) {
+ try {
+ Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ tmp.Close();
+
+ ipv6_supported = 1;
+ } catch {
+ ipv6_supported = 0;
+ }
+ }
+ }
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void Select_internal (ref Socket [] sockets,
- int microSeconds,
- out int error);
- public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
- {
- var list = new List<Socket> ();
- AddSockets (list, checkRead, "checkRead");
- AddSockets (list, checkWrite, "checkWrite");
- AddSockets (list, checkError, "checkError");
- if (list.Count == 3) {
- throw new ArgumentNullException ("checkRead, checkWrite, checkError",
- "All the lists are null or empty.");
+ [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
+ public Socket (SocketType socketType, ProtocolType protocolType)
+ : this (AddressFamily.InterNetwork, socketType, protocolType)
+ {
+ }
+
+ public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
+ {
+#if NET_2_1 && !MOBILE
+ switch (addressFamily) {
+ case AddressFamily.InterNetwork: // ok
+ case AddressFamily.InterNetworkV6: // ok
+ case AddressFamily.Unknown: // SocketException will be thrown later (with right error #)
+ break;
+ // case AddressFamily.Unspecified:
+ default:
+ throw new ArgumentException ("addressFamily");
+ }
+
+ switch (socketType) {
+ case SocketType.Stream: // ok
+ case SocketType.Unknown: // SocketException will be thrown later (with right error #)
+ break;
+ default:
+ throw new ArgumentException ("socketType");
+ }
+
+ switch (protocolType) {
+ case ProtocolType.Tcp: // ok
+ case ProtocolType.Unspecified: // ok
+ case ProtocolType.Unknown: // SocketException will be thrown later (with right error #)
+ break;
+ default:
+ throw new ArgumentException ("protocolType");
}
-
+#endif
+ this.address_family = addressFamily;
+ this.socket_type = socketType;
+ this.protocol_type = protocolType;
+
int error;
- /*
- * The 'sockets' array contains: READ socket 0-n, null,
- * WRITE socket 0-n, null,
- * ERROR socket 0-n, null
- */
- Socket [] sockets = list.ToArray ();
- Select_internal (ref sockets, microSeconds, out error);
+ var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
+
+ this.safe_handle = new SafeSocketHandle (handle, true);
if (error != 0)
throw new SocketException (error);
- if (sockets == null) {
- if (checkRead != null)
- checkRead.Clear ();
- if (checkWrite != null)
- checkWrite.Clear ();
- if (checkError != null)
- checkError.Clear ();
- return;
- }
+#if !NET_2_1 || MOBILE
+ SocketDefaults ();
+#endif
+ }
- int mode = 0;
- int count = sockets.Length;
- IList currentList = checkRead;
- int currentIdx = 0;
- for (int i = 0; i < count; i++) {
- Socket sock = sockets [i];
- if (sock == null) { // separator
- if (currentList != null) {
- // Remove non-signaled sockets after the current one
- int to_remove = currentList.Count - currentIdx;
- for (int k = 0; k < to_remove; k++)
- currentList.RemoveAt (currentIdx);
- }
- currentList = (mode == 0) ? checkWrite : checkError;
- currentIdx = 0;
- mode++;
- continue;
- }
+#if !MOBILE
+ public Socket (SocketInformation socketInformation)
+ {
+ this.is_listening = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
+ this.is_connected = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
+ this.is_blocking = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
+ this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
- if (mode == 1 && currentList == checkWrite && !sock.connected) {
- if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
- sock.connected = true;
- }
+ var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
- // Remove non-signaled sockets before the current one
- //int max = currentList.Count;
- while (((Socket) currentList [currentIdx]) != sock) {
- currentList.RemoveAt (currentIdx);
- }
- currentIdx++;
- }
+ this.address_family = (AddressFamily) (int) result [0];
+ this.socket_type = (SocketType) (int) result [1];
+ this.protocol_type = (ProtocolType) (int) result [2];
+ this.is_bound = (ProtocolType) (int) result [3] != 0;
+ this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
+
+ SocketDefaults ();
}
+#endif
- // private constructor used by Accept, which already
- // has a socket handle to use
- internal Socket(AddressFamily family, SocketType type,
- ProtocolType proto, SafeSocketHandle sock)
+ /* private constructor used by Accept, which already has a socket handle to use */
+ internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
{
- address_family=family;
- socket_type=type;
- protocol_type=proto;
+ this.address_family = family;
+ this.socket_type = type;
+ this.protocol_type = proto;
- socket=sock;
- connected=true;
+ this.safe_handle = safe_handle;
+ this.is_connected = true;
+ }
+
+ ~Socket ()
+ {
+ Dispose (false);
}
- private void SocketDefaults ()
+ void SocketDefaults ()
{
try {
- if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
- address_family == AddressFamily.InterNetworkV6 */) {
- /* This is the default, but it
- * probably has nasty side
- * effects on Linux, as the
- * socket option is kludged by
- * turning on or off PMTU
- * discovery...
- */
+ /* Need to test IPv6 further */
+ if (address_family == AddressFamily.InterNetwork
+ // || address_family == AddressFamily.InterNetworkV6
+ ) {
+ /* This is the default, but it probably has nasty side
+ * effects on Linux, as the socket option is kludged by
+ * turning on or off PMTU discovery... */
this.DontFragment = false;
}
- //
- // Microsoft sets these to 8192, but we are going to keep them
- // both to the OS defaults as these have a big performance impact.
- // on WebClient performance.
- //
- //this.ReceiveBufferSize = 8192;
- //this.SendBufferSize = 8192;
+ /* Microsoft sets these to 8192, but we are going to keep them
+ * both to the OS defaults as these have a big performance impact.
+ * on WebClient performance. */
+ // this.ReceiveBufferSize = 8192;
+ // this.SendBufferSize = 8192;
} catch (SocketException) {
}
}
-#if !MOBILE
- public Socket (SocketInformation socketInformation)
- {
- var options = socketInformation.Options;
- islistening = (options & SocketInformationOptions.Listening) != 0;
- connected = (options & SocketInformationOptions.Connected) != 0;
- blocking = (options & SocketInformationOptions.NonBlocking) == 0;
- useoverlappedIO = (options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
+ /* Creates a new system socket, returning the handle */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern IntPtr Socket_internal (AddressFamily family, SocketType type, ProtocolType proto, out int error);
- var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
-
- address_family = (AddressFamily) (int) result [0];
- socket_type = (SocketType) (int) result [1];
- protocol_type = (ProtocolType) (int) result [2];
- isbound = (ProtocolType) (int) result [3] != 0;
- socket = new SafeSocketHandle ((IntPtr) (long) result [4], true);
- SocketDefaults ();
+#endregion
+
+#region Properties
+
+ public static bool SupportsIPv4 {
+ get { return ipv4_supported == 1; }
+ }
+
+ [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
+ public static bool SupportsIPv6 {
+ get { return ipv6_supported == 1; }
+ }
+
+#if NET_2_1
+ public static bool OSSupportsIPv4 {
+ get { return ipv4_supported == 1; }
}
#endif
-
- // Returns the amount of data waiting to be read on socket
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static int Available_internal(IntPtr socket, out int error);
- private static int Available_internal (SafeSocketHandle safeHandle, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- return Available_internal (safeHandle.DangerousGetHandle (), out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
+#if NET_2_1
+ public static bool OSSupportsIPv6 {
+ get { return ipv6_supported == 1; }
+ }
+#else
+ public static bool OSSupportsIPv6 {
+ get {
+ NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
+
+ foreach (NetworkInterface adapter in nics) {
+ if (adapter.Supports (NetworkInterfaceComponent.IPv6))
+ return true;
+ }
+
+ return false;
}
}
+#endif
public int Available {
get {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
int ret, error;
-
- ret = Available_internal(socket, out error);
+ ret = Available_internal (safe_handle, out error);
if (error != 0)
throw new SocketException (error);
- return(ret);
+ return ret;
+ }
+ }
+
+ static int Available_internal (SafeSocketHandle safeHandle, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ return Available_internal (safeHandle.DangerousGetHandle (), out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
}
}
+ /* Returns the amount of data waiting to be read on socket */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static int Available_internal (IntPtr socket, out int error);
public bool DontFragment {
get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
-
- bool dontfragment;
-
- if (address_family == AddressFamily.InterNetwork) {
- dontfragment = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
- } else if (address_family == AddressFamily.InterNetworkV6) {
- dontfragment = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
- } else {
+ ThrowIfDisposedAndClosed ();
+
+ switch (address_family) {
+ case AddressFamily.InterNetwork:
+ return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
+ case AddressFamily.InterNetworkV6:
+ return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
+ default:
throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
}
-
- return(dontfragment);
}
set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
-
- if (address_family == AddressFamily.InterNetwork) {
- SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value?1:0);
- } else if (address_family == AddressFamily.InterNetworkV6) {
- SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value?1:0);
- } else {
+ ThrowIfDisposedAndClosed ();
+
+ switch (address_family) {
+ case AddressFamily.InterNetwork:
+ SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
+ break;
+ case AddressFamily.InterNetworkV6:
+ SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
+ break;
+ default:
throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
}
}
public bool EnableBroadcast {
get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
+ ThrowIfDisposedAndClosed ();
- if (protocol_type != ProtocolType.Udp) {
- throw new SocketException ((int)SocketError.ProtocolOption);
- }
-
- return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0);
+ if (protocol_type != ProtocolType.Udp)
+ throw new SocketException ((int) SocketError.ProtocolOption);
+
+ return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
}
set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
+ ThrowIfDisposedAndClosed ();
- if (protocol_type != ProtocolType.Udp) {
- throw new SocketException ((int)SocketError.ProtocolOption);
- }
+ if (protocol_type != ProtocolType.Udp)
+ throw new SocketException ((int) SocketError.ProtocolOption);
- SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value?1:0);
+ SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
}
}
-
+
public bool ExclusiveAddressUse {
get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
+ ThrowIfDisposedAndClosed ();
- return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0);
+ return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
}
set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
- if (isbound) {
+ ThrowIfDisposedAndClosed ();
+
+ if (is_bound)
throw new InvalidOperationException ("Bind has already been called for this socket");
- }
-
- SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value?1:0);
+
+ SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
}
}
-
+
public bool IsBound {
get {
- return(isbound);
+ return is_bound;
}
}
-
+
public LingerOption LingerState {
get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
+ ThrowIfDisposedAndClosed ();
- return((LingerOption)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger));
+ return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
}
set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
-
- SetSocketOption (SocketOptionLevel.Socket,
- SocketOptionName.Linger,
- value);
+ ThrowIfDisposedAndClosed ();
+ SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
}
}
-
+
public bool MulticastLoopback {
get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
-
- /* Even though this option can be set
- * for TCP sockets on Linux, throw
- * this exception anyway to be
- * compatible (the MSDN docs say
- * "Setting this property on a
- * Transmission Control Protocol (TCP)
- * socket will have no effect." but
- * the MS runtime throws the
- * exception...)
- */
- if (protocol_type == ProtocolType.Tcp) {
+ ThrowIfDisposedAndClosed ();
+
+ /* Even though this option can be set for TCP sockets on Linux, throw
+ * this exception anyway to be compatible (the MSDN docs say
+ * "Setting this property on a Transmission Control Protocol (TCP)
+ * socket will have no effect." but the MS runtime throws the
+ * exception...) */
+ if (protocol_type == ProtocolType.Tcp)
throw new SocketException ((int)SocketError.ProtocolOption);
- }
-
- bool multicastloopback;
-
- if (address_family == AddressFamily.InterNetwork) {
- multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
- } else if (address_family == AddressFamily.InterNetworkV6) {
- multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
- } else {
+
+ switch (address_family) {
+ case AddressFamily.InterNetwork:
+ return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
+ case AddressFamily.InterNetworkV6:
+ return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
+ default:
throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
}
-
- return(multicastloopback);
}
set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
-
- /* Even though this option can be set
- * for TCP sockets on Linux, throw
- * this exception anyway to be
- * compatible (the MSDN docs say
- * "Setting this property on a
- * Transmission Control Protocol (TCP)
- * socket will have no effect." but
- * the MS runtime throws the
- * exception...)
- */
- if (protocol_type == ProtocolType.Tcp) {
+ ThrowIfDisposedAndClosed ();
+
+ /* Even though this option can be set for TCP sockets on Linux, throw
+ * this exception anyway to be compatible (the MSDN docs say
+ * "Setting this property on a Transmission Control Protocol (TCP)
+ * socket will have no effect." but the MS runtime throws the
+ * exception...) */
+ if (protocol_type == ProtocolType.Tcp)
throw new SocketException ((int)SocketError.ProtocolOption);
- }
-
- if (address_family == AddressFamily.InterNetwork) {
- SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value?1:0);
- } else if (address_family == AddressFamily.InterNetworkV6) {
- SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value?1:0);
- } else {
+
+ switch (address_family) {
+ case AddressFamily.InterNetwork:
+ SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
+ break;
+ case AddressFamily.InterNetworkV6:
+ SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
+ break;
+ default:
throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
}
}
}
-
-
+
[MonoTODO ("This doesn't do anything on Mono yet")]
public bool UseOnlyOverlappedIO {
- get {
- return(useoverlappedIO);
- }
- set {
- useoverlappedIO = value;
- }
+ get { return use_overlapped_io; }
+ set { use_overlapped_io = value; }
}
public IntPtr Handle {
- get {
- return(socket.DangerousGetHandle ());
- }
- }
-
- // Returns the local endpoint details in addr and port
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, int family, out int error);
-
- private static SocketAddress LocalEndPoint_internal(SafeSocketHandle safeHandle, int family, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
+ get { return safe_handle.DangerousGetHandle (); }
}
// Wish: support non-IP endpoints.
public EndPoint LocalEndPoint {
get {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- /*
- * If the seed EndPoint is null, Connect, Bind,
- * etc has not yet been called. MS returns null
- * in this case.
- */
+ ThrowIfDisposedAndClosed ();
+
+ /* If the seed EndPoint is null, Connect, Bind, etc has not yet
+ * been called. MS returns null in this case. */
if (seed_endpoint == null)
return null;
-
- SocketAddress sa;
+
int error;
-
- sa=LocalEndPoint_internal(socket, (int) address_family, out error);
+ SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
if (error != 0)
throw new SocketException (error);
}
}
- public SocketType SocketType {
- get {
- return(socket_type);
+ static SocketAddress LocalEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
}
}
+ /* Returns the local endpoint details in addr and port */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
+
+ public SocketType SocketType {
+ get { return socket_type; }
+ }
+
public int SendTimeout {
get {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- return (int)GetSocketOption(
- SocketOptionLevel.Socket,
- SocketOptionName.SendTimeout);
+ return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
}
set {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
if (value < -1)
throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
- /* According to the MSDN docs we
- * should adjust values between 1 and
- * 499 to 500, but the MS runtime
- * doesn't do this.
- */
+ /* According to the MSDN docs we should adjust values between 1 and
+ * 499 to 500, but the MS runtime doesn't do this. */
if (value == -1)
value = 0;
- SetSocketOption(
- SocketOptionLevel.Socket,
- SocketOptionName.SendTimeout, value);
+ SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
}
}
public int ReceiveTimeout {
get {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- return (int)GetSocketOption(
- SocketOptionLevel.Socket,
- SocketOptionName.ReceiveTimeout);
+ return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
}
set {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
if (value < -1)
throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
- if (value == -1) {
+ if (value == -1)
value = 0;
- }
-
- SetSocketOption(
- SocketOptionLevel.Socket,
- SocketOptionName.ReceiveTimeout, value);
+
+ SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
}
}
- public bool AcceptAsync (SocketAsyncEventArgs e)
- {
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
-
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (!IsBound)
- throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
- if (!islistening)
- throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
- if (e.BufferList != null)
- throw new ArgumentException ("Multiple buffers cannot be used with this method.");
- if (e.Count < 0)
- throw new ArgumentOutOfRangeException ("e.Count");
+ public AddressFamily AddressFamily {
+ get { return address_family; }
+ }
- Socket acceptSocket = e.AcceptSocket;
- if (acceptSocket != null) {
- if (acceptSocket.IsBound || acceptSocket.Connected)
- throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
- }
+ public bool Blocking {
+ get { return is_blocking; }
+ set {
+ ThrowIfDisposedAndClosed ();
- e.curSocket = this;
- Worker w = e.Worker;
- w.Init (this, e, SocketOperation.Accept);
- int count;
- lock (readQ) {
- readQ.Enqueue (e.Worker);
- count = readQ.Count;
+ int error;
+ Blocking_internal (safe_handle, value, out error);
+
+ if (error != 0)
+ throw new SocketException (error);
+
+ is_blocking = value;
}
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, w.result);
- return true;
}
- // Creates a new system socket, returning the handle
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
- private static SafeSocketHandle Accept_internal(SafeSocketHandle safeHandle, out int error, bool blocking)
+ static void Blocking_internal (SafeSocketHandle safeHandle, bool block, out int error)
{
+ bool release = false;
try {
- safeHandle.RegisterForBlockingSyscall ();
- var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
- return new SafeSocketHandle (ret, true);
+ safeHandle.DangerousAddRef (ref release);
+ Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
} finally {
- safeHandle.UnRegisterForBlockingSyscall ();
+ if (release)
+ safeHandle.DangerousRelease ();
}
}
- public Socket Accept() {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static void Blocking_internal(IntPtr socket, bool block, out int error);
+
+ public bool Connected {
+ get { return is_connected; }
+ internal set { is_connected = value; }
+ }
+
+ public ProtocolType ProtocolType {
+ get { return protocol_type; }
+ }
+
+ public bool NoDelay {
+ get {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfUdp ();
+
+ return ((int) GetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0;
+ }
+
+ set {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfUdp ();
+
+ SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
+ }
+ }
+
+ public int ReceiveBufferSize {
+ get {
+ ThrowIfDisposedAndClosed ();
+
+ return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
+ }
+ set {
+ ThrowIfDisposedAndClosed ();
+
+ if (value < 0)
+ throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
+
+ SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
+ }
+ }
+
+ public int SendBufferSize {
+ get {
+ ThrowIfDisposedAndClosed ();
+
+ return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
+ }
+ set {
+ ThrowIfDisposedAndClosed ();
+
+ if (value < 0)
+ throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
+
+ SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
+ }
+ }
+
+ public short Ttl {
+ get {
+ ThrowIfDisposedAndClosed ();
+
+ switch (address_family) {
+ case AddressFamily.InterNetwork:
+ return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
+ case AddressFamily.InterNetworkV6:
+ return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
+ default:
+ throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
+ }
+ }
+ set {
+ ThrowIfDisposedAndClosed ();
+
+ if (value < 0)
+ throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
+
+ switch (address_family) {
+ case AddressFamily.InterNetwork:
+ SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
+ break;
+ case AddressFamily.InterNetworkV6:
+ SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
+ break;
+ default:
+ throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
+ }
+ }
+ }
+
+ public EndPoint RemoteEndPoint {
+ get {
+ ThrowIfDisposedAndClosed ();
+
+ /* If the seed EndPoint is null, Connect, Bind, etc has
+ * not yet been called. MS returns null in this case. */
+ if (!is_connected || seed_endpoint == null)
+ return null;
+
+ int error;
+ SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
+
+ if (error != 0)
+ throw new SocketException (error);
+
+ return seed_endpoint.Create (sa);
+ }
+ }
+
+ static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
+
+ /* Returns the remote endpoint details in addr and port */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static SocketAddress RemoteEndPoint_internal (IntPtr socket, int family, out int error);
+
+#endregion
+
+#region Select
+
+ public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
+ {
+ var list = new List<Socket> ();
+ AddSockets (list, checkRead, "checkRead");
+ AddSockets (list, checkWrite, "checkWrite");
+ AddSockets (list, checkError, "checkError");
+
+ if (list.Count == 3)
+ throw new ArgumentNullException ("checkRead, checkWrite, checkError", "All the lists are null or empty.");
+
+ /* The 'sockets' array contains:
+ * - READ socket 0-n, null,
+ * - WRITE socket 0-n, null,
+ * - ERROR socket 0-n, null */
+ Socket [] sockets = list.ToArray ();
+
+ int error;
+ Select_internal (ref sockets, microSeconds, out error);
+
+ if (error != 0)
+ throw new SocketException (error);
+
+ if (sockets == null) {
+ if (checkRead != null)
+ checkRead.Clear ();
+ if (checkWrite != null)
+ checkWrite.Clear ();
+ if (checkError != null)
+ checkError.Clear ();
+ return;
+ }
+
+ int mode = 0;
+ int count = sockets.Length;
+ IList currentList = checkRead;
+ int currentIdx = 0;
+ for (int i = 0; i < count; i++) {
+ Socket sock = sockets [i];
+ if (sock == null) { // separator
+ if (currentList != null) {
+ // Remove non-signaled sockets after the current one
+ int to_remove = currentList.Count - currentIdx;
+ for (int k = 0; k < to_remove; k++)
+ currentList.RemoveAt (currentIdx);
+ }
+ currentList = (mode == 0) ? checkWrite : checkError;
+ currentIdx = 0;
+ mode++;
+ continue;
+ }
+
+ if (mode == 1 && currentList == checkWrite && !sock.is_connected) {
+ if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
+ sock.is_connected = true;
+ }
+
+ /* Remove non-signaled sockets before the current one */
+ while (((Socket) currentList [currentIdx]) != sock)
+ currentList.RemoveAt (currentIdx);
+
+ currentIdx++;
+ }
+ }
+
+ static void AddSockets (List<Socket> sockets, IList list, string name)
+ {
+ if (list != null) {
+ foreach (Socket sock in list) {
+ if (sock == null) // MS throws a NullRef
+ throw new ArgumentNullException ("name", "Contains a null element");
+ sockets.Add (sock);
+ }
+ }
+
+ sockets.Add (null);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void Select_internal (ref Socket [] sockets, int microSeconds, out int error);
+
+#endregion
+
+#region Poll
+
+ public bool Poll (int time_us, SelectMode mode)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (mode != SelectMode.SelectRead && mode != SelectMode.SelectWrite && mode != SelectMode.SelectError)
+ throw new NotSupportedException ("'mode' parameter is not valid.");
+
+ int error;
+ bool result = Poll_internal (safe_handle, mode, time_us, out error);
+
+ if (error != 0)
+ throw new SocketException (error);
+
+ if (mode == SelectMode.SelectWrite && result && !is_connected) {
+ /* Update the is_connected state; for non-blocking Connect()
+ * this is when we can find out that the connect succeeded. */
+ if ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
+ is_connected = true;
+ }
+
+ return result;
+ }
+
+ static bool Poll_internal (SafeSocketHandle safeHandle, SelectMode mode, int timeout, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ return Poll_internal (safeHandle.DangerousGetHandle (), mode, timeout, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
+
+#endregion
+
+#region Accept
+
+ public Socket Accept()
+ {
+ ThrowIfDisposedAndClosed ();
int error = 0;
- var sock = Accept_internal(socket, out error, blocking);
+ SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
if (error != 0) {
- if (closed)
- error = SOCKET_CLOSED;
+ if (is_closed)
+ error = SOCKET_CLOSED_CODE;
throw new SocketException(error);
}
- Socket accepted = new Socket(this.AddressFamily, this.SocketType,
- this.ProtocolType, sock);
+ Socket accepted = new Socket (this.AddressFamily, this.SocketType, this.ProtocolType, safe_handle) {
+ seed_endpoint = this.seed_endpoint,
+ Blocking = this.Blocking,
+ };
- accepted.seed_endpoint = this.seed_endpoint;
- accepted.Blocking = this.Blocking;
- return(accepted);
+ return accepted;
}
internal void Accept (Socket acceptSocket)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
+ ThrowIfDisposedAndClosed ();
+
int error = 0;
- var sock = Accept_internal (socket, out error, blocking);
-
+ SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
+
if (error != 0) {
- if (closed)
- error = SOCKET_CLOSED;
+ if (is_closed)
+ error = SOCKET_CLOSED_CODE;
throw new SocketException (error);
}
-
+
acceptSocket.address_family = this.AddressFamily;
acceptSocket.socket_type = this.SocketType;
acceptSocket.protocol_type = this.ProtocolType;
- acceptSocket.socket = sock;
- acceptSocket.connected = true;
+ acceptSocket.safe_handle = safe_handle;
+ acceptSocket.is_connected = true;
acceptSocket.seed_endpoint = this.seed_endpoint;
acceptSocket.Blocking = this.Blocking;
- /* FIXME: figure out what if anything else
- * needs to be reset
- */
+ // FIXME: figure out what if anything else needs to be reset
+ }
+
+ public bool AcceptAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ ThrowIfDisposedAndClosed ();
+
+ if (!is_bound)
+ throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
+ if (!is_listening)
+ throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
+ if (e.BufferList != null)
+ throw new ArgumentException ("Multiple buffers cannot be used with this method.");
+ if (e.Count < 0)
+ throw new ArgumentOutOfRangeException ("e.Count");
+
+ Socket acceptSocket = e.AcceptSocket;
+ if (acceptSocket != null) {
+ if (acceptSocket.is_bound || acceptSocket.is_connected)
+ throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
+ }
+
+ e.curSocket = this;
+ e.Worker.Init (this, e, SocketOperation.Accept);
+
+ SocketAsyncResult sockares = e.Worker.result;
+
+ QueueSocketAsyncResult (readQ, e.Worker, sockares);
+
+ return true;
}
public IAsyncResult BeginAccept(AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (!isbound || !islistening)
+ if (!is_bound || !is_listening)
throw new InvalidOperationException ();
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
- int count;
- lock (readQ) {
- readQ.Enqueue (req.Worker);
- count = readQ.Count;
- }
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
+
+ QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
+
+ return sockares;
}
- public IAsyncResult BeginAccept (int receiveSize,
- AsyncCallback callback,
- object state)
+ public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
if (receiveSize < 0)
throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
- req.Buffer = new byte[receiveSize];
- req.Offset = 0;
- req.Size = receiveSize;
- req.SockFlags = SocketFlags.None;
- int count;
- lock (readQ) {
- readQ.Enqueue (req.Worker);
- count = readQ.Count;
- }
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive) {
+ Buffer = new byte [receiveSize],
+ Offset = 0,
+ Size = receiveSize,
+ SockFlags = SocketFlags.None,
+ };
+
+ QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
+
+ return sockares;
}
- public IAsyncResult BeginAccept (Socket acceptSocket,
- int receiveSize,
- AsyncCallback callback,
- object state)
+ public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
if (receiveSize < 0)
throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
if (acceptSocket != null) {
- if (acceptSocket.disposed && acceptSocket.closed)
- throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
+ ThrowIfDisposedAndClosed (acceptSocket);
if (acceptSocket.IsBound)
throw new InvalidOperationException ();
throw new SocketException ((int)SocketError.InvalidArgument);
}
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
- req.Buffer = new byte[receiveSize];
- req.Offset = 0;
- req.Size = receiveSize;
- req.SockFlags = SocketFlags.None;
- req.AcceptSocket = acceptSocket;
- int count;
- lock (readQ) {
- readQ.Enqueue (req.Worker);
- count = readQ.Count;
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive) {
+ Buffer = new byte [receiveSize],
+ Offset = 0,
+ Size = receiveSize,
+ SockFlags = SocketFlags.None,
+ AcceptSocket = acceptSocket,
+ };
+
+ QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
+
+ return sockares;
+ }
+
+ public Socket EndAccept (IAsyncResult result)
+ {
+ int bytes;
+ byte[] buffer;
+ return EndAccept (out buffer, out bytes, result);
+ }
+
+ public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
+ {
+ int bytes;
+ return EndAccept (out buffer, out bytes, asyncResult);
+ }
+
+ public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndAccept", "asyncResult");
+
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne ();
+
+ sockares.CheckIfThrowDelayedException ();
+
+ buffer = sockares.Buffer;
+ bytesTransferred = sockares.Total;
+
+ return sockares.Socket;
+ }
+
+ static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
+ {
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
+ return new SafeSocketHandle (ret, true);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
}
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return(req);
}
- public IAsyncResult BeginConnect (IPAddress address, int port,
- AsyncCallback callback,
- object state)
+ /* Creates a new system socket, returning the handle */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static IntPtr Accept_internal (IntPtr sock, out int error, bool blocking);
+
+#endregion
+
+#region Bind
+
+ public void Bind (EndPoint local_end)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (address == null)
- throw new ArgumentNullException ("address");
+ if (local_end == null)
+ throw new ArgumentNullException("local_end");
+ int error;
+ Bind_internal (safe_handle, local_end.Serialize(), out error);
+
+ if (error != 0)
+ throw new SocketException (error);
+ if (error == 0)
+ is_bound = true;
+
+ seed_endpoint = local_end;
+ }
+
+ private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
+
+ // Creates a new system socket, returning the handle
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Bind_internal(IntPtr sock, SocketAddress sa, out int error);
+
+#endregion
+
+#region Listen
+
+ public void Listen (int backlog)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (!is_bound)
+ throw new SocketException ((int) SocketError.InvalidArgument);
+
+ int error;
+ Listen_internal(safe_handle, backlog, out error);
+
+ if (error != 0)
+ throw new SocketException (error);
+
+ is_listening = true;
+ }
+
+ static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void Listen_internal (IntPtr sock, int backlog, out int error);
+
+#endregion
+
+#region Connect
+
+ public void Connect (IPAddress address, int port)
+ {
+ Connect (new IPEndPoint (address, port));
+ }
+
+ public void Connect (string host, int port)
+ {
+ Connect (Dns.GetHostAddresses (host), port);
+ }
+
+ public void Connect (IPAddress[] addresses, int port)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (addresses == null)
+ throw new ArgumentNullException ("addresses");
+ if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
+ throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
+ if (is_listening)
+ throw new InvalidOperationException ();
+
+ // FIXME: do non-blocking sockets Poll here?
+ int error = 0;
+ foreach (IPAddress address in addresses) {
+ IPEndPoint iep = new IPEndPoint (address, port);
+
+ Connect_internal (safe_handle, iep.Serialize (), out error);
+ if (error == 0) {
+ is_connected = true;
+ is_bound = true;
+ seed_endpoint = iep;
+ return;
+ }
+ if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
+ continue;
+
+ if (!is_blocking) {
+ Poll (-1, SelectMode.SelectWrite);
+ error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
+ if (error == 0) {
+ is_connected = true;
+ is_bound = true;
+ seed_endpoint = iep;
+ return;
+ }
+ }
+ }
+
+ if (error != 0)
+ throw new SocketException (error);
+ }
+
+
+ public void Connect (EndPoint remoteEP)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (remoteEP == null)
+ throw new ArgumentNullException ("remoteEP");
+
+ IPEndPoint ep = remoteEP as IPEndPoint;
+ /* Dgram uses Any to 'disconnect' */
+ if (ep != null && socket_type != SocketType.Dgram) {
+ if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
+ throw new SocketException ((int) SocketError.AddressNotAvailable);
+ }
+
+ if (is_listening)
+ throw new InvalidOperationException ();
+
+ SocketAddress serial = remoteEP.Serialize ();
+
+ int error = 0;
+ Connect_internal (safe_handle, serial, out error);
+
+ if (error == 0 || error == 10035)
+ seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
+
+ if (error != 0) {
+ if (is_closed)
+ error = SOCKET_CLOSED_CODE;
+ throw new SocketException (error);
+ }
+
+ is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
+ is_bound = true;
+ }
+
+ public bool ConnectAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ ThrowIfDisposedAndClosed ();
+
+ if (is_listening)
+ throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
+ if (e.RemoteEndPoint == null)
+ throw new ArgumentNullException ("remoteEP");
+
+ e.curSocket = this;
+ e.Worker.Init (this, e, SocketOperation.Connect);
+
+ SocketAsyncResult result = e.Worker.result;
+
+ try {
+ IPAddress [] addresses;
+ IAsyncResult ares;
+
+ if (!GetCheckedIPs (e, out addresses)) {
+ result.EndPoint = e.RemoteEndPoint;
+ ares = BeginConnect (e.RemoteEndPoint, SocketAsyncEventArgs.Dispatcher, e);
+ } else {
+ DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
+ result.Addresses = addresses;
+ result.Port = dep.Port;
+ ares = BeginConnect (addresses, dep.Port, SocketAsyncEventArgs.Dispatcher, e);
+ }
+
+ if (ares.IsCompleted && ares.CompletedSynchronously) {
+ ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
+ return false;
+ }
+ } catch (Exception exc) {
+ result.Complete (exc, true);
+ return false;
+ }
+
+ return true;
+ }
+
+ public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (address == null)
+ throw new ArgumentNullException ("address");
if (address.ToString ().Length == 0)
throw new ArgumentException ("The length of the IP address is zero");
+ if (port <= 0 || port > 65535)
+ throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+ if (is_listening)
+ throw new InvalidOperationException ();
+
+ return BeginConnect (new IPEndPoint (address, port), callback, state);
+ }
+
+ public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (host == null)
+ throw new ArgumentNullException ("host");
+ if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
+ throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
+ if (port <= 0 || port > 65535)
+ throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+ if (is_listening)
+ throw new InvalidOperationException ();
+
+ return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
+ }
+
+ public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (end_point == null)
+ throw new ArgumentNullException ("end_point");
+
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Connect) {
+ EndPoint = end_point,
+ };
+
+ // Bug #75154: Connect() should not succeed for .Any addresses.
+ if (end_point is IPEndPoint) {
+ IPEndPoint ep = (IPEndPoint) end_point;
+ if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
+ sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
+ return sockares;
+ }
+ }
+
+ int error = 0;
+
+ if (connect_in_progress) {
+ // This could happen when multiple IPs are used
+ // Calling connect() again will reset the connection attempt and cause
+ // an error. Better to just close the socket and move on.
+ connect_in_progress = false;
+ safe_handle.Dispose ();
+ var handle = Socket_internal (address_family, socket_type, protocol_type, out error);
+ safe_handle = new SafeSocketHandle (handle, true);
+ if (error != 0)
+ throw new SocketException (error);
+ }
+
+ bool blk = is_blocking;
+ if (blk)
+ Blocking = false;
+ Connect_internal (safe_handle, end_point.Serialize (), out error);
+ if (blk)
+ Blocking = true;
+
+ if (error == 0) {
+ // succeeded synch
+ is_connected = true;
+ is_bound = true;
+ sockares.Complete (true);
+ return sockares;
+ }
+
+ if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
+ // error synch
+ is_connected = false;
+ is_bound = false;
+ sockares.Complete (new SocketException (error), true);
+ return sockares;
+ }
+
+ // continue asynch
+ is_connected = false;
+ is_bound = false;
+ connect_in_progress = true;
+
+ socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
+
+ return sockares;
+ }
+
+ public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (addresses == null)
+ throw new ArgumentNullException ("addresses");
+ if (addresses.Length == 0)
+ throw new ArgumentException ("Empty addresses list");
+ if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
+ throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
+ if (port <= 0 || port > 65535)
+ throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+ if (is_listening)
+ throw new InvalidOperationException ();
+
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Connect) {
+ Addresses = addresses,
+ Port = port,
+ };
+
+ is_connected = false;
+
+ return BeginMConnect (sockares);
+ }
+
+ internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
+ {
+ IAsyncResult ares = null;
+ Exception exc = null;
+
+ for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
+ try {
+ sockares.CurrentAddress++;
+
+ ares = BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
+ if (ares.IsCompleted && ares.CompletedSynchronously) {
+ ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
+ sockares.DoMConnectCallback ();
+ }
+
+ break;
+ } catch (Exception e) {
+ exc = e;
+ ares = null;
+ }
+ }
+
+ if (ares == null)
+ throw exc;
+
+ return sockares;
+ }
+
+ public void EndConnect (IAsyncResult result)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
+
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne();
+
+ sockares.CheckIfThrowDelayedException();
+ }
+
+ static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
+ {
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
+ }
+ }
+
+ /* Connects to the remote address */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
+
+ /* Returns :
+ * - false when it is ok to use RemoteEndPoint
+ * - true when addresses must be used (and addresses could be null/empty) */
+ bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
+ {
+ addresses = null;
+
+ // Connect to the first address that match the host name, like:
+ // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
+ // while skipping entries that do not match the address family
+ DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
+ if (dep != null) {
+ addresses = Dns.GetHostAddresses (dep.Host);
+ return true;
+ } else {
+ e.ConnectByNameError = null;
+ return false;
+ }
+ }
+
+#endregion
+
+#region Disconnect
+
+ /* According to the docs, the MS runtime will throw PlatformNotSupportedException
+ * if the platform is newer than w2k. We should be able to cope... */
+ public void Disconnect (bool reuseSocket)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ int error = 0;
+ Disconnect_internal (safe_handle, reuseSocket, out error);
+
+ if (error != 0) {
+ if (error == 50) {
+ /* ERROR_NOT_SUPPORTED */
+ throw new PlatformNotSupportedException ();
+ } else {
+ throw new SocketException (error);
+ }
+ }
+
+ is_connected = false;
+ if (reuseSocket) {
+ /* Do managed housekeeping here... */
+ }
+ }
+
+ public bool DisconnectAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ ThrowIfDisposedAndClosed ();
+
+ e.curSocket = this;
+ e.Worker.Init (this, e, SocketOperation.Disconnect);
+
+ SocketAsyncResult sockares = e.Worker.result;
+
+ socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
+
+ return true;
+ }
+
+
+ public IAsyncResult BeginDisconnect (bool reuseSocket, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect) {
+ ReuseSocket = reuseSocket,
+ };
+
+ socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
+
+ return sockares;
+ }
+
+ public void EndDisconnect (IAsyncResult asyncResult)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndDisconnect", "asyncResult");
+
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne ();
+
+ sockares.CheckIfThrowDelayedException ();
+ }
+
+ static void Disconnect_internal (SafeSocketHandle safeHandle, bool reuse, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void Disconnect_internal (IntPtr sock, bool reuse, out int error);
+
+#endregion
+
+#region Receive
+
+ public int Receive (byte [] buffer)
+ {
+ return Receive (buffer, SocketFlags.None);
+ }
+
+ public int Receive (byte [] buffer, SocketFlags flags)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
+
+ SocketError error;
+ int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
+
+ if (error != SocketError.Success) {
+ if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
+ throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
+ throw new SocketException ((int) error);
+ }
+
+ return ret;
+ }
+
+ public int Receive (byte [] buffer, int size, SocketFlags flags)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, size);
+
+ SocketError error;
+ int ret = Receive_nochecks (buffer, 0, size, flags, out error);
+
+ if (error != SocketError.Success) {
+ if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
+ throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
+ throw new SocketException ((int) error);
+ }
+
+ return ret;
+ }
+
+ public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
+
+ SocketError error;
+ int ret = Receive_nochecks (buffer, offset, size, flags, out error);
+
+ if (error != SocketError.Success) {
+ if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
+ throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
+ throw new SocketException ((int) error);
+ }
+
+ return ret;
+ }
+
+ public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
+
+ return Receive_nochecks (buffer, offset, size, flags, out error);
+ }
+
+ public int Receive (IList<ArraySegment<byte>> buffers)
+ {
+ SocketError error;
+ int ret = Receive (buffers, SocketFlags.None, out error);
+
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
+
+ return ret;
+ }
+
+ [CLSCompliant (false)]
+ public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
+ {
+ SocketError error;
+ int ret = Receive (buffers, socketFlags, out error);
+
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
+
+ return(ret);
+ }
+
+ [CLSCompliant (false)]
+ public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (buffers == null || buffers.Count == 0)
+ throw new ArgumentNullException ("buffers");
+
+ int numsegments = buffers.Count;
+ int nativeError;
+ int ret;
+
+ /* Only example I can find of sending a byte array reference directly into an internal
+ * call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
+ * so taking a lead from that... */
+ WSABUF[] bufarray = new WSABUF[numsegments];
+ GCHandle[] gch = new GCHandle[numsegments];
+
+ for (int i = 0; i < numsegments; i++) {
+ ArraySegment<byte> segment = buffers[i];
+
+ if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
+ throw new ArgumentOutOfRangeException ("segment");
+
+ gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
+ bufarray[i].len = segment.Count;
+ bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
+ }
+
+ try {
+ ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
+ } finally {
+ for (int i = 0; i < numsegments; i++) {
+ if (gch[i].IsAllocated)
+ gch[i].Free ();
+ }
+ }
+
+ errorCode = (SocketError) nativeError;
+
+ return ret;
+ }
+
+ public bool ReceiveAsync (SocketAsyncEventArgs e)
+ {
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
+
+ ThrowIfDisposedAndClosed ();
+
+ // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
+ // thrown when e.Buffer and e.BufferList are null (works fine when one is
+ // set to a valid object)
+ if (e.Buffer == null && e.BufferList == null)
+ throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
+
+ e.curSocket = this;
+ e.Worker.Init (this, e, e.Buffer != null ? SocketOperation.Receive : SocketOperation.ReceiveGeneric);
+
+ SocketAsyncResult sockares = e.Worker.result;
+ sockares.SockFlags = e.SocketFlags;
+
+ if (e.Buffer != null) {
+ sockares.Buffer = e.Buffer;
+ sockares.Offset = e.Offset;
+ sockares.Size = e.Count;
+ } else {
+ sockares.Buffers = e.BufferList;
+ }
+
+ // Receive takes care of ReceiveGeneric
+ QueueSocketAsyncResult (readQ, e.Worker, sockares);
+
+ return true;
+ }
+
+ public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
+
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Receive) {
+ Buffer = buffer,
+ Offset = offset,
+ Size = size,
+ SockFlags = socket_flags,
+ };
+
+ QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
+
+ return sockares;
+ }
+
+ public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
+ {
+ /* As far as I can tell from the docs and from experimentation, a pointer to the
+ * SocketError parameter is not supposed to be saved for the async parts. And as we don't
+ * set any socket errors in the setup code, we just have to set it to Success. */
+ error = SocketError.Success;
+ return BeginReceive (buffer, offset, size, flags, callback, state);
+ }
+
+ [CLSCompliant (false)]
+ public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ if (buffers == null)
+ throw new ArgumentNullException ("buffers");
+
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric) {
+ Buffers = buffers,
+ SockFlags = socketFlags,
+ };
+
+ QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
+
+ return sockares;
+ }
+
+ [CLSCompliant (false)]
+ public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
+ {
+ /* I assume the same SocketError semantics as above */
+ errorCode = SocketError.Success;
+ return BeginReceive (buffers, socketFlags, callback, state);
+ }
+
+ public int EndReceive (IAsyncResult result)
+ {
+ SocketError error;
+ int bytesReceived = EndReceive (result, out error);
+
+ if (error != SocketError.Success) {
+ if (error != SocketError.WouldBlock && error != SocketError.InProgress)
+ is_connected = false;
+ throw new SocketException ((int)error);
+ }
+
+ return bytesReceived;
+ }
+
+ public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceive", "asyncResult");
+
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne ();
+
+ // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
+ // kinds of exceptions that should be thrown.
+ if ((errorCode = sockares.ErrorCode) == SocketError.Success)
+ sockares.CheckIfThrowDelayedException();
+
+ return sockares.Total;
+ }
+
+ internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+ {
+ int nativeError;
+ int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
+
+ error = (SocketError) nativeError;
+ if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
+ is_connected = false;
+ is_bound = false;
+ } else {
+ is_connected = true;
+ }
+
+ return ret;
+ }
+
+ static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
+ {
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
+ }
+ }
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
+
+ static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
+ {
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
+
+#endregion
+
+#region ReceiveFrom
+
+ public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
+
+ if (remoteEP == null)
+ throw new ArgumentNullException ("remoteEP");
+
+ return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
+ }
+
+ public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
+
+ if (remoteEP == null)
+ throw new ArgumentNullException ("remoteEP");
+
+ return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
+ }
+
+ public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, size);
+
+ if (remoteEP == null)
+ throw new ArgumentNullException ("remoteEP");
+
+ return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
+ }
+
+ public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
+
+ if (remoteEP == null)
+ throw new ArgumentNullException ("remoteEP");
+
+ return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
+ }
+
+ public bool ReceiveFromAsync (SocketAsyncEventArgs e)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ // We do not support recv into multiple buffers yet
+ if (e.BufferList != null)
+ throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
+ if (e.RemoteEndPoint == null)
+ throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
+
+ e.curSocket = this;
+ e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
- if (port <= 0 || port > 65535)
- throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+ SocketAsyncResult sockares = e.Worker.result;
+ sockares.Buffer = e.Buffer;
+ sockares.Offset = e.Offset;
+ sockares.Size = e.Count;
+ sockares.EndPoint = e.RemoteEndPoint;
+ sockares.SockFlags = e.SocketFlags;
- if (islistening)
- throw new InvalidOperationException ();
+ QueueSocketAsyncResult (readQ, e.Worker, sockares);
- IPEndPoint iep = new IPEndPoint (address, port);
- return(BeginConnect (iep, callback, state));
+ return true;
}
- public IAsyncResult BeginConnect (string host, int port,
- AsyncCallback callback,
- object state)
+ public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (host == null)
- throw new ArgumentNullException ("host");
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- if (address_family != AddressFamily.InterNetwork &&
- address_family != AddressFamily.InterNetworkV6)
- throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
- if (port <= 0 || port > 65535)
- throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom) {
+ Buffer = buffer,
+ Offset = offset,
+ Size = size,
+ SockFlags = socket_flags,
+ EndPoint = remote_end,
+ };
- if (islistening)
- throw new InvalidOperationException ();
+ QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
- return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
+ return sockares;
}
- public IAsyncResult BeginDisconnect (bool reuseSocket,
- AsyncCallback callback,
- object state)
+ public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
- req.ReuseSocket = reuseSocket;
- socket_pool_queue (Worker.Dispatcher, req);
- return(req);
- }
+ if (end_point == null)
+ throw new ArgumentNullException ("remote_end");
- void CheckRange (byte[] buffer, int offset, int size)
- {
- if (offset < 0)
- throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
- if (offset > buffer.Length)
- throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
- if (size < 0)
- throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
-
- if (size > buffer.Length - offset)
- throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
- }
-
- public IAsyncResult BeginReceive(byte[] buffer, int offset,
- int size,
- SocketFlags socket_flags,
- AsyncCallback callback,
- object state) {
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne();
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ sockares.CheckIfThrowDelayedException();
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ end_point = sockares.EndPoint;
- CheckRange (buffer, offset, size);
+ return sockares.Total;
+ }
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- int count;
- lock (readQ) {
- readQ.Enqueue (req.Worker);
- count = readQ.Count;
- }
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
- }
-
- public IAsyncResult BeginReceive (byte[] buffer, int offset,
- int size, SocketFlags flags,
- out SocketError error,
- AsyncCallback callback,
- object state)
- {
- /* As far as I can tell from the docs and from
- * experimentation, a pointer to the
- * SocketError parameter is not supposed to be
- * saved for the async parts. And as we don't
- * set any socket errors in the setup code, we
- * just have to set it to Success.
- */
- error = SocketError.Success;
- return (BeginReceive (buffer, offset, size, flags, callback, state));
+ internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end)
+ {
+ int error;
+ return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
}
- [CLSCompliant (false)]
- public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
- SocketFlags socketFlags,
- AsyncCallback callback,
- object state)
+ internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ SocketAddress sockaddr = remote_end.Serialize();
- if (buffers == null)
- throw new ArgumentNullException ("buffers");
+ int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
- req.Buffers = buffers;
- req.SockFlags = socketFlags;
- int count;
- lock(readQ) {
- readQ.Enqueue (req.Worker);
- count = readQ.Count;
+ SocketError err = (SocketError) error;
+ if (err != 0) {
+ if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
+ is_connected = false;
+ } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
+ if (throwOnError)
+ throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
+ error = (int) SocketError.TimedOut;
+ return 0;
+ }
+
+ if (throwOnError)
+ throw new SocketException (error);
+
+ return 0;
}
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
- }
-
- [CLSCompliant (false)]
- public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
- SocketFlags socketFlags,
- out SocketError errorCode,
- AsyncCallback callback,
- object state)
- {
- /* I assume the same SocketError semantics as
- * above
- */
- errorCode = SocketError.Success;
- return (BeginReceive (buffers, socketFlags, callback, state));
- }
- public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
- int size,
- SocketFlags socket_flags,
- ref EndPoint remote_end,
- AsyncCallback callback,
- object state) {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ is_connected = true;
+ is_bound = true;
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ /* If sockaddr is null then we're a connection oriented protocol and should ignore the
+ * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
+ if (sockaddr != null) {
+ /* Stupidly, EndPoint.Create() is an instance method */
+ remote_end = remote_end.Create (sockaddr);
+ }
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
+ seed_endpoint = remote_end;
- CheckRange (buffer, offset, size);
+ return cnt;
+ }
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- req.EndPoint = remote_end;
- int count;
- lock (readQ) {
- readQ.Enqueue (req.Worker);
- count = readQ.Count;
+ static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
+ {
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
}
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
}
- [MonoTODO]
- public IAsyncResult BeginReceiveMessageFrom (
- byte[] buffer, int offset, int size,
- SocketFlags socketFlags, ref EndPoint remoteEP,
- AsyncCallback callback, object state)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+#endregion
+
+#region ReceiveMessageFrom
+
+ [MonoTODO ("Not implemented")]
+ public int ReceiveMessageFrom (byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
if (remoteEP == null)
throw new ArgumentNullException ("remoteEP");
- CheckRange (buffer, offset, size);
-
+ // FIXME: figure out how we get hold of the IPPacketInformation
throw new NotImplementedException ();
}
- public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
- AsyncCallback callback, object state)
+ [MonoTODO ("Not implemented")]
+ public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
-
- CheckRange (buffer, offset, size);
-
- if (!connected)
- throw new SocketException ((int)SocketError.NotConnected);
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- int count;
- lock (writeQ) {
- writeQ.Enqueue (req.Worker);
- count = writeQ.Count;
- }
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
- }
+ ThrowIfDisposedAndClosed ();
- public IAsyncResult BeginSend (byte[] buffer, int offset,
- int size,
- SocketFlags socketFlags,
- out SocketError errorCode,
- AsyncCallback callback,
- object state)
- {
- if (!connected) {
- errorCode = SocketError.NotConnected;
- throw new SocketException ((int)errorCode);
- }
-
- errorCode = SocketError.Success;
-
- return (BeginSend (buffer, offset, size, socketFlags, callback,
- state));
+ throw new NotImplementedException ();
}
- public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
- SocketFlags socketFlags,
- AsyncCallback callback,
- object state)
+ [MonoTODO]
+ public IAsyncResult BeginReceiveMessageFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffers == null)
- throw new ArgumentNullException ("buffers");
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- if (!connected)
- throw new SocketException ((int)SocketError.NotConnected);
+ if (remoteEP == null)
+ throw new ArgumentNullException ("remoteEP");
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
- req.Buffers = buffers;
- req.SockFlags = socketFlags;
- int count;
- lock (writeQ) {
- writeQ.Enqueue (req.Worker);
- count = writeQ.Count;
- }
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
+ throw new NotImplementedException ();
}
- [CLSCompliant (false)]
- public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
- SocketFlags socketFlags,
- out SocketError errorCode,
- AsyncCallback callback,
- object state)
+ [MonoTODO]
+ public int EndReceiveMessageFrom (IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
{
- if (!connected) {
- errorCode = SocketError.NotConnected;
- throw new SocketException ((int)errorCode);
- }
-
- errorCode = SocketError.Success;
- return (BeginSend (buffers, socketFlags, callback, state));
- }
+ ThrowIfDisposedAndClosed ();
- delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
+ if (endPoint == null)
+ throw new ArgumentNullException ("endPoint");
- sealed class SendFileAsyncResult : IAsyncResult {
- IAsyncResult ares;
- SendFileHandler d;
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
- public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
- {
- this.d = d;
- this.ares = ares;
- }
+ throw new NotImplementedException ();
+ }
- public object AsyncState {
- get { return ares.AsyncState; }
- }
+#endregion
- public WaitHandle AsyncWaitHandle {
- get { return ares.AsyncWaitHandle; }
- }
+#region Send
- public bool CompletedSynchronously {
- get { return ares.CompletedSynchronously; }
- }
+ public int Send (byte [] buffer)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
- public bool IsCompleted {
- get { return ares.IsCompleted; }
- }
+ SocketError error;
+ int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
- public SendFileHandler Delegate {
- get { return d; }
- }
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
- public IAsyncResult Original {
- get { return ares; }
- }
+ return ret;
}
- public IAsyncResult BeginSendFile (string fileName,
- AsyncCallback callback,
- object state)
+ public int Send (byte [] buffer, SocketFlags flags)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
- if (!connected)
- throw new NotSupportedException ();
+ SocketError error;
+ int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
- if (!File.Exists (fileName))
- throw new FileNotFoundException ();
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
- return BeginSendFile (fileName, null, null, 0, callback, state);
+ return ret;
}
- public IAsyncResult BeginSendFile (string fileName,
- byte[] preBuffer,
- byte[] postBuffer,
- TransmitFileOptions flags,
- AsyncCallback callback,
- object state)
+ public int Send (byte [] buffer, int size, SocketFlags flags)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, size);
- if (!connected)
- throw new NotSupportedException ();
+ SocketError error;
+ int ret = Send_nochecks (buffer, 0, size, flags, out error);
- if (!File.Exists (fileName))
- throw new FileNotFoundException ();
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
- SendFileHandler d = new SendFileHandler (SendFile);
- return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => {
- SendFileAsyncResult sfar = new SendFileAsyncResult (d, ar);
- callback (sfar);
- }, state));
+ return ret;
}
- public IAsyncResult BeginSendTo(byte[] buffer, int offset,
- int size,
- SocketFlags socket_flags,
- EndPoint remote_end,
- AsyncCallback callback,
- object state) {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ SocketError error;
+ int ret = Send_nochecks (buffer, offset, size, flags, out error);
- CheckRange (buffer, offset, size);
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- req.EndPoint = remote_end;
- int count;
- lock (writeQ) {
- writeQ.Enqueue (req.Worker);
- count = writeQ.Count;
- }
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
+ return ret;
}
- // Creates a new system socket, returning the handle
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void Bind_internal(IntPtr sock,
- SocketAddress sa,
- out int error);
-
- private static void Bind_internal (SafeSocketHandle safeHandle,
- SocketAddress sa,
- out int error)
+ public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
{
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- public void Bind(EndPoint local_end) {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- if (local_end == null)
- throw new ArgumentNullException("local_end");
-
- int error;
-
- Bind_internal(socket, local_end.Serialize(), out error);
- if (error != 0)
- throw new SocketException (error);
- if (error == 0)
- isbound = true;
-
- seed_endpoint = local_end;
+ return Send_nochecks (buffer, offset, size, flags, out error);
}
- public void Connect (IPAddress address, int port)
- {
- Connect (new IPEndPoint (address, port));
- }
-
- public void Connect (IPAddress[] addresses, int port)
+ public
+ int Send (IList<ArraySegment<byte>> buffers)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (addresses == null)
- throw new ArgumentNullException ("addresses");
-
- if (this.AddressFamily != AddressFamily.InterNetwork &&
- this.AddressFamily != AddressFamily.InterNetworkV6)
- throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
+ SocketError error;
+ int ret = Send (buffers, SocketFlags.None, out error);
- if (islistening)
- throw new InvalidOperationException ();
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
- /* FIXME: do non-blocking sockets Poll here? */
- int error = 0;
- foreach (IPAddress address in addresses) {
- IPEndPoint iep = new IPEndPoint (address, port);
- SocketAddress serial = iep.Serialize ();
-
- Connect_internal (socket, serial, out error);
- if (error == 0) {
- connected = true;
- isbound = true;
- seed_endpoint = iep;
- return;
- } else if (error != (int)SocketError.InProgress &&
- error != (int)SocketError.WouldBlock) {
- continue;
- }
-
- if (!blocking) {
- Poll (-1, SelectMode.SelectWrite);
- error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
- if (error == 0) {
- connected = true;
- isbound = true;
- seed_endpoint = iep;
- return;
- }
- }
- }
- if (error != 0)
- throw new SocketException (error);
+ return ret;
}
- public void Connect (string host, int port)
+ public
+ int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
{
- IPAddress [] addresses = Dns.GetHostAddresses (host);
- Connect (addresses, port);
+ SocketError error;
+ int ret = Send (buffers, socketFlags, out error);
+
+ if (error != SocketError.Success)
+ throw new SocketException ((int) error);
+
+ return ret;
}
- public bool DisconnectAsync (SocketAsyncEventArgs e)
+ [CLSCompliant (false)]
+ public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
{
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- e.curSocket = this;
- e.Worker.Init (this, e, SocketOperation.Disconnect);
- socket_pool_queue (Worker.Dispatcher, e.Worker.result);
- return true;
- }
+ if (buffers == null)
+ throw new ArgumentNullException ("buffers");
+ if (buffers.Count == 0)
+ throw new ArgumentException ("Buffer is empty", "buffers");
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
+ int numsegments = buffers.Count;
+ int nativeError;
+ int ret;
+
+ WSABUF[] bufarray = new WSABUF[numsegments];
+ GCHandle[] gch = new GCHandle[numsegments];
+
+ for(int i = 0; i < numsegments; i++) {
+ ArraySegment<byte> segment = buffers[i];
+
+ if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
+ throw new ArgumentOutOfRangeException ("segment");
+
+ gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
+ bufarray[i].len = segment.Count;
+ bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
+ }
- private static void Disconnect_internal(SafeSocketHandle safeHandle, bool reuse, out int error)
- {
- bool release = false;
try {
- safeHandle.DangerousAddRef (ref release);
- Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
+ ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
} finally {
- if (release)
- safeHandle.DangerousRelease ();
+ for(int i = 0; i < numsegments; i++) {
+ if (gch[i].IsAllocated) {
+ gch[i].Free ();
+ }
+ }
}
+
+ errorCode = (SocketError)nativeError;
+
+ return ret;
}
- /* According to the docs, the MS runtime will throw
- * PlatformNotSupportedException if the platform is
- * newer than w2k. We should be able to cope...
- */
- public void Disconnect (bool reuseSocket)
+ internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ if (size == 0) {
+ error = SocketError.Success;
+ return 0;
+ }
- int error = 0;
-
- Disconnect_internal (socket, reuseSocket, out error);
+ int nativeError;
+ int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
- if (error != 0) {
- if (error == 50) {
- /* ERROR_NOT_SUPPORTED */
- throw new PlatformNotSupportedException ();
- } else {
- throw new SocketException (error);
- }
- }
+ error = (SocketError)nativeError;
- connected = false;
-
- if (reuseSocket) {
- /* Do managed housekeeping here... */
+ if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
+ is_connected = false;
+ is_bound = false;
+ } else {
+ is_connected = true;
}
+
+ return ret;
}
-#if !MOBILE
- [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
- public SocketInformation DuplicateAndClose (int targetProcessId)
+ public bool SendAsync (SocketAsyncEventArgs e)
{
- var si = new SocketInformation ();
- si.Options =
- (islistening ? SocketInformationOptions.Listening : 0) |
- (connected ? SocketInformationOptions.Connected : 0) |
- (blocking ? 0 : SocketInformationOptions.NonBlocking) |
- (useoverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, isbound ? 1 : 0, (long)Handle);
- socket = null;
+ ThrowIfDisposedAndClosed ();
- return si;
- }
-#endif
-
- public Socket EndAccept (IAsyncResult result)
- {
- int bytes;
- byte[] buffer;
-
- return(EndAccept (out buffer, out bytes, result));
- }
+ if (e.Buffer == null && e.BufferList == null)
+ throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
- public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
- {
- int bytes;
- return(EndAccept (out buffer, out bytes, asyncResult));
- }
+ e.curSocket = this;
+ e.Worker.Init (this, e, e.Buffer != null ? SocketOperation.Send : SocketOperation.SendGeneric);
- public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ SocketAsyncResult sockares = e.Worker.result;
+ sockares.SockFlags = e.SocketFlags;
- if (asyncResult == null)
- throw new ArgumentNullException ("asyncResult");
-
- SocketAsyncResult req = asyncResult as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+ if (e.Buffer != null) {
+ sockares.Buffer = e.Buffer;
+ sockares.Offset = e.Offset;
+ sockares.Size = e.Count;
+ } else {
+ sockares.Buffers = e.BufferList;
+ }
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndAccept");
- if (!asyncResult.IsCompleted)
- asyncResult.AsyncWaitHandle.WaitOne ();
+ // Send takes care of SendGeneric
+ QueueSocketAsyncResult (writeQ, e.Worker, sockares);
- req.CheckIfThrowDelayedException ();
-
- buffer = req.Buffer;
- bytesTransferred = req.Total;
-
- return(req.Socket);
+ return true;
}
- public void EndConnect (IAsyncResult result)
+ public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (result == null)
- throw new ArgumentNullException ("result");
-
- SocketAsyncResult req = result as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "result");
-
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndConnect");
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne();
+ if (!is_connected) {
+ errorCode = SocketError.NotConnected;
+ throw new SocketException ((int) errorCode);
+ }
- req.CheckIfThrowDelayedException();
+ errorCode = SocketError.Success;
+ return BeginSend (buffer, offset, size, socketFlags, callback, state);
}
- public void EndDisconnect (IAsyncResult asyncResult)
+ public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- if (asyncResult == null)
- throw new ArgumentNullException ("asyncResult");
+ if (!is_connected)
+ throw new SocketException ((int)SocketError.NotConnected);
- SocketAsyncResult req = asyncResult as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Send) {
+ Buffer = buffer,
+ Offset = offset,
+ Size = size,
+ SockFlags = socket_flags,
+ };
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndDisconnect");
- if (!asyncResult.IsCompleted)
- asyncResult.AsyncWaitHandle.WaitOne ();
+ QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
- req.CheckIfThrowDelayedException ();
+ return sockares;
}
- [MonoTODO]
- public int EndReceiveMessageFrom (IAsyncResult asyncResult,
- ref SocketFlags socketFlags,
- ref EndPoint endPoint,
- out IPPacketInformation ipPacketInformation)
+ public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (asyncResult == null)
- throw new ArgumentNullException ("asyncResult");
+ if (buffers == null)
+ throw new ArgumentNullException ("buffers");
+ if (!is_connected)
+ throw new SocketException ((int)SocketError.NotConnected);
- if (endPoint == null)
- throw new ArgumentNullException ("endPoint");
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric) {
+ Buffers = buffers,
+ SockFlags = socketFlags,
+ };
- SocketAsyncResult req = asyncResult as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+ QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndReceiveMessageFrom");
- throw new NotImplementedException ();
+ return sockares;
}
- public void EndSendFile (IAsyncResult asyncResult)
+ [CLSCompliant (false)]
+ public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ if (!is_connected) {
+ errorCode = SocketError.NotConnected;
+ throw new SocketException ((int)errorCode);
+ }
- if (asyncResult == null)
- throw new ArgumentNullException ("asyncResult");
+ errorCode = SocketError.Success;
+ return BeginSend (buffers, socketFlags, callback, state);
+ }
- SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
- if (ares == null)
- throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
+ public int EndSend (IAsyncResult result)
+ {
+ SocketError error;
+ int bytesSent = EndSend (result, out error);
- ares.Delegate.EndInvoke (ares.Original);
+ if (error != SocketError.Success) {
+ if (error != SocketError.WouldBlock && error != SocketError.InProgress)
+ is_connected = false;
+ throw new SocketException ((int)error);
+ }
+
+ return bytesSent;
}
- public int EndSendTo (IAsyncResult result)
+ public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (result == null)
- throw new ArgumentNullException ("result");
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSend", "asyncResult");
- SocketAsyncResult req = result as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "result");
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne ();
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndSendTo");
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne();
+ /* If no socket error occurred, call CheckIfThrowDelayedException in
+ * case there are other kinds of exceptions that should be thrown.*/
+ if ((errorCode = sockares.ErrorCode) == SocketError.Success)
+ sockares.CheckIfThrowDelayedException ();
- req.CheckIfThrowDelayedException();
- return req.Total;
+ return sockares.Total;
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void GetSocketOption_arr_internal(IntPtr socket,
- SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
- out int error);
-
- private static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle,
- SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
- out int error)
+ static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
{
bool release = false;
try {
safeHandle.DangerousAddRef (ref release);
- GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
+ return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
} finally {
if (release)
safeHandle.DangerousRelease ();
}
}
- public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
+
+ static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
+ }
+ }
- if (optionValue == null)
- throw new SocketException ((int) SocketError.Fault,
- "Error trying to dereference an invalid pointer");
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
- int error;
+#endregion
- GetSocketOption_arr_internal (socket, optionLevel, optionName, ref optionValue,
- out error);
- if (error != 0)
- throw new SocketException (error);
- }
+#region SendTo
- public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
+ public int SendTo (byte [] buffer, EndPoint remote_end)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- byte[] byte_val=new byte[length];
- int error;
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
- GetSocketOption_arr_internal (socket, optionLevel, optionName, ref byte_val,
- out error);
- if (error != 0)
- throw new SocketException (error);
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
- return(byte_val);
+ return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
}
- // See Socket.IOControl, WSAIoctl documentation in MSDN. The
- // common options between UNIX and Winsock are FIONREAD,
- // FIONBIO and SIOCATMARK. Anything else will depend on the
- // system except SIO_KEEPALIVE_VALS which is properly handled
- // on both windows and linux.
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
- byte [] output, out int error);
-
- private static int WSAIoctl (SafeSocketHandle safeHandle, int ioctl_code, byte [] input,
- byte [] output, out int error)
+ public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
{
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- return WSAIoctl (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
+
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
+
+ return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
}
- public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
+ public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
{
- if (disposed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- int error;
- int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
- out error);
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, 0, size);
- if (error != 0)
- throw new SocketException (error);
-
- if (result == -1)
- throw new InvalidOperationException ("Must use Blocking property instead.");
+ if (remote_end == null)
+ throw new ArgumentNullException ("remote_end");
- return result;
+ return SendTo_nochecks (buffer, 0, size, flags, remote_end);
}
- public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
+ public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
{
- return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
- }
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void Listen_internal(IntPtr sock, int backlog, out int error);
+ if (remote_end == null)
+ throw new ArgumentNullException("remote_end");
- private static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
+ return SendTo_nochecks (buffer, offset, size, flags, remote_end);
}
- public void Listen (int backlog)
+ internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (!isbound)
- throw new SocketException ((int)SocketError.InvalidArgument);
-
int error;
- Listen_internal(socket, backlog, out error);
+ int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
- if (error != 0)
+ SocketError err = (SocketError) error;
+ if (err != 0) {
+ if (err != SocketError.WouldBlock && err != SocketError.InProgress)
+ is_connected = false;
throw new SocketException (error);
+ }
+
+ is_connected = true;
+ is_bound = true;
+ seed_endpoint = remote_end;
- islistening = true;
+ return ret;
}
- public bool Poll (int time_us, SelectMode mode)
+ public bool SendToAsync (SocketAsyncEventArgs e)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- if (mode != SelectMode.SelectRead &&
- mode != SelectMode.SelectWrite &&
- mode != SelectMode.SelectError)
- throw new NotSupportedException ("'mode' parameter is not valid.");
+ ThrowIfDisposedAndClosed ();
- int error;
- bool result = Poll_internal (socket, mode, time_us, out error);
- if (error != 0)
- throw new SocketException (error);
+ if (e.BufferList != null)
+ throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
+ if (e.RemoteEndPoint == null)
+ throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
- if (mode == SelectMode.SelectWrite && result && !connected) {
- /* Update the connected state; for
- * non-blocking Connect()s this is
- * when we can find out that the
- * connect succeeded.
- */
- if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
- connected = true;
- }
- }
-
- return result;
- }
+ e.curSocket = this;
+ e.Worker.Init (this, e, SocketOperation.SendTo);
- public int Receive (byte [] buffer)
- {
- return Receive (buffer, SocketFlags.None);
+ SocketAsyncResult sockares = e.Worker.result;
+ sockares.Buffer = e.Buffer;
+ sockares.Offset = e.Offset;
+ sockares.Size = e.Count;
+ sockares.SockFlags = e.SocketFlags;
+ sockares.EndPoint = e.RemoteEndPoint;
+
+ QueueSocketAsyncResult (writeQ, e.Worker, sockares);
+
+ return true;
}
- public int Receive (byte [] buffer, SocketFlags flags)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
+ {
+ ThrowIfDisposedAndClosed ();
+ ThrowIfBufferNull (buffer);
+ ThrowIfBufferOutOfRange (buffer, offset, size);
- SocketError error;
+ SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo) {
+ Buffer = buffer,
+ Offset = offset,
+ Size = size,
+ SockFlags = socket_flags,
+ EndPoint = remote_end,
+ };
- int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
-
- if (error != SocketError.Success) {
- if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
- throw new SocketException ((int) error, timeout_exc_msg);
- throw new SocketException ((int) error);
- }
+ QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
- return ret;
+ return sockares;
}
- public int Receive (byte [] buffer, int size, SocketFlags flags)
+ public int EndSendTo (IAsyncResult result)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
- CheckRange (buffer, 0, size);
-
- SocketError error;
+ if (!sockares.IsCompleted)
+ sockares.AsyncWaitHandle.WaitOne();
- int ret = Receive_nochecks (buffer, 0, size, flags, out error);
-
- if (error != SocketError.Success) {
- if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
- throw new SocketException ((int) error, timeout_exc_msg);
- throw new SocketException ((int) error);
- }
+ sockares.CheckIfThrowDelayedException();
- return ret;
+ return sockares.Total;
}
- public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
+ static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ try {
+ safeHandle.RegisterForBlockingSyscall ();
+ return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
+ } finally {
+ safeHandle.UnRegisterForBlockingSyscall ();
+ }
+ }
- CheckRange (buffer, offset, size);
-
- SocketError error;
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
- int ret = Receive_nochecks (buffer, offset, size, flags, out error);
-
- if (error != SocketError.Success) {
- if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
- throw new SocketException ((int) error, timeout_exc_msg);
- throw new SocketException ((int) error);
- }
+#endregion
- return ret;
- }
+#region SendFile
- public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
+ public void SendFile (string fileName)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ if (!is_connected)
+ throw new NotSupportedException ();
+ if (!is_blocking)
+ throw new InvalidOperationException ();
- CheckRange (buffer, offset, size);
-
- return Receive_nochecks (buffer, offset, size, flags, out error);
+ SendFile (fileName, null, null, 0);
}
- public bool ReceiveFromAsync (SocketAsyncEventArgs e)
+ public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- // We do not support recv into multiple buffers yet
- if (e.BufferList != null)
- throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
- if (e.RemoteEndPoint == null)
- throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
+ if (!is_connected)
+ throw new NotSupportedException ();
+ if (!is_blocking)
+ throw new InvalidOperationException ();
- e.curSocket = this;
- e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
- SocketAsyncResult res = e.Worker.result;
- res.Buffer = e.Buffer;
- res.Offset = e.Offset;
- res.Size = e.Count;
- res.EndPoint = e.RemoteEndPoint;
- res.SockFlags = e.SocketFlags;
- int count;
- lock (readQ) {
- readQ.Enqueue (e.Worker);
- count = readQ.Count;
+ if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
+ SocketException exc = new SocketException ();
+ if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
+ throw new FileNotFoundException ();
+ throw exc;
}
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, res);
- return true;
}
- public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
+ public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ ThrowIfDisposedAndClosed ();
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
+ if (!is_connected)
+ throw new NotSupportedException ();
+ if (!File.Exists (fileName))
+ throw new FileNotFoundException ();
- return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
+ return BeginSendFile (fileName, null, null, 0, callback, state);
}
- public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
+ public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ if (!is_connected)
+ throw new NotSupportedException ();
+ if (!File.Exists (fileName))
+ throw new FileNotFoundException ();
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
+ SendFileHandler handler = new SendFileHandler (SendFile);
- return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
+ return new SendFileAsyncResult (handler, handler.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => callback (new SendFileAsyncResult (handler, ar)), state));
}
- public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
- ref EndPoint remoteEP)
+ public void EndSendFile (IAsyncResult asyncResult)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ ThrowIfDisposedAndClosed ();
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
+ if (asyncResult == null)
+ throw new ArgumentNullException ("asyncResult");
- if (size < 0 || size > buffer.Length)
- throw new ArgumentOutOfRangeException ("size");
+ SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
+ if (ares == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
- return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
+ ares.Delegate.EndInvoke (ares.Original);
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static int RecvFrom_internal(IntPtr sock,
- byte[] buffer,
- int offset,
- int count,
- SocketFlags flags,
- ref SocketAddress sockaddr,
- out int error);
-
- private static int RecvFrom_internal (SafeSocketHandle safeHandle,
- byte[] buffer,
- int offset,
- int count,
- SocketFlags flags,
- ref SocketAddress sockaddr,
- out int error)
+ static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
{
try {
safeHandle.RegisterForBlockingSyscall ();
- return RecvFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
+ return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}
- public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
- ref EndPoint remoteEP)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
+ sealed class SendFileAsyncResult : IAsyncResult {
+ IAsyncResult ares;
+ SendFileHandler d;
- CheckRange (buffer, offset, size);
+ public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
+ {
+ this.d = d;
+ this.ares = ares;
+ }
- return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
- }
+ public object AsyncState {
+ get { return ares.AsyncState; }
+ }
- internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
- ref EndPoint remote_end)
- {
- int error;
- return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
- }
+ public WaitHandle AsyncWaitHandle {
+ get { return ares.AsyncWaitHandle; }
+ }
- internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
- ref EndPoint remote_end, bool throwOnError, out int error)
- {
- SocketAddress sockaddr = remote_end.Serialize();
- int cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
- SocketError err = (SocketError) error;
- if (err != 0) {
- if (err != SocketError.WouldBlock && err != SocketError.InProgress)
- connected = false;
- else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
- if (throwOnError)
- throw new SocketException ((int) SocketError.TimedOut, timeout_exc_msg);
- error = (int) SocketError.TimedOut;
- return 0;
- }
+ public bool CompletedSynchronously {
+ get { return ares.CompletedSynchronously; }
+ }
- if (throwOnError)
- throw new SocketException (error);
- return 0;
+ public bool IsCompleted {
+ get { return ares.IsCompleted; }
}
- connected = true;
- isbound = true;
+ public SendFileHandler Delegate {
+ get { return d; }
+ }
- // If sockaddr is null then we're a connection
- // oriented protocol and should ignore the
- // remote_end parameter (see MSDN
- // documentation for Socket.ReceiveFrom(...) )
-
- if ( sockaddr != null ) {
- // Stupidly, EndPoint.Create() is an
- // instance method
- remote_end = remote_end.Create (sockaddr);
+ public IAsyncResult Original {
+ get { return ares; }
}
-
- seed_endpoint = remote_end;
-
- return cnt;
}
+#endregion
+
+#region SendPackets
+
[MonoTODO ("Not implemented")]
- public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
+ public bool SendPacketsAsync (SocketAsyncEventArgs e)
{
// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
+
+ ThrowIfDisposedAndClosed ();
+
throw new NotImplementedException ();
}
-
- [MonoTODO ("Not implemented")]
- public int ReceiveMessageFrom (byte[] buffer, int offset,
- int size,
- ref SocketFlags socketFlags,
- ref EndPoint remoteEP,
- out IPPacketInformation ipPacketInformation)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+#endregion
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
+#region DuplicateAndClose
+
+#if !MOBILE
+ [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
+ public SocketInformation DuplicateAndClose (int targetProcessId)
+ {
+ var si = new SocketInformation ();
+ si.Options =
+ (is_listening ? SocketInformationOptions.Listening : 0) |
+ (is_connected ? SocketInformationOptions.Connected : 0) |
+ (is_blocking ? 0 : SocketInformationOptions.NonBlocking) |
+ (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
- CheckRange (buffer, offset, size);
+ si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
+ safe_handle = null;
- /* FIXME: figure out how we get hold of the
- * IPPacketInformation
- */
- throw new NotImplementedException ();
+ return si;
}
+#endif
- [MonoTODO ("Not implemented")]
- public bool SendPacketsAsync (SocketAsyncEventArgs e)
+#endregion
+
+#region GetSocketOption
+
+ public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
{
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
-
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- throw new NotImplementedException ();
+ ThrowIfDisposedAndClosed ();
+
+ if (optionValue == null)
+ throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
+
+ int error;
+ GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
+
+ if (error != 0)
+ throw new SocketException (error);
}
- public int Send (byte [] buf)
+ public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ ThrowIfDisposedAndClosed ();
+
+ int error;
+ byte[] byte_val = new byte [length];
+ GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
- if (buf == null)
- throw new ArgumentNullException ("buf");
+ if (error != 0)
+ throw new SocketException (error);
- SocketError error;
+ return byte_val;
+ }
- int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
+ public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
+ {
+ ThrowIfDisposedAndClosed ();
- if (error != SocketError.Success)
- throw new SocketException ((int) error);
+ int error;
+ object obj_val;
+ GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
- return ret;
+ if (error != 0)
+ throw new SocketException (error);
+
+ if (optionName == SocketOptionName.Linger)
+ return (LingerOption) obj_val;
+ else if (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)
+ return (MulticastOption) obj_val;
+ else if (obj_val is int)
+ return (int) obj_val;
+ else
+ return obj_val;
}
- public int Send (byte [] buf, SocketFlags flags)
+ static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
- if (buf == null)
- throw new ArgumentNullException ("buf");
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
- SocketError error;
+ static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
+ }
+ }
- int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
- if (error != SocketError.Success)
- throw new SocketException ((int) error);
+#endregion
- return ret;
+#region SetSocketOption
+
+ public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
+ {
+ ThrowIfDisposedAndClosed ();
+
+ // I'd throw an ArgumentNullException, but this is what MS does.
+ if (optionValue == null)
+ throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
+
+ int error;
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
+
+ if (error != 0) {
+ if (error == (int) SocketError.InvalidArgument)
+ throw new ArgumentException ();
+ throw new SocketException (error);
+ }
}
- public int Send (byte [] buf, int size, SocketFlags flags)
+ public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buf == null)
- throw new ArgumentNullException ("buf");
-
- CheckRange (buf, 0, size);
+ ThrowIfDisposedAndClosed ();
- SocketError error;
+ // NOTE: if a null is passed, the byte[] overload is used instead...
+ if (optionValue == null)
+ throw new ArgumentNullException("optionValue");
- int ret = Send_nochecks (buf, 0, size, flags, out error);
+ int error;
- if (error != SocketError.Success)
- throw new SocketException ((int) error);
+ if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
+ LingerOption linger = optionValue as LingerOption;
+ if (linger == null)
+ throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
+ } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
+ MulticastOption multicast = optionValue as MulticastOption;
+ if (multicast == null)
+ throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
+ } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
+ IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
+ if (multicast == null)
+ throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
+ } else {
+ throw new ArgumentException ("Invalid value specified.", "optionValue");
+ }
- return ret;
+ if (error != 0) {
+ if (error == (int) SocketError.InvalidArgument)
+ throw new ArgumentException ();
+ throw new SocketException (error);
+ }
}
- public int Send (byte [] buf, int offset, int size, SocketFlags flags)
+ public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buf == null)
- throw new ArgumentNullException ("buffer");
-
- CheckRange (buf, offset, size);
-
- SocketError error;
-
- int ret = Send_nochecks (buf, offset, size, flags, out error);
+ ThrowIfDisposedAndClosed ();
- if (error != SocketError.Success)
- throw new SocketException ((int) error);
+ int error;
+ int int_val = optionValue ? 1 : 0;
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
- return ret;
+ if (error != 0) {
+ if (error == (int) SocketError.InvalidArgument)
+ throw new ArgumentException ();
+ throw new SocketException (error);
+ }
}
- public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+ public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buf == null)
- throw new ArgumentNullException ("buffer");
+ ThrowIfDisposedAndClosed ();
- CheckRange (buf, offset, size);
+ int error;
+ SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
- return Send_nochecks (buf, offset, size, flags, out error);
+ if (error != 0) {
+ throw new SocketException (error);
+ }
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
-
- private static bool SendFile (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
+ static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error)
{
+ bool release = false;
try {
- safeHandle.RegisterForBlockingSyscall ();
- return SendFile (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
+ safeHandle.DangerousAddRef (ref release);
+ SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
} finally {
- safeHandle.UnRegisterForBlockingSyscall ();
+ if (release)
+ safeHandle.DangerousRelease ();
}
}
- public void SendFile (string fileName)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (!connected)
- throw new NotSupportedException ();
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error);
- if (!blocking)
- throw new InvalidOperationException ();
+#endregion
- SendFile (fileName, null, null, 0);
- }
+#region IOControl
- public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
+ public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
{
- if (disposed && closed)
+ if (is_disposed)
throw new ObjectDisposedException (GetType ().ToString ());
- if (!connected)
- throw new NotSupportedException ();
+ int error;
+ int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
- if (!blocking)
- throw new InvalidOperationException ();
+ if (error != 0)
+ throw new SocketException (error);
+ if (result == -1)
+ throw new InvalidOperationException ("Must use Blocking property instead.");
- if (!SendFile (socket, fileName, preBuffer, postBuffer, flags)) {
- SocketException exc = new SocketException ();
- if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
- throw new FileNotFoundException ();
- throw exc;
- }
+ return result;
}
- public bool SendToAsync (SocketAsyncEventArgs e)
+ public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
{
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
-
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (e.BufferList != null)
- throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
- if (e.RemoteEndPoint == null)
- throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
+ return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
+ }
- e.curSocket = this;
- e.Worker.Init (this, e, SocketOperation.SendTo);
- SocketAsyncResult res = e.Worker.result;
- res.Buffer = e.Buffer;
- res.Offset = e.Offset;
- res.Size = e.Count;
- res.SockFlags = e.SocketFlags;
- res.EndPoint = e.RemoteEndPoint;
- int count;
- lock (writeQ) {
- writeQ.Enqueue (e.Worker);
- count = writeQ.Count;
+ static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
+ {
+ bool release = false;
+ try {
+ safeHandle.DangerousAddRef (ref release);
+ return IOControl_internal (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
+ } finally {
+ if (release)
+ safeHandle.DangerousRelease ();
}
- if (count == 1)
- socket_pool_queue (Worker.Dispatcher, res);
- return true;
}
-
- public int SendTo (byte [] buffer, EndPoint remote_end)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ /* See Socket.IOControl, WSAIoctl documentation in MSDN. The common options between UNIX
+ * and Winsock are FIONREAD, FIONBIO and SIOCATMARK. Anything else will depend on the system
+ * except SIO_KEEPALIVE_VALS which is properly handled on both windows and linux. */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static int IOControl_internal (IntPtr sock, int ioctl_code, byte [] input, byte [] output, out int error);
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
+#endregion
- return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
+#region Close
+
+ public void Close ()
+ {
+ linger_timeout = 0;
+ Dispose ();
}
- public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
+ public void Close (int timeout)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ linger_timeout = timeout;
+ Dispose ();
+ }
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static void Close_internal (IntPtr socket, out int error);
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
-
- return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
- }
+#endregion
- public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+#region Shutdown
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
+ public void Shutdown (SocketShutdown how)
+ {
+ ThrowIfDisposedAndClosed ();
- if (remote_end == null)
- throw new ArgumentNullException ("remote_end");
+ if (!is_connected)
+ throw new SocketException (10057); // Not connected
- CheckRange (buffer, 0, size);
+ int error;
+ Shutdown_internal (safe_handle, how, out error);
- return SendTo_nochecks (buffer, 0, size, flags, remote_end);
+ if (error != 0)
+ throw new SocketException (error);
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static int SendTo_internal(IntPtr sock,
- byte[] buffer,
- int offset,
- int count,
- SocketFlags flags,
- SocketAddress sa,
- out int error);
-
- private static int SendTo_internal (SafeSocketHandle safeHandle,
- byte[] buffer,
- int offset,
- int count,
- SocketFlags flags,
- SocketAddress sa,
- out int error)
+ static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
{
+ bool release = false;
try {
- safeHandle.RegisterForBlockingSyscall ();
- return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
+ safeHandle.DangerousAddRef (ref release);
+ Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
} finally {
- safeHandle.UnRegisterForBlockingSyscall ();
+ if (release)
+ safeHandle.DangerousRelease ();
}
}
- public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
- EndPoint remote_end)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
-
- if (remote_end == null)
- throw new ArgumentNullException("remote_end");
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
- CheckRange (buffer, offset, size);
+#endregion
- return SendTo_nochecks (buffer, offset, size, flags, remote_end);
- }
+#region Dispose
- internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
- EndPoint remote_end)
+ protected virtual void Dispose (bool disposing)
{
- SocketAddress sockaddr = remote_end.Serialize ();
+ if (is_disposed)
+ return;
- int ret, error;
+ is_disposed = true;
+ bool was_connected = is_connected;
+ is_connected = false;
- ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
+ if (safe_handle != null) {
+ is_closed = true;
+ IntPtr x = Handle;
- SocketError err = (SocketError) error;
- if (err != 0) {
- if (err != SocketError.WouldBlock && err != SocketError.InProgress)
- connected = false;
+ if (was_connected)
+ Linger (x);
- throw new SocketException (error);
+ safe_handle.Dispose ();
}
+ }
- connected = true;
- isbound = true;
- seed_endpoint = remote_end;
-
- return ret;
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
}
- public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
+ void Linger (IntPtr handle)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ if (!is_connected || linger_timeout <= 0)
+ return;
- // I'd throw an ArgumentNullException, but this is what MS does.
- if (optionValue == null)
- throw new SocketException ((int) SocketError.Fault,
- "Error trying to dereference an invalid pointer");
-
+ /* We don't want to receive any more data */
int error;
+ Shutdown_internal (handle, SocketShutdown.Receive, out error);
- SetSocketOption_internal (socket, optionLevel, optionName, null,
- optionValue, 0, out error);
+ if (error != 0)
+ return;
- if (error != 0) {
- if (error == (int) SocketError.InvalidArgument)
- throw new ArgumentException ();
- throw new SocketException (error);
+ int seconds = linger_timeout / 1000;
+ int ms = linger_timeout % 1000;
+ if (ms > 0) {
+ /* If the other end closes, this will return 'true' with 'Available' == 0 */
+ Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
+ if (error != 0)
+ return;
+ }
+
+ if (seconds > 0) {
+ LingerOption linger = new LingerOption (true, seconds);
+ SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
+ /* Not needed, we're closing upon return */
+ //if (error != 0)
+ // return;
}
}
- public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
+#endregion
+
+ void ThrowIfDisposedAndClosed (Socket socket)
+ {
+ if (socket.is_disposed && socket.is_closed)
+ throw new ObjectDisposedException (socket.GetType ().ToString ());
+ }
+
+ void ThrowIfDisposedAndClosed ()
{
- if (disposed && closed)
+ if (is_disposed && is_closed)
throw new ObjectDisposedException (GetType ().ToString ());
+ }
- // NOTE: if a null is passed, the byte[] overload is used instead...
- if (optionValue == null)
- throw new ArgumentNullException("optionValue");
-
- int error;
+ void ThrowIfBufferNull (byte[] buffer)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+ }
- if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
- LingerOption linger = optionValue as LingerOption;
- if (linger == null)
- throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
- SetSocketOption_internal (socket, optionLevel, optionName, linger, null, 0, out error);
- } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
- MulticastOption multicast = optionValue as MulticastOption;
- if (multicast == null)
- throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
- SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
- } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
- IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
- if (multicast == null)
- throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
- SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
- } else {
- throw new ArgumentException ("Invalid value specified.", "optionValue");
- }
+ void ThrowIfBufferOutOfRange (byte[] buffer, int offset, int size)
+ {
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
+ if (offset > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
+ if (size < 0)
+ throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
+ if (size > buffer.Length - offset)
+ throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
+ }
- if (error != 0) {
- if (error == (int) SocketError.InvalidArgument)
- throw new ArgumentException ();
- throw new SocketException (error);
- }
+ void ThrowIfUdp ()
+ {
+#if !NET_2_1 || MOBILE
+ if (protocol_type == ProtocolType.Udp)
+ throw new SocketException ((int)SocketError.ProtocolOption);
+#endif
}
- public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
+ SocketAsyncResult ValidateEndIAsyncResult (IAsyncResult ares, string methodName, string argName)
{
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
+ if (ares == null)
+ throw new ArgumentNullException (argName);
- int error;
- int int_val = (optionValue) ? 1 : 0;
- SetSocketOption_internal (socket, optionLevel, optionName, null, null, int_val, out error);
- if (error != 0) {
- if (error == (int) SocketError.InvalidArgument)
- throw new ArgumentException ();
- throw new SocketException (error);
+ SocketAsyncResult sockares = ares as SocketAsyncResult;
+ if (sockares == null)
+ throw new ArgumentException ("Invalid IAsyncResult", argName);
+ if (Interlocked.CompareExchange (ref sockares.EndCalled, 1, 0) == 1)
+ throw new InvalidOperationException (methodName + " can only be called once per asynchronous operation");
+
+ return sockares;
+ }
+
+ void QueueSocketAsyncResult (Queue<SocketAsyncWorker> queue, SocketAsyncWorker worker, SocketAsyncResult sockares)
+ {
+ int count;
+ lock (queue) {
+ queue.Enqueue (worker);
+ count = queue.Count;
}
+
+ if (count == 1)
+ socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct WSABUF {
+ public int len;
+ public IntPtr buf;
}
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void cancel_blocking_socket_operation (Thread thread);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void socket_pool_queue (SocketAsyncCallback d, SocketAsyncResult r);
}
}
--- /dev/null
+// System.Net.Sockets.SocketAsyncCallback.cs
+//
+// Authors:
+// Ludovic Henry <ludovic@xamarin.com>
+//
+// Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
+//
+//
+// 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.
+//
+
+namespace System.Net.Sockets
+{
+ internal delegate void SocketAsyncCallback (SocketAsyncResult sar);
+}
{
bool disposed;
int in_progress;
- internal Socket.Worker Worker;
+ internal SocketAsyncWorker Worker;
EndPoint remote_ep;
public Exception ConnectByNameError { get; internal set; }
public SocketAsyncEventArgs ()
{
- Worker = new Socket.Worker (this);
+ Worker = new SocketAsyncWorker (this);
AcceptSocket = null;
Buffer = null;
BufferList = null;
static void DispatcherCB (IAsyncResult ares)
{
SocketAsyncEventArgs args = (SocketAsyncEventArgs) ares.AsyncState;
+
if (Interlocked.Exchange (ref args.in_progress, 0) != 1)
throw new InvalidOperationException ("No operation in progress");
- SocketAsyncOperation op = args.LastOperation;
- // Notes;
- // -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
- // -SendPackets and ReceiveMessageFrom are not implemented yet
- if (op == SocketAsyncOperation.Receive)
+
+ /* Notes;
+ * -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
+ * -SendPackets and ReceiveMessageFrom are not implemented yet */
+ switch (args.LastOperation) {
+ case SocketAsyncOperation.Receive:
args.ReceiveCallback (ares);
- else if (op == SocketAsyncOperation.Send)
+ break;
+ case SocketAsyncOperation.Send:
args.SendCallback (ares);
- else if (op == SocketAsyncOperation.ReceiveFrom)
+ break;
+ case SocketAsyncOperation.ReceiveFrom:
args.ReceiveFromCallback (ares);
- else if (op == SocketAsyncOperation.SendTo)
+ break;
+ case SocketAsyncOperation.SendTo:
args.SendToCallback (ares);
- else if (op == SocketAsyncOperation.Accept)
+ break;
+ case SocketAsyncOperation.Accept:
args.AcceptCallback (ares);
- else if (op == SocketAsyncOperation.Disconnect)
+ break;
+ case SocketAsyncOperation.Disconnect:
args.DisconnectCallback (ares);
- else if (op == SocketAsyncOperation.Connect)
+ break;
+ case SocketAsyncOperation.Connect:
args.ConnectCallback (ares);
+ break;
/*
- else if (op == Socket.SocketOperation.ReceiveMessageFrom)
- else if (op == Socket.SocketOperation.SendPackets)
+ case SocketOperation.ReceiveMessageFrom:
+ case SocketOperation.SendPackets:
*/
- else
- throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
-
+ default:
+ throw new NotImplementedException (String.Format ("Operation {0} is not implemented", args.LastOperation));
+ }
}
internal void ReceiveCallback (IAsyncResult ares)
--- /dev/null
+// System.Net.Sockets.SocketAsyncResult.cs
+//
+// Authors:
+// Ludovic Henry <ludovic@xamarin.com>
+//
+// Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
+//
+//
+// 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.
+//
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting.Messaging;
+using System.Threading;
+
+namespace System.Net.Sockets
+{
+ [StructLayout (LayoutKind.Sequential)]
+ internal sealed class SocketAsyncResult: IAsyncResult
+ {
+ /* Same structure in the runtime. Keep this in sync with
+ * MonoSocketAsyncResult in metadata/socket-io.h and
+ * ProcessAsyncReader in System.Diagnostics/Process.cs. */
+
+ public Socket socket;
+ IntPtr handle;
+ object state;
+ AsyncCallback callback; // used from the runtime
+ WaitHandle wait_handle;
+
+ Exception delayed_exception;
+
+ public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
+ public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
+ public int Offset; // Receive,ReceiveFrom,Send,SendTo
+ public int Size; // Receive,ReceiveFrom,Send,SendTo
+ public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
+ public Socket AcceptSocket; // AcceptReceive
+ public IPAddress[] Addresses; // Connect
+ public int Port; // Connect
+ public IList<ArraySegment<byte>> Buffers; // Receive, Send
+ public bool ReuseSocket; // Disconnect
+
+ // Return values
+ Socket accept_socket;
+ int total;
+
+ bool completed_synchronously;
+ bool completed;
+ bool is_blocking;
+ internal int error;
+ public SocketOperation operation;
+ AsyncResult async_result;
+ public int EndCalled;
+
+ /* These fields are not in MonoSocketAsyncResult */
+ public SocketAsyncWorker Worker;
+ public int CurrentAddress; // Connect
+
+ public SocketAsyncResult ()
+ {
+ }
+
+ public SocketAsyncResult (Socket socket, object state, AsyncCallback callback, SocketOperation operation)
+ {
+ Init (socket, state, callback, operation, new SocketAsyncWorker (this));
+ }
+
+ public object AsyncState {
+ get {
+ return state;
+ }
+ }
+
+ public WaitHandle AsyncWaitHandle {
+ get {
+ lock (this) {
+ if (wait_handle == null)
+ wait_handle = new ManualResetEvent (completed);
+ }
+
+ return wait_handle;
+ }
+ set {
+ wait_handle = value;
+ }
+ }
+
+ public bool CompletedSynchronously {
+ get {
+ return completed_synchronously;
+ }
+ }
+
+ public bool IsCompleted {
+ get {
+ return completed;
+ }
+ set {
+ completed = value;
+ lock (this) {
+ if (wait_handle != null && value)
+ ((ManualResetEvent) wait_handle).Set ();
+ }
+ }
+ }
+
+ public Socket Socket {
+ get {
+ return accept_socket;
+ }
+ }
+
+ public int Total {
+ get { return total; }
+ set { total = value; }
+ }
+
+ public SocketError ErrorCode {
+ get {
+ SocketException ex = delayed_exception as SocketException;
+ if (ex != null)
+ return ex.SocketErrorCode;
+
+ if (error != 0)
+ return (SocketError) error;
+
+ return SocketError.Success;
+ }
+ }
+
+ public void Init (Socket socket, object state, AsyncCallback callback, SocketOperation operation, SocketAsyncWorker worker)
+ {
+ this.socket = socket;
+ this.is_blocking = socket != null ? socket.is_blocking : true;
+ this.handle = socket != null ? socket.Handle : IntPtr.Zero;
+ this.state = state;
+ this.callback = callback;
+ this.operation = operation;
+
+ if (wait_handle != null)
+ ((ManualResetEvent) wait_handle).Reset ();
+
+ delayed_exception = null;
+
+ EndPoint = null;
+ Buffer = null;
+ Offset = 0;
+ Size = 0;
+ SockFlags = SocketFlags.None;
+ AcceptSocket = null;
+ Addresses = null;
+ Port = 0;
+ Buffers = null;
+ ReuseSocket = false;
+ accept_socket = null;
+ total = 0;
+
+ completed_synchronously = false;
+ completed = false;
+ is_blocking = false;
+ error = 0;
+ async_result = null;
+ EndCalled = 0;
+ Worker = worker;
+ }
+
+ public void DoMConnectCallback ()
+ {
+ if (callback == null)
+ return;
+ ThreadPool.UnsafeQueueUserWorkItem (_ => callback (this), null);
+ }
+
+ public void Dispose ()
+ {
+ Init (null, null, null, 0, Worker);
+ if (wait_handle != null) {
+ wait_handle.Close ();
+ wait_handle = null;
+ }
+ }
+
+ public void CheckIfThrowDelayedException ()
+ {
+ if (delayed_exception != null) {
+ socket.is_connected = false;
+ throw delayed_exception;
+ }
+
+ if (error != 0) {
+ socket.is_connected = false;
+ throw new SocketException (error);
+ }
+ }
+
+ void CompleteDisposed (object unused)
+ {
+ Complete ();
+ }
+
+ public void Complete ()
+ {
+ if (operation != SocketOperation.Receive && socket.is_disposed)
+ delayed_exception = new ObjectDisposedException (socket.GetType ().ToString ());
+
+ IsCompleted = true;
+
+ Queue<SocketAsyncWorker> queue = null;
+ switch (operation) {
+ case SocketOperation.Receive:
+ case SocketOperation.ReceiveFrom:
+ case SocketOperation.ReceiveGeneric:
+ case SocketOperation.Accept:
+ queue = socket.readQ;
+ break;
+ case SocketOperation.Send:
+ case SocketOperation.SendTo:
+ case SocketOperation.SendGeneric:
+ queue = socket.writeQ;
+ break;
+ }
+
+ if (queue != null) {
+ lock (queue) {
+ /* queue.Count will only be 0 if the socket is closed while receive/send/accept
+ * operation(s) are pending and at least one call to this method is waiting
+ * on the lock while another one calls CompleteAllOnDispose() */
+ if (queue.Count > 0)
+ queue.Dequeue (); /* remove ourselves */
+ if (queue.Count > 0) {
+ if (!socket.is_disposed) {
+ Socket.socket_pool_queue (SocketAsyncWorker.Dispatcher, (queue.Peek ()).result);
+ } else {
+ /* CompleteAllOnDispose */
+ SocketAsyncWorker [] workers = queue.ToArray ();
+ for (int i = 0; i < workers.Length; i++)
+ ThreadPool.UnsafeQueueUserWorkItem (workers [i].result.CompleteDisposed, null);
+ queue.Clear ();
+ }
+ }
+ }
+ }
+
+ // IMPORTANT: 'callback', if any is scheduled from unmanaged code
+ }
+
+ public void Complete (bool synch)
+ {
+ this.completed_synchronously = synch;
+ Complete ();
+ }
+
+ public void Complete (int total)
+ {
+ this.total = total;
+ Complete ();
+ }
+
+ public void Complete (Exception e, bool synch)
+ {
+ this.completed_synchronously = synch;
+ this.delayed_exception = e;
+ Complete ();
+ }
+
+ public void Complete (Exception e)
+ {
+ this.delayed_exception = e;
+ Complete ();
+ }
+
+ public void Complete (Socket s)
+ {
+ this.accept_socket = s;
+ Complete ();
+ }
+
+ public void Complete (Socket s, int total)
+ {
+ this.accept_socket = s;
+ this.total = total;
+ Complete ();
+ }
+ }
+}
--- /dev/null
+// System.Net.Sockets.SocketAsyncWorker.cs
+//
+// Authors:
+// Ludovic Henry <ludovic@xamarin.com>
+//
+// Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
+//
+//
+// 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.
+//
+
+namespace System.Net.Sockets
+{
+ internal sealed class SocketAsyncWorker
+ {
+ public SocketAsyncResult result;
+ SocketAsyncEventArgs args;
+
+ public SocketAsyncWorker (SocketAsyncEventArgs args)
+ {
+ this.args = args;
+ result = new SocketAsyncResult ();
+ result.Worker = this;
+ }
+
+ public SocketAsyncWorker (SocketAsyncResult ares)
+ {
+ this.result = ares;
+ }
+
+ public void Dispose ()
+ {
+ if (result != null) {
+ result.Dispose ();
+ result = null;
+ args = null;
+ }
+ }
+
+ public static SocketAsyncCallback Dispatcher = new SocketAsyncCallback (DispatcherCB);
+
+ static void DispatcherCB (SocketAsyncResult sar)
+ {
+ /* SendPackets and ReceiveMessageFrom are not implemented yet */
+ switch (sar.operation) {
+ case SocketOperation.Receive:
+ case SocketOperation.ReceiveGeneric:
+ case SocketOperation.RecvJustCallback:
+ sar.Worker.Receive ();
+ break;
+ case SocketOperation.Send:
+ case SocketOperation.SendGeneric:
+ case SocketOperation.SendJustCallback:
+ sar.Worker.Send ();
+ break;
+ case SocketOperation.ReceiveFrom:
+ sar.Worker.ReceiveFrom ();
+ break;
+ case SocketOperation.SendTo:
+ sar.Worker.SendTo ();
+ break;
+ case SocketOperation.Connect:
+ sar.Worker.Connect ();
+ break;
+ case SocketOperation.Accept:
+ sar.Worker.Accept ();
+ break;
+ case SocketOperation.AcceptReceive:
+ sar.Worker.AcceptReceive ();
+ break;
+ case SocketOperation.Disconnect:
+ sar.Worker.Disconnect ();
+ break;
+ // case SocketOperation.ReceiveMessageFrom
+ // sar.Worker.ReceiveMessageFrom ()
+ // break;
+ // case SocketOperation.SendPackets:
+ // sar.Worker.SendPackets ();
+ // break;
+ default:
+ throw new NotImplementedException (String.Format ("Operation {0} is not implemented", sar.operation));
+ }
+ }
+
+ /* This is called when reusing a SocketAsyncEventArgs */
+ public void Init (Socket sock, SocketAsyncEventArgs args, SocketOperation op)
+ {
+ result.Init (sock, args, SocketAsyncEventArgs.Dispatcher, op, this);
+
+ SocketAsyncOperation async_op;
+
+ // Notes;
+ // -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
+ // -SendPackets and ReceiveMessageFrom are not implemented yet
+ switch (op) {
+ case SocketOperation.Connect:
+ async_op = SocketAsyncOperation.Connect;
+ break;
+ case SocketOperation.Accept:
+ async_op = SocketAsyncOperation.Accept;
+ break;
+ case SocketOperation.Disconnect:
+ async_op = SocketAsyncOperation.Disconnect;
+ break;
+ case SocketOperation.Receive:
+ case SocketOperation.ReceiveGeneric:
+ async_op = SocketAsyncOperation.Receive;
+ break;
+ case SocketOperation.ReceiveFrom:
+ async_op = SocketAsyncOperation.ReceiveFrom;
+ break;
+ // case SocketOperation.ReceiveMessageFrom:
+ // async_op = SocketAsyncOperation.ReceiveMessageFrom;
+ // break;
+ case SocketOperation.Send:
+ case SocketOperation.SendGeneric:
+ async_op = SocketAsyncOperation.Send;
+ break;
+ // case SocketOperation.SendPackets:
+ // async_op = SocketAsyncOperation.SendPackets;
+ // break;
+ case SocketOperation.SendTo:
+ async_op = SocketAsyncOperation.SendTo;
+ break;
+ default:
+ throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
+ }
+
+ args.SetLastOperation (async_op);
+ args.SocketError = SocketError.Success;
+ args.BytesTransferred = 0;
+ }
+
+ public void Accept ()
+ {
+ Socket acc_socket = null;
+ try {
+ if (args != null && args.AcceptSocket != null) {
+ result.socket.Accept (args.AcceptSocket);
+ acc_socket = args.AcceptSocket;
+ } else {
+ acc_socket = result.socket.Accept ();
+ if (args != null)
+ args.AcceptSocket = acc_socket;
+ }
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+
+ result.Complete (acc_socket);
+ }
+
+ /* only used in 2.0 profile and newer, but
+ * leave in older profiles to keep interface
+ * to runtime consistent
+ */
+ public void AcceptReceive ()
+ {
+ Socket acc_socket = null;
+ try {
+ if (result.AcceptSocket == null) {
+ acc_socket = result.socket.Accept ();
+ } else {
+ acc_socket = result.AcceptSocket;
+ result.socket.Accept (acc_socket);
+ }
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+
+ /* It seems the MS runtime
+ * special-cases 0-length requested
+ * receive data. See bug 464201.
+ */
+ int total = 0;
+ if (result.Size > 0) {
+ try {
+ SocketError error;
+ total = acc_socket.Receive_nochecks (result.Buffer, result.Offset, result.Size, result.SockFlags, out error);
+ if (error != 0) {
+ result.Complete (new SocketException ((int) error));
+ return;
+ }
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+ }
+
+ result.Complete (acc_socket, total);
+ }
+
+ public void Connect ()
+ {
+ if (result.EndPoint == null) {
+ result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
+ return;
+ }
+
+ SocketAsyncResult mconnect = result.AsyncState as SocketAsyncResult;
+ bool is_mconnect = (mconnect != null && mconnect.Addresses != null);
+ try {
+ int error_code;
+ EndPoint ep = result.EndPoint;
+ error_code = (int) result.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
+ if (error_code == 0) {
+ if (is_mconnect)
+ result = mconnect;
+ result.socket.seed_endpoint = ep;
+ result.socket.is_connected = true;
+ result.socket.is_bound = true;
+ result.socket.connect_in_progress = false;
+ result.error = 0;
+ result.Complete ();
+ if (is_mconnect)
+ result.DoMConnectCallback ();
+ return;
+ }
+
+ if (!is_mconnect) {
+ result.socket.connect_in_progress = false;
+ result.Complete (new SocketException (error_code));
+ return;
+ }
+
+ if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
+ mconnect.Complete (new SocketException (error_code));
+ if (is_mconnect)
+ mconnect.DoMConnectCallback ();
+ return;
+ }
+ mconnect.socket.BeginMConnect (mconnect);
+ } catch (Exception e) {
+ result.socket.connect_in_progress = false;
+ if (is_mconnect)
+ result = mconnect;
+ result.Complete (e);
+ if (is_mconnect)
+ result.DoMConnectCallback ();
+ return;
+ }
+ }
+
+ /* Also only used in 2.0 profile and newer */
+ public void Disconnect ()
+ {
+ try {
+ if (args != null)
+ result.ReuseSocket = args.DisconnectReuseSocket;
+ result.socket.Disconnect (result.ReuseSocket);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+ result.Complete ();
+ }
+
+ public void Receive ()
+ {
+ if (result.operation == SocketOperation.ReceiveGeneric) {
+ ReceiveGeneric ();
+ return;
+ }
+ // Actual recv() done in the runtime
+ result.Complete ();
+ }
+
+ public void ReceiveFrom ()
+ {
+ int total = 0;
+ try {
+ total = result.socket.ReceiveFrom_nochecks (result.Buffer, result.Offset, result.Size, result.SockFlags, ref result.EndPoint);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+
+ result.Complete (total);
+ }
+
+ public void ReceiveGeneric ()
+ {
+ int total = 0;
+ try {
+ total = result.socket.Receive (result.Buffers, result.SockFlags);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+ result.Complete (total);
+ }
+
+ int send_so_far;
+
+ void UpdateSendValues (int last_sent)
+ {
+ if (result.error == 0) {
+ send_so_far += last_sent;
+ result.Offset += last_sent;
+ result.Size -= last_sent;
+ }
+ }
+
+ public void Send ()
+ {
+ if (result.operation == SocketOperation.SendGeneric) {
+ SendGeneric ();
+ return;
+ }
+ // Actual send() done in the runtime
+ if (result.error == 0) {
+ UpdateSendValues (result.Total);
+ if (result.socket.is_disposed) {
+ result.Complete ();
+ return;
+ }
+
+ if (result.Size > 0) {
+ Socket.socket_pool_queue (SocketAsyncWorker.Dispatcher, result);
+ return; // Have to finish writing everything. See bug #74475.
+ }
+ result.Total = send_so_far;
+ send_so_far = 0;
+ }
+ result.Complete ();
+ }
+
+ public void SendTo ()
+ {
+ int total = 0;
+ try {
+ total = result.socket.SendTo_nochecks (result.Buffer, result.Offset, result.Size, result.SockFlags, result.EndPoint);
+
+ UpdateSendValues (total);
+ if (result.Size > 0) {
+ Socket.socket_pool_queue (SocketAsyncWorker.Dispatcher, result);
+ return; // Have to finish writing everything. See bug #74475.
+ }
+ result.Total = send_so_far;
+ send_so_far = 0;
+ } catch (Exception e) {
+ send_so_far = 0;
+ result.Complete (e);
+ return;
+ }
+
+ result.Complete ();
+ }
+
+ public void SendGeneric ()
+ {
+ int total = 0;
+ try {
+ total = result.socket.Send (result.Buffers, result.SockFlags);
+ } catch (Exception e) {
+ result.Complete (e);
+ return;
+ }
+ result.Complete (total);
+ }
+ }
+}
--- /dev/null
+// System.Net.Sockets.SocketOperation.cs
+//
+// Authors:
+// Ludovic Henry <ludovic@xamarin.com>
+//
+// Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
+//
+//
+// 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.
+//
+
+namespace System.Net.Sockets
+{
+ // Used by the runtime
+ internal enum SocketOperation {
+ Accept,
+ Connect,
+ Receive,
+ ReceiveFrom,
+ Send,
+ SendTo,
+ RecvJustCallback,
+ SendJustCallback,
+ UsedInProcess,
+ UsedInConsole2,
+ Disconnect,
+ AcceptReceive,
+ ReceiveGeneric,
+ SendGeneric
+ }
+}
+++ /dev/null
-// System.Net.Sockets.Socket.cs
-//
-// Authors:
-// Phillip Pearson (pp@myelin.co.nz)
-// Dick Porter <dick@ximian.com>
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-// Sridhar Kulkarni (sridharkulkarni@gmail.com)
-// Brian Nickel (brian.nickel@gmail.com)
-//
-// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
-// http://www.myelin.co.nz
-// (c) 2004-2011 Novell, Inc. (http://www.novell.com)
-//
-
-//
-// 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.
-//
-
-using System;
-using System.Net;
-using System.Collections;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.IO;
-using System.Security;
-using System.Text;
-
-#if !NET_2_1
-using System.Net.Configuration;
-using System.Net.NetworkInformation;
-#endif
-
-namespace System.Net.Sockets {
-
- public partial class Socket : IDisposable {
- [StructLayout (LayoutKind.Sequential)]
- struct WSABUF {
- public int len;
- public IntPtr buf;
- }
-
- // Used by the runtime
- internal enum SocketOperation {
- Accept,
- Connect,
- Receive,
- ReceiveFrom,
- Send,
- SendTo,
- RecvJustCallback,
- SendJustCallback,
- UsedInProcess,
- UsedInConsole2,
- Disconnect,
- AcceptReceive,
- ReceiveGeneric,
- SendGeneric
- }
-
- [StructLayout (LayoutKind.Sequential)]
- internal sealed class SocketAsyncResult: IAsyncResult
- {
- /* Same structure in the runtime */
- /*
- Keep this in sync with MonoSocketAsyncResult in
- metadata/socket-io.h and ProcessAsyncReader
- in System.Diagnostics/Process.cs.
- */
-
- public Socket Sock;
- public IntPtr handle;
- object state;
- AsyncCallback callback; // used from the runtime
- WaitHandle waithandle;
-
- Exception delayedException;
-
- public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
- public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
- public int Offset; // Receive,ReceiveFrom,Send,SendTo
- public int Size; // Receive,ReceiveFrom,Send,SendTo
- public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
- public Socket AcceptSocket; // AcceptReceive
- public IPAddress[] Addresses; // Connect
- public int Port; // Connect
- public IList<ArraySegment<byte>> Buffers; // Receive, Send
- public bool ReuseSocket; // Disconnect
-
- // Return values
- Socket acc_socket;
- int total;
-
- bool completed_sync;
- bool completed;
- public bool blocking;
- internal int error;
- public SocketOperation operation;
- public object ares;
- public int EndCalled;
-
- // These fields are not in MonoSocketAsyncResult
- public Worker Worker;
- public int CurrentAddress; // Connect
-
- public SocketAsyncResult ()
- {
- }
-
- public void Init (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
- {
- this.Sock = sock;
- if (sock != null) {
- this.blocking = sock.blocking;
- this.handle = sock.Handle;
- } else {
- this.blocking = true;
- this.handle = IntPtr.Zero;
- }
- this.state = state;
- this.callback = callback;
- GC.KeepAlive (this.callback);
- this.operation = operation;
- SockFlags = SocketFlags.None;
- if (waithandle != null)
- ((ManualResetEvent) waithandle).Reset ();
-
- delayedException = null;
-
- EndPoint = null;
- Buffer = null;
- Offset = 0;
- Size = 0;
- SockFlags = 0;
- AcceptSocket = null;
- Addresses = null;
- Port = 0;
- Buffers = null;
- ReuseSocket = false;
- acc_socket = null;
- total = 0;
-
- completed_sync = false;
- completed = false;
- blocking = false;
- error = 0;
- ares = null;
- EndCalled = 0;
- Worker = null;
- }
-
- public void DoMConnectCallback ()
- {
- if (callback == null)
- return;
- ThreadPool.UnsafeQueueUserWorkItem (_ => { callback (this); }, null);
- }
-
- public void Dispose ()
- {
- Init (null, null, null, 0);
- if (waithandle != null) {
- waithandle.Close ();
- waithandle = null;
- }
- }
-
- public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
- {
- this.Sock = sock;
- this.blocking = sock.blocking;
- this.handle = sock.Handle;
- this.state = state;
- this.callback = callback;
- GC.KeepAlive (this.callback);
- this.operation = operation;
- SockFlags = SocketFlags.None;
- Worker = new Worker (this);
- }
-
- public void CheckIfThrowDelayedException ()
- {
- if (delayedException != null) {
- Sock.connected = false;
- throw delayedException;
- }
-
- if (error != 0) {
- Sock.connected = false;
- throw new SocketException (error);
- }
- }
-
- void CompleteAllOnDispose (Queue queue)
- {
- object [] pending = queue.ToArray ();
- queue.Clear ();
-
- WaitCallback cb;
- for (int i = 0; i < pending.Length; i++) {
- Worker worker = (Worker) pending [i];
- SocketAsyncResult ares = worker.result;
- cb = new WaitCallback (ares.CompleteDisposed);
- ThreadPool.UnsafeQueueUserWorkItem (cb, null);
- }
- }
-
- void CompleteDisposed (object unused)
- {
- Complete ();
- }
-
- public void Complete ()
- {
- if (operation != SocketOperation.Receive && Sock.disposed)
- delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
-
- IsCompleted = true;
-
- Queue queue = null;
- if (operation == SocketOperation.Receive ||
- operation == SocketOperation.ReceiveFrom ||
- operation == SocketOperation.ReceiveGeneric ||
- operation == SocketOperation.Accept) {
- queue = Sock.readQ;
- } else if (operation == SocketOperation.Send ||
- operation == SocketOperation.SendTo ||
- operation == SocketOperation.SendGeneric) {
-
- queue = Sock.writeQ;
- }
-
- if (queue != null) {
- Worker worker = null;
- SocketAsyncCall sac = null;
- lock (queue) {
- // queue.Count will only be 0 if the socket is closed while receive/send/accept
- // operation(s) are pending and at least one call to this method is
- // waiting on the lock while another one calls CompleteAllOnDispose()
- if (queue.Count > 0)
- queue.Dequeue (); // remove ourselves
- if (queue.Count > 0) {
- worker = (Worker) queue.Peek ();
- if (!Sock.disposed) {
- sac = Worker.Dispatcher;
- } else {
- CompleteAllOnDispose (queue);
- }
- }
- }
-
- if (sac != null)
- Socket.socket_pool_queue (sac, worker.result);
- }
- // IMPORTANT: 'callback', if any is scheduled from unmanaged code
- }
-
- public void Complete (bool synch)
- {
- completed_sync = synch;
- Complete ();
- }
-
- public void Complete (int total)
- {
- this.total = total;
- Complete ();
- }
-
- public void Complete (Exception e, bool synch)
- {
- completed_sync = synch;
- delayedException = e;
- Complete ();
- }
-
- public void Complete (Exception e)
- {
- delayedException = e;
- Complete ();
- }
-
- public void Complete (Socket s)
- {
- acc_socket = s;
- Complete ();
- }
-
- public void Complete (Socket s, int total)
- {
- acc_socket = s;
- this.total = total;
- Complete ();
- }
-
- public object AsyncState {
- get {
- return state;
- }
- }
-
- public WaitHandle AsyncWaitHandle {
- get {
- lock (this) {
- if (waithandle == null)
- waithandle = new ManualResetEvent (completed);
- }
-
- return waithandle;
- }
- set {
- waithandle=value;
- }
- }
-
- public bool CompletedSynchronously {
- get {
- return(completed_sync);
- }
- }
-
- public bool IsCompleted {
- get {
- return(completed);
- }
- set {
- completed=value;
- lock (this) {
- if (waithandle != null && value) {
- ((ManualResetEvent) waithandle).Set ();
- }
- }
- }
- }
-
- public Socket Socket {
- get {
- return acc_socket;
- }
- }
-
- public int Total {
- get { return total; }
- set { total = value; }
- }
-
- public SocketError ErrorCode {
- get {
- SocketException ex = delayedException as SocketException;
- if (ex != null)
- return(ex.SocketErrorCode);
-
- if (error != 0)
- return((SocketError)error);
-
- return(SocketError.Success);
- }
- }
- }
-
- internal sealed class Worker
- {
- public SocketAsyncResult result;
- SocketAsyncEventArgs args;
-
- public Worker (SocketAsyncEventArgs args)
- {
- this.args = args;
- result = new SocketAsyncResult ();
- result.Worker = this;
- }
-
- public Worker (SocketAsyncResult ares)
- {
- this.result = ares;
- }
-
- public void Dispose ()
- {
- if (result != null) {
- result.Dispose ();
- result = null;
- args = null;
- }
- }
-
- public static SocketAsyncCall Dispatcher = new SocketAsyncCall (DispatcherCB);
-
- static void DispatcherCB (SocketAsyncResult sar)
- {
- SocketOperation op = sar.operation;
- if (op == Socket.SocketOperation.Receive || op == Socket.SocketOperation.ReceiveGeneric ||
- op == Socket.SocketOperation.RecvJustCallback)
- sar.Worker.Receive ();
- else if (op == Socket.SocketOperation.Send || op == Socket.SocketOperation.SendGeneric ||
- op == Socket.SocketOperation.SendJustCallback)
- sar.Worker.Send ();
- else if (op == Socket.SocketOperation.ReceiveFrom)
- sar.Worker.ReceiveFrom ();
- else if (op == Socket.SocketOperation.SendTo)
- sar.Worker.SendTo ();
- else if (op == Socket.SocketOperation.Connect)
- sar.Worker.Connect ();
- else if (op == Socket.SocketOperation.Accept)
- sar.Worker.Accept ();
- else if (op == Socket.SocketOperation.AcceptReceive)
- sar.Worker.AcceptReceive ();
- else if (op == Socket.SocketOperation.Disconnect)
- sar.Worker.Disconnect ();
-
- // SendPackets and ReceiveMessageFrom are not implemented yet
- /*
- else if (op == Socket.SocketOperation.ReceiveMessageFrom)
- async_op = SocketAsyncOperation.ReceiveMessageFrom;
- else if (op == Socket.SocketOperation.SendPackets)
- async_op = SocketAsyncOperation.SendPackets;
- */
- else
- throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
- }
-
- /* This is called when reusing a SocketAsyncEventArgs */
- public void Init (Socket sock, SocketAsyncEventArgs args, SocketOperation op)
- {
- result.Init (sock, args, SocketAsyncEventArgs.Dispatcher, op);
- result.Worker = this;
- SocketAsyncOperation async_op;
-
- // Notes;
- // -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
- // -SendPackets and ReceiveMessageFrom are not implemented yet
- if (op == Socket.SocketOperation.Connect)
- async_op = SocketAsyncOperation.Connect;
- else if (op == Socket.SocketOperation.Accept)
- async_op = SocketAsyncOperation.Accept;
- else if (op == Socket.SocketOperation.Disconnect)
- async_op = SocketAsyncOperation.Disconnect;
- else if (op == Socket.SocketOperation.Receive || op == Socket.SocketOperation.ReceiveGeneric)
- async_op = SocketAsyncOperation.Receive;
- else if (op == Socket.SocketOperation.ReceiveFrom)
- async_op = SocketAsyncOperation.ReceiveFrom;
- /*
- else if (op == Socket.SocketOperation.ReceiveMessageFrom)
- async_op = SocketAsyncOperation.ReceiveMessageFrom;
- */
- else if (op == Socket.SocketOperation.Send || op == Socket.SocketOperation.SendGeneric)
- async_op = SocketAsyncOperation.Send;
- /*
- else if (op == Socket.SocketOperation.SendPackets)
- async_op = SocketAsyncOperation.SendPackets;
- */
- else if (op == Socket.SocketOperation.SendTo)
- async_op = SocketAsyncOperation.SendTo;
- else
- throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
-
- args.SetLastOperation (async_op);
- args.SocketError = SocketError.Success;
- args.BytesTransferred = 0;
- }
-
- public void Accept ()
- {
- Socket acc_socket = null;
- try {
- if (args != null && args.AcceptSocket != null) {
- result.Sock.Accept (args.AcceptSocket);
- acc_socket = args.AcceptSocket;
- } else {
- acc_socket = result.Sock.Accept ();
- if (args != null)
- args.AcceptSocket = acc_socket;
- }
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- result.Complete (acc_socket);
- }
-
- /* only used in 2.0 profile and newer, but
- * leave in older profiles to keep interface
- * to runtime consistent
- */
- public void AcceptReceive ()
- {
- Socket acc_socket = null;
- try {
- if (result.AcceptSocket == null) {
- acc_socket = result.Sock.Accept ();
- } else {
- acc_socket = result.AcceptSocket;
- result.Sock.Accept (acc_socket);
- }
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- /* It seems the MS runtime
- * special-cases 0-length requested
- * receive data. See bug 464201.
- */
- int total = 0;
- if (result.Size > 0) {
- try {
- SocketError error;
- total = acc_socket.Receive_nochecks (result.Buffer,
- result.Offset,
- result.Size,
- result.SockFlags,
- out error);
- if (error != 0) {
- result.Complete (new SocketException ((int) error));
- return;
- }
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- }
-
- result.Complete (acc_socket, total);
- }
-
- public void Connect ()
- {
- if (result.EndPoint == null) {
- result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
- return;
- }
-
- SocketAsyncResult mconnect = result.AsyncState as SocketAsyncResult;
- bool is_mconnect = (mconnect != null && mconnect.Addresses != null);
- try {
- int error_code;
- EndPoint ep = result.EndPoint;
- error_code = (int) result.Sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
- if (error_code == 0) {
- if (is_mconnect)
- result = mconnect;
- result.Sock.seed_endpoint = ep;
- result.Sock.connected = true;
- result.Sock.isbound = true;
- result.Sock.connect_in_progress = false;
- result.error = 0;
- result.Complete ();
- if (is_mconnect)
- result.DoMConnectCallback ();
- return;
- }
-
- if (!is_mconnect) {
- result.Sock.connect_in_progress = false;
- result.Complete (new SocketException (error_code));
- return;
- }
-
- if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
- mconnect.Complete (new SocketException (error_code));
- if (is_mconnect)
- mconnect.DoMConnectCallback ();
- return;
- }
- mconnect.Sock.BeginMConnect (mconnect);
- } catch (Exception e) {
- result.Sock.connect_in_progress = false;
- if (is_mconnect)
- result = mconnect;
- result.Complete (e);
- if (is_mconnect)
- result.DoMConnectCallback ();
- return;
- }
- }
-
- /* Also only used in 2.0 profile and newer */
- public void Disconnect ()
- {
- try {
- if (args != null)
- result.ReuseSocket = args.DisconnectReuseSocket;
- result.Sock.Disconnect (result.ReuseSocket);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- result.Complete ();
- }
-
- public void Receive ()
- {
- if (result.operation == SocketOperation.ReceiveGeneric) {
- ReceiveGeneric ();
- return;
- }
- // Actual recv() done in the runtime
- result.Complete ();
- }
-
- public void ReceiveFrom ()
- {
- int total = 0;
- try {
- total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
- result.Offset,
- result.Size,
- result.SockFlags,
- ref result.EndPoint);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
-
- result.Complete (total);
- }
-
- public void ReceiveGeneric ()
- {
- int total = 0;
- try {
- total = result.Sock.Receive (result.Buffers, result.SockFlags);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- result.Complete (total);
- }
-
- int send_so_far;
-
- void UpdateSendValues (int last_sent)
- {
- if (result.error == 0) {
- send_so_far += last_sent;
- result.Offset += last_sent;
- result.Size -= last_sent;
- }
- }
-
- public void Send ()
- {
- if (result.operation == SocketOperation.SendGeneric) {
- SendGeneric ();
- return;
- }
- // Actual send() done in the runtime
- if (result.error == 0) {
- UpdateSendValues (result.Total);
- if (result.Sock.disposed) {
- result.Complete ();
- return;
- }
-
- if (result.Size > 0) {
- Socket.socket_pool_queue (Worker.Dispatcher, result);
- return; // Have to finish writing everything. See bug #74475.
- }
- result.Total = send_so_far;
- send_so_far = 0;
- }
- result.Complete ();
- }
-
- public void SendTo ()
- {
- int total = 0;
- try {
- total = result.Sock.SendTo_nochecks (result.Buffer,
- result.Offset,
- result.Size,
- result.SockFlags,
- result.EndPoint);
-
- UpdateSendValues (total);
- if (result.Size > 0) {
- Socket.socket_pool_queue (Worker.Dispatcher, result);
- return; // Have to finish writing everything. See bug #74475.
- }
- result.Total = send_so_far;
- send_so_far = 0;
- } catch (Exception e) {
- send_so_far = 0;
- result.Complete (e);
- return;
- }
-
- result.Complete ();
- }
-
- public void SendGeneric ()
- {
- int total = 0;
- try {
- total = result.Sock.Send (result.Buffers, result.SockFlags);
- } catch (Exception e) {
- result.Complete (e);
- return;
- }
- result.Complete (total);
- }
- }
-
- private Queue readQ = new Queue (2);
- private Queue writeQ = new Queue (2);
-
- internal delegate void SocketAsyncCall (SocketAsyncResult sar);
-
- /*
- * These two fields are looked up by name by the runtime, don't change
- * their name without also updating the runtime code.
- */
- private static int ipv4Supported = -1, ipv6Supported = -1;
- int linger_timeout;
-
- static Socket ()
- {
- // initialize ipv4Supported and ipv6Supported
- CheckProtocolSupport ();
- }
-
- internal static void CheckProtocolSupport ()
- {
- if(ipv4Supported == -1) {
- try {
- Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- tmp.Close();
-
- ipv4Supported = 1;
- } catch {
- ipv4Supported = 0;
- }
- }
-
- if (ipv6Supported == -1) {
- // We need to put a try/catch around ConfigurationManager methods as will always throw an exception
- // when run in a mono embedded application. This occurs as embedded applications do not have a setup
- // for application config. The exception is not thrown when called from a normal .NET application.
- //
- // We, then, need to guard calls to the ConfigurationManager. If the config is not found or throws an
- // exception, will fall through to the existing Socket / API directly below in the code.
- //
- // Also note that catching ConfigurationErrorsException specifically would require library dependency
- // System.Configuration, and wanted to avoid that.
-#if !NET_2_1
-#if CONFIGURATION_DEP
- try {
- SettingsSection config;
- config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
- if (config != null)
- ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
- } catch {
- ipv6Supported = -1;
- }
-#else
- try {
- NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
- if (config != null)
- ipv6Supported = config.ipv6Enabled ? -1 : 0;
- } catch {
- ipv6Supported = -1;
- }
-#endif
-#endif
- if (ipv6Supported != 0) {
- try {
- Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
- tmp.Close();
-
- ipv6Supported = 1;
- } catch {
- ipv6Supported = 0;
- }
- }
- }
- }
-
- public static bool SupportsIPv4 {
- get {
- CheckProtocolSupport();
- return ipv4Supported == 1;
- }
- }
-
- [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
- public static bool SupportsIPv6 {
- get {
- CheckProtocolSupport();
- return ipv6Supported == 1;
- }
- }
-#if NET_2_1
- public static bool OSSupportsIPv4 {
- get {
- CheckProtocolSupport();
- return ipv4Supported == 1;
- }
- }
-#endif
-#if NET_2_1
- public static bool OSSupportsIPv6 {
- get {
- CheckProtocolSupport();
- return ipv6Supported == 1;
- }
- }
-#else
- public static bool OSSupportsIPv6 {
- get {
- NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
-
- foreach (NetworkInterface adapter in nics) {
- if (adapter.Supports (NetworkInterfaceComponent.IPv6))
- return true;
- }
- return false;
- }
- }
-#endif
-
- /* the field "socket" is looked up by name by the runtime */
- private SafeSocketHandle socket;
- private AddressFamily address_family;
- private SocketType socket_type;
- private ProtocolType protocol_type;
- internal bool blocking=true;
- private bool isbound;
- /* When true, the socket was connected at the time of
- * the last IO operation
- */
- private bool connected;
- /* true if we called Close_internal */
- private bool closed;
- internal bool disposed;
- bool connect_in_progress;
-
- /*
- * This EndPoint is used when creating new endpoints. Because
- * there are many types of EndPoints possible,
- * seed_endpoint.Create(addr) is used for creating new ones.
- * As such, this value is set on Bind, SentTo, ReceiveFrom,
- * Connect, etc.
- */
- internal EndPoint seed_endpoint = null;
-
- // Creates a new system socket, returning the handle
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern IntPtr Socket_internal(AddressFamily family,
- SocketType type,
- ProtocolType proto,
- out int error);
-
- public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
- {
-#if NET_2_1 && !MOBILE
- switch (addressFamily) {
- case AddressFamily.InterNetwork: // ok
- case AddressFamily.InterNetworkV6: // ok
- case AddressFamily.Unknown: // SocketException will be thrown later (with right error #)
- break;
- // case AddressFamily.Unspecified:
- default:
- throw new ArgumentException ("addressFamily");
- }
-
- switch (socketType) {
- case SocketType.Stream: // ok
- case SocketType.Unknown: // SocketException will be thrown later (with right error #)
- break;
- default:
- throw new ArgumentException ("socketType");
- }
-
- switch (protocolType) {
- case ProtocolType.Tcp: // ok
- case ProtocolType.Unspecified: // ok
- case ProtocolType.Unknown: // SocketException will be thrown later (with right error #)
- break;
- default:
- throw new ArgumentException ("protocolType");
- }
-#endif
- address_family = addressFamily;
- socket_type = socketType;
- protocol_type = protocolType;
-
- int error;
-
- var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
- socket = new SafeSocketHandle (handle, true);
-
- if (error != 0)
- throw new SocketException (error);
-#if !NET_2_1 || MOBILE
- SocketDefaults ();
-#endif
- }
-
- [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
- public Socket (SocketType socketType, ProtocolType protocolType)
- : this (AddressFamily.InterNetwork, socketType, protocolType)
- {
- }
-
- ~Socket ()
- {
- Dispose (false);
- }
-
-
- public AddressFamily AddressFamily {
- get { return address_family; }
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern static void Blocking_internal(IntPtr socket,
- bool block,
- out int error);
-
- private static void Blocking_internal (SafeSocketHandle safeHandle,
- bool block,
- out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- public bool Blocking {
- get {
- return(blocking);
- }
- set {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- int error;
-
- Blocking_internal (socket, value, out error);
-
- if (error != 0)
- throw new SocketException (error);
-
- blocking=value;
- }
- }
-
- public bool Connected {
- get { return connected; }
- internal set { connected = value; }
- }
-
- public ProtocolType ProtocolType {
- get { return protocol_type; }
- }
-
- public bool NoDelay {
- get {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- ThrowIfUpd ();
-
- return (int)(GetSocketOption (
- SocketOptionLevel.Tcp,
- SocketOptionName.NoDelay)) != 0;
- }
-
- set {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- ThrowIfUpd ();
-
- SetSocketOption (
- SocketOptionLevel.Tcp,
- SocketOptionName.NoDelay, value ? 1 : 0);
- }
- }
-
- public int ReceiveBufferSize {
- get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
- return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));
- }
- set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
- if (value < 0) {
- throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
- }
-
- SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
- }
- }
-
- public int SendBufferSize {
- get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
- return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer));
- }
- set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
- if (value < 0) {
- throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
- }
-
- SetSocketOption (SocketOptionLevel.Socket,
- SocketOptionName.SendBuffer,
- value);
- }
- }
-
- public short Ttl {
- get {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
-
- short ttl_val;
-
- if (address_family == AddressFamily.InterNetwork) {
- ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
- } else if (address_family == AddressFamily.InterNetworkV6) {
- ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit));
- } else {
- throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
- }
-
- return(ttl_val);
- }
- set {
- if (disposed && closed) {
- throw new ObjectDisposedException (GetType ().ToString ());
- }
- if (value < 0) {
- throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
- }
-
- if (address_family == AddressFamily.InterNetwork) {
- SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
- } else if (address_family == AddressFamily.InterNetworkV6) {
- SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
- } else {
- throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
- }
- }
- }
-
- // Returns the remote endpoint details in addr and port
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, int family, out int error);
-
- private static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- public EndPoint RemoteEndPoint {
- get {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- /*
- * If the seed EndPoint is null, Connect, Bind,
- * etc has not yet been called. MS returns null
- * in this case.
- */
- if (!connected || seed_endpoint == null)
- return null;
- SocketAddress sa;
- int error;
-
- sa=RemoteEndPoint_internal(socket, (int) address_family, out error);
-
- if (error != 0)
- throw new SocketException (error);
-
- return seed_endpoint.Create (sa);
- }
- }
-
- void Linger (IntPtr handle)
- {
- if (!connected || linger_timeout <= 0)
- return;
-
- // We don't want to receive any more data
- int error;
- Shutdown_internal (handle, SocketShutdown.Receive, out error);
- if (error != 0)
- return;
-
- int seconds = linger_timeout / 1000;
- int ms = linger_timeout % 1000;
- if (ms > 0) {
- // If the other end closes, this will return 'true' with 'Available' == 0
- Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
- if (error != 0)
- return;
-
- }
- if (seconds > 0) {
- LingerOption linger = new LingerOption (true, seconds);
- SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
- /* Not needed, we're closing upon return */
- /*if (error != 0)
- return; */
- }
- }
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern void cancel_blocking_socket_operation (Thread thread);
-
- protected virtual void Dispose (bool disposing)
- {
- if (disposed)
- return;
-
- disposed = true;
- bool was_connected = connected;
- connected = false;
-
- if (socket != null) {
- closed = true;
- IntPtr x = Handle;
-
- if (was_connected)
- Linger (x);
-
- socket.Dispose ();
- }
- }
-
- public void Dispose ()
- {
- Dispose (true);
- GC.SuppressFinalize (this);
- }
-
- // Closes the socket
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern static void Close_internal(IntPtr socket, out int error);
-
- public void Close ()
- {
- linger_timeout = 0;
- ((IDisposable) this).Dispose ();
- }
-
- public void Close (int timeout)
- {
- linger_timeout = timeout;
- ((IDisposable) this).Dispose ();
- }
-
- // Connects to the remote address
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void Connect_internal(IntPtr sock,
- SocketAddress sa,
- out int error);
-
- private static void Connect_internal (SafeSocketHandle safeHandle,
- SocketAddress sa,
- out int error)
- {
- try {
- safeHandle.RegisterForBlockingSyscall ();
- Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
- } finally {
- safeHandle.UnRegisterForBlockingSyscall ();
- }
- }
-
- public void Connect (EndPoint remoteEP)
- {
- SocketAddress serial = null;
-
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (remoteEP == null)
- throw new ArgumentNullException ("remoteEP");
-
- IPEndPoint ep = remoteEP as IPEndPoint;
- if (ep != null && socket_type != SocketType.Dgram) /* Dgram uses Any to 'disconnect' */
- if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
- throw new SocketException ((int) SocketError.AddressNotAvailable);
-
- if (islistening)
- throw new InvalidOperationException ();
- serial = remoteEP.Serialize ();
-
- int error = 0;
-
- Connect_internal (socket, serial, out error);
-
- if (error == 0 || error == 10035)
- seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
-
- if (error != 0) {
- if (closed)
- error = SOCKET_CLOSED;
- throw new SocketException (error);
- }
-
- if (socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)))
- connected = false;
- else
- connected = true;
- isbound = true;
- }
-
- public bool ReceiveAsync (SocketAsyncEventArgs e)
- {
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
- // thrown when e.Buffer and e.BufferList are null (works fine when one is
- // set to a valid object)
- if (e.Buffer == null && e.BufferList == null)
- throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
-
- e.curSocket = this;
- SocketOperation op = (e.Buffer != null) ? SocketOperation.Receive : SocketOperation.ReceiveGeneric;
- e.Worker.Init (this, e, op);
- SocketAsyncResult res = e.Worker.result;
- if (e.Buffer != null) {
- res.Buffer = e.Buffer;
- res.Offset = e.Offset;
- res.Size = e.Count;
- } else {
- res.Buffers = e.BufferList;
- }
- res.SockFlags = e.SocketFlags;
- int count;
- lock (readQ) {
- readQ.Enqueue (e.Worker);
- count = readQ.Count;
- }
- if (count == 1) {
- // Receive takes care of ReceiveGeneric
- socket_pool_queue (Worker.Dispatcher, res);
- }
-
- return true;
- }
-
- public bool SendAsync (SocketAsyncEventArgs e)
- {
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (e.Buffer == null && e.BufferList == null)
- throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
-
- e.curSocket = this;
- SocketOperation op = (e.Buffer != null) ? SocketOperation.Send : SocketOperation.SendGeneric;
- e.Worker.Init (this, e, op);
- SocketAsyncResult res = e.Worker.result;
- if (e.Buffer != null) {
- res.Buffer = e.Buffer;
- res.Offset = e.Offset;
- res.Size = e.Count;
- } else {
- res.Buffers = e.BufferList;
- }
- res.SockFlags = e.SocketFlags;
- int count;
- lock (writeQ) {
- writeQ.Enqueue (e.Worker);
- count = writeQ.Count;
- }
- if (count == 1) {
- // Send takes care of SendGeneric
- socket_pool_queue (Worker.Dispatcher, res);
- }
- return true;
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
-
- private static bool Poll_internal (SafeSocketHandle safeHandle, SelectMode mode, int timeout, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- return Poll_internal (safeHandle.DangerousGetHandle (), mode, timeout, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static int Receive_internal(IntPtr sock,
- byte[] buffer,
- int offset,
- int count,
- SocketFlags flags,
- out int error);
-
- private static int Receive_internal (SafeSocketHandle safeHandle,
- byte[] buffer,
- int offset,
- int count,
- SocketFlags flags,
- out int error)
- {
- try {
- safeHandle.RegisterForBlockingSyscall ();
- return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
- } finally {
- safeHandle.UnRegisterForBlockingSyscall ();
- }
- }
-
- internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
- {
- int nativeError;
- int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
- error = (SocketError) nativeError;
- if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
- connected = false;
- isbound = false;
- } else {
- connected = true;
- }
-
- return ret;
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void GetSocketOption_obj_internal(IntPtr socket,
- SocketOptionLevel level, SocketOptionName name, out object obj_val,
- out int error);
-
- private static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle,
- SocketOptionLevel level, SocketOptionName name, out object obj_val,
- out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static int Send_internal(IntPtr sock,
- byte[] buf, int offset,
- int count,
- SocketFlags flags,
- out int error);
-
- private static int Send_internal (SafeSocketHandle safeHandle,
- byte[] buf, int offset,
- int count,
- SocketFlags flags,
- out int error)
- {
- try {
- safeHandle.RegisterForBlockingSyscall ();
- return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
- } finally {
- safeHandle.UnRegisterForBlockingSyscall ();
- }
- }
-
- internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
- {
- if (size == 0) {
- error = SocketError.Success;
- return 0;
- }
-
- int nativeError;
-
- int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
-
- error = (SocketError)nativeError;
-
- if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
- connected = false;
- isbound = false;
- } else {
- connected = true;
- }
-
- return ret;
- }
-
- public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- object obj_val;
- int error;
-
- GetSocketOption_obj_internal (socket, optionLevel, optionName, out obj_val,
- out error);
- if (error != 0)
- throw new SocketException (error);
-
- if (optionName == SocketOptionName.Linger) {
- return((LingerOption)obj_val);
- } else if (optionName == SocketOptionName.AddMembership ||
- optionName == SocketOptionName.DropMembership) {
- return((MulticastOption)obj_val);
- } else if (obj_val is int) {
- return((int)obj_val);
- } else {
- return(obj_val);
- }
- }
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
-
- private static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- public void Shutdown (SocketShutdown how)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (!connected)
- throw new SocketException (10057); // Not connected
-
- int error;
-
- Shutdown_internal (socket, how, out error);
- if (error != 0)
- throw new SocketException (error);
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
- SocketOptionName name, object obj_val,
- byte [] byte_val, int int_val,
- out int error);
-
- private static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level,
- SocketOptionName name, object obj_val,
- byte [] byte_val, int int_val,
- out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- int error;
-
- SetSocketOption_internal (socket, optionLevel, optionName, null,
- null, optionValue, out error);
-
- if (error != 0)
- throw new SocketException (error);
- }
-
- private void ThrowIfUpd ()
- {
-#if !NET_2_1 || MOBILE
- if (protocol_type == ProtocolType.Udp)
- throw new SocketException ((int)SocketError.ProtocolOption);
-#endif
- }
-
- public
- IAsyncResult BeginConnect(EndPoint end_point, AsyncCallback callback, object state)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (end_point == null)
- throw new ArgumentNullException ("end_point");
-
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
- req.EndPoint = end_point;
-
- // Bug #75154: Connect() should not succeed for .Any addresses.
- if (end_point is IPEndPoint) {
- IPEndPoint ep = (IPEndPoint) end_point;
- if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
- req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
- return req;
- }
- }
-
- int error = 0;
- if (connect_in_progress) {
- // This could happen when multiple IPs are used
- // Calling connect() again will reset the connection attempt and cause
- // an error. Better to just close the socket and move on.
- connect_in_progress = false;
- socket.Dispose ();
- var handle = Socket_internal (address_family, socket_type, protocol_type, out error);
- socket = new SafeSocketHandle (handle, true);
- if (error != 0)
- throw new SocketException (error);
- }
- bool blk = blocking;
- if (blk)
- Blocking = false;
- SocketAddress serial = end_point.Serialize ();
- Connect_internal (socket, serial, out error);
- if (blk)
- Blocking = true;
- if (error == 0) {
- // succeeded synch
- connected = true;
- isbound = true;
- req.Complete (true);
- return req;
- }
-
- if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
- // error synch
- connected = false;
- isbound = false;
- req.Complete (new SocketException (error), true);
- return req;
- }
-
- // continue asynch
- connected = false;
- isbound = false;
- connect_in_progress = true;
- socket_pool_queue (Worker.Dispatcher, req);
- return req;
- }
-
- public
- IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
-
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (addresses == null)
- throw new ArgumentNullException ("addresses");
-
- if (addresses.Length == 0)
- throw new ArgumentException ("Empty addresses list");
-
- if (this.AddressFamily != AddressFamily.InterNetwork &&
- this.AddressFamily != AddressFamily.InterNetworkV6)
- throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
-
- if (port <= 0 || port > 65535)
- throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
- if (islistening)
- throw new InvalidOperationException ();
-
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
- req.Addresses = addresses;
- req.Port = port;
- connected = false;
- return BeginMConnect (req);
- }
-
- IAsyncResult BeginMConnect (SocketAsyncResult req)
- {
- IAsyncResult ares = null;
- Exception exc = null;
- for (int i = req.CurrentAddress; i < req.Addresses.Length; i++) {
- IPAddress addr = req.Addresses [i];
- IPEndPoint ep = new IPEndPoint (addr, req.Port);
- try {
- req.CurrentAddress++;
- ares = BeginConnect (ep, null, req);
- if (ares.IsCompleted && ares.CompletedSynchronously) {
- ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
- req.DoMConnectCallback ();
- }
- break;
- } catch (Exception e) {
- exc = e;
- ares = null;
- }
- }
-
- if (ares == null)
- throw exc;
-
- return req;
- }
-
- // Returns false when it is ok to use RemoteEndPoint
- // true when addresses must be used (and addresses could be null/empty)
- bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
- {
- addresses = null;
- // Connect to the first address that match the host name, like:
- // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
- // while skipping entries that do not match the address family
- DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
- if (dep != null) {
- addresses = Dns.GetHostAddresses (dep.Host);
- return true;
- } else {
- e.ConnectByNameError = null;
- return false;
- }
- }
-
- bool ConnectAsyncReal (SocketAsyncEventArgs e)
- {
- bool use_remoteep = true;
- IPAddress [] addresses = null;
- use_remoteep = !GetCheckedIPs (e, out addresses);
- e.curSocket = this;
- Worker w = e.Worker;
- w.Init (this, e, SocketOperation.Connect);
- SocketAsyncResult result = w.result;
- IAsyncResult ares = null;
- try {
- if (use_remoteep) {
- result.EndPoint = e.RemoteEndPoint;
- ares = BeginConnect (e.RemoteEndPoint, SocketAsyncEventArgs.Dispatcher, e);
- }
- else {
-
- DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
- result.Addresses = addresses;
- result.Port = dep.Port;
-
- ares = BeginConnect (addresses, dep.Port, SocketAsyncEventArgs.Dispatcher, e);
- }
- if (ares.IsCompleted && ares.CompletedSynchronously) {
- ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
- return false;
- }
- } catch (Exception exc) {
- result.Complete (exc, true);
- return false;
- }
- return true;
- }
-
- public bool ConnectAsync (SocketAsyncEventArgs e)
- {
- // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (islistening)
- throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
- if (e.RemoteEndPoint == null)
- throw new ArgumentNullException ("remoteEP");
-
- return ConnectAsyncReal (e);
- }
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
-
- private static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
- {
- try {
- safeHandle.RegisterForBlockingSyscall ();
- return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
- } finally {
- safeHandle.UnRegisterForBlockingSyscall ();
- }
- }
-
- public
- int Receive (IList<ArraySegment<byte>> buffers)
- {
- int ret;
- SocketError error;
- ret = Receive (buffers, SocketFlags.None, out error);
- if (error != SocketError.Success) {
- throw new SocketException ((int)error);
- }
- return(ret);
- }
-
- [CLSCompliant (false)]
- public
- int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
- {
- int ret;
- SocketError error;
- ret = Receive (buffers, socketFlags, out error);
- if (error != SocketError.Success) {
- throw new SocketException ((int)error);
- }
- return(ret);
- }
-
- [CLSCompliant (false)]
- public
- int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (buffers == null ||
- buffers.Count == 0) {
- throw new ArgumentNullException ("buffers");
- }
-
- int numsegments = buffers.Count;
- int nativeError;
- int ret;
-
- /* Only example I can find of sending a byte
- * array reference directly into an internal
- * call is in
- * System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
- * so taking a lead from that...
- */
- WSABUF[] bufarray = new WSABUF[numsegments];
- GCHandle[] gch = new GCHandle[numsegments];
-
- for(int i = 0; i < numsegments; i++) {
- ArraySegment<byte> segment = buffers[i];
-
- if (segment.Offset < 0 || segment.Count < 0 ||
- segment.Count > segment.Array.Length - segment.Offset)
- throw new ArgumentOutOfRangeException ("segment");
-
- gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
- bufarray[i].len = segment.Count;
- bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
- }
-
- try {
- ret = Receive_internal (socket, bufarray,
- socketFlags,
- out nativeError);
- } finally {
- for(int i = 0; i < numsegments; i++) {
- if (gch[i].IsAllocated) {
- gch[i].Free ();
- }
- }
- }
-
- errorCode = (SocketError)nativeError;
- return(ret);
- }
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
-
- private static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
- {
- bool release = false;
- try {
- safeHandle.DangerousAddRef (ref release);
- return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
- } finally {
- if (release)
- safeHandle.DangerousRelease ();
- }
- }
-
- public
- int Send (IList<ArraySegment<byte>> buffers)
- {
- int ret;
- SocketError error;
- ret = Send (buffers, SocketFlags.None, out error);
- if (error != SocketError.Success) {
- throw new SocketException ((int)error);
- }
- return(ret);
- }
-
- public
- int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
- {
- int ret;
- SocketError error;
- ret = Send (buffers, socketFlags, out error);
- if (error != SocketError.Success) {
- throw new SocketException ((int)error);
- }
- return(ret);
- }
-
- [CLSCompliant (false)]
- public
- int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (buffers == null)
- throw new ArgumentNullException ("buffers");
- if (buffers.Count == 0)
- throw new ArgumentException ("Buffer is empty", "buffers");
- int numsegments = buffers.Count;
- int nativeError;
- int ret;
-
- WSABUF[] bufarray = new WSABUF[numsegments];
- GCHandle[] gch = new GCHandle[numsegments];
- for(int i = 0; i < numsegments; i++) {
- ArraySegment<byte> segment = buffers[i];
-
- if (segment.Offset < 0 || segment.Count < 0 ||
- segment.Count > segment.Array.Length - segment.Offset)
- throw new ArgumentOutOfRangeException ("segment");
-
- gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
- bufarray[i].len = segment.Count;
- bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
- }
-
- try {
- ret = Send_internal (socket, bufarray, socketFlags, out nativeError);
- } finally {
- for(int i = 0; i < numsegments; i++) {
- if (gch[i].IsAllocated) {
- gch[i].Free ();
- }
- }
- }
- errorCode = (SocketError)nativeError;
- return(ret);
- }
-
- Exception InvalidAsyncOp (string method)
- {
- return new InvalidOperationException (method + " can only be called once per asynchronous operation");
- }
-
- public
- int EndReceive (IAsyncResult result)
- {
- SocketError error;
- int bytesReceived = EndReceive (result, out error);
- if (error != SocketError.Success) {
- if (error != SocketError.WouldBlock && error != SocketError.InProgress)
- connected = false;
- throw new SocketException ((int)error);
- }
- return bytesReceived;
- }
-
- public
- int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (asyncResult == null)
- throw new ArgumentNullException ("asyncResult");
-
- SocketAsyncResult req = asyncResult as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
-
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndReceive");
- if (!asyncResult.IsCompleted)
- asyncResult.AsyncWaitHandle.WaitOne ();
-
- errorCode = req.ErrorCode;
- // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
- // kinds of exceptions that should be thrown.
- if (errorCode == SocketError.Success)
- req.CheckIfThrowDelayedException();
-
- return(req.Total);
- }
-
- public
- int EndSend (IAsyncResult result)
- {
- SocketError error;
- int bytesSent = EndSend (result, out error);
- if (error != SocketError.Success) {
- if (error != SocketError.WouldBlock && error != SocketError.InProgress)
- connected = false;
- throw new SocketException ((int)error);
- }
- return bytesSent;
- }
-
- public
- int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
- if (asyncResult == null)
- throw new ArgumentNullException ("asyncResult");
-
- SocketAsyncResult req = asyncResult as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "result");
-
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndSend");
- if (!asyncResult.IsCompleted)
- asyncResult.AsyncWaitHandle.WaitOne ();
-
- errorCode = req.ErrorCode;
- // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
- // kinds of exceptions that should be thrown.
- if (errorCode == SocketError.Success)
- req.CheckIfThrowDelayedException ();
-
- return(req.Total);
- }
-
- // Used by Udpclient
- public
- int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
- {
- if (disposed && closed)
- throw new ObjectDisposedException (GetType ().ToString ());
-
- if (result == null)
- throw new ArgumentNullException ("result");
-
- if (end_point == null)
- throw new ArgumentNullException ("remote_end");
-
- SocketAsyncResult req = result as SocketAsyncResult;
- if (req == null)
- throw new ArgumentException ("Invalid IAsyncResult", "result");
-
- if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
- throw InvalidAsyncOp ("EndReceiveFrom");
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne();
-
- req.CheckIfThrowDelayedException();
- end_point = req.EndPoint;
- return req.Total;
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- static extern void socket_pool_queue (SocketAsyncCall d, SocketAsyncResult r);
- }
-}
-
static Dns ()
{
- System.Net.Sockets.Socket.CheckProtocolSupport();
-
#if !MOBILE
if (Environment.GetEnvironmentVariable ("MONO_DNS") != null) {
resolver = new SimpleResolver ();
}
public bool CloseConnectionGroup (string connectionGroupName)
{
+ WebConnectionGroup cncGroup = null;
+
lock (this) {
- WebConnectionGroup cncGroup = GetConnectionGroup (connectionGroupName);
+ cncGroup = GetConnectionGroup (connectionGroupName);
if (cncGroup != null) {
- cncGroup.Close ();
RemoveConnectionGroup (cncGroup);
- return true;
}
}
+ // WebConnectionGroup.Close() must *not* be called inside the lock
+ if (cncGroup != null) {
+ cncGroup.Close ();
+ return true;
+ }
+
return false;
}
public void Close ()
{
+ List<WebConnection> connectionsToClose = null;
+
//TODO: what do we do with the queue? Empty it out and abort the requests?
//TODO: abort requests or wait for them to finish
lock (sPoint) {
var node = iter;
iter = iter.Next;
+ // Closing connections inside the lock leads to a deadlock.
+ if (connectionsToClose == null)
+ connectionsToClose = new List<WebConnection>();
+
+ connectionsToClose.Add (cnc);
connections.Remove (node);
+ }
+ }
+
+ if (connectionsToClose != null) {
+ foreach (var cnc in connectionsToClose) {
cnc.Close (false);
OnConnectionClosed ();
}
System.Net.Sockets/SelectMode.cs
System.Net.Sockets/SendPacketsElement.cs
System.Net.Sockets/Socket.cs
-System.Net.Sockets/Socket_2_1.cs
+System.Net.Sockets/SocketAsyncCallback.cs
System.Net.Sockets/SocketAsyncEventArgs.cs
System.Net.Sockets/SocketAsyncOperation.cs
+System.Net.Sockets/SocketAsyncResult.cs
+System.Net.Sockets/SocketAsyncWorker.cs
System.Net.Sockets/SocketError.cs
System.Net.Sockets/SocketException.cs
System.Net.Sockets/SocketFlags.cs
System.Net.Sockets/SocketInformation.cs
System.Net.Sockets/SocketInformationOptions.cs
+System.Net.Sockets/SocketOperation.cs
System.Net.Sockets/SocketOptionLevel.cs
System.Net.Sockets/SocketOptionName.cs
System.Net.Sockets/SocketShutdown.cs
}
}
+ [Test] // Covers #26363
+ public void GetProcesses_StartTime ()
+ {
+ foreach (var p in Process.GetProcesses ()) {
+ if (!p.HasExited && p.StartTime.Year < 1800)
+ Assert.Fail ("Process should not be started since the 18th century.");
+ }
+ }
+
[Test]
public void PriorityClass_NotStarted ()
{
compressing.Close ();
backing.Close ();
}
+
+ [Test]
+ public void Bug28777_EmptyFlush ()
+ {
+ MemoryStream backing = new MemoryStream ();
+ DeflateStream compressing = new DeflateStream (backing, CompressionLevel.Fastest, true);
+ compressing.Flush ();
+ compressing.Close ();
+ backing.Close ();
+ }
+
+ [Test]
+ public void Bug28777_DoubleFlush ()
+ {
+ byte[] buffer = new byte [4096];
+ MemoryStream backing = new MemoryStream ();
+ DeflateStream compressing = new DeflateStream (backing, CompressionLevel.Fastest, true);
+ compressing.Write (buffer, 0, buffer.Length);
+ compressing.Flush ();
+ compressing.Flush ();
+ compressing.Close ();
+ backing.Close ();
+ }
}
}
EndPoint remoteEP = new IPEndPoint (IPAddress.Loopback, 8001);
try {
- s.ReceiveFrom ((Byte []) null, -1, (SocketFlags) 666,
+ s.ReceiveFrom ((Byte []) null, 0, (SocketFlags) 666,
ref remoteEP);
Assert.Fail ("#1");
} catch (ArgumentNullException ex) {
byte [] buffer = new byte [5];
EndPoint remoteEP = null;
try {
- s.ReceiveFrom (buffer, -1, (SocketFlags) 666, ref remoteEP);
+ s.ReceiveFrom (buffer, buffer.Length, (SocketFlags) 666, ref remoteEP);
Assert.Fail ("#1");
} catch (ArgumentNullException ex) {
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
EndPoint remoteEP = null;
try {
- s.ReceiveFrom (buffer, -1, -1, (SocketFlags) 666, ref remoteEP);
+ s.ReceiveFrom (buffer, 0, buffer.Length, (SocketFlags) 666, ref remoteEP);
Assert.Fail ("#1");
} catch (ArgumentNullException ex) {
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
System.Net.Sockets/SelectMode.cs
System.Net.Sockets/SendPacketsElement.cs
System.Net.Sockets/Socket.cs
+System.Net.Sockets/SocketAsyncCallback.cs
System.Net.Sockets/SocketAsyncEventArgs.cs
System.Net.Sockets/SocketAsyncOperation.cs
+System.Net.Sockets/SocketAsyncResult.cs
+System.Net.Sockets/SocketAsyncWorker.cs
System.Net.Sockets/SocketError.cs
System.Net.Sockets/SocketException.cs
System.Net.Sockets/SocketFlags.cs
System.Net.Sockets/SocketInformation.cs
System.Net.Sockets/SocketInformationOptions.cs
+System.Net.Sockets/SocketOperation.cs
System.Net.Sockets/SocketOptionLevel.cs
System.Net.Sockets/SocketOptionName.cs
System.Net.Sockets/SocketShutdown.cs
System.Net.Sockets/SocketType.cs
-System.Net.Sockets/Socket_2_1.cs
System.Net.Sockets/TcpClient.cs
System.Net.Sockets/TcpListener.cs
System.Net.Sockets/TransmitFileOptions.cs
resources/collation.cjkKO.bin \
resources/collation.cjkKOlv2.bin
-REFERENCE_SOURCES_FLAGS = -d:FEATURE_PAL,GENERICS_WORK,FEATURE_LIST_PREDICATES,FEATURE_SERIALIZATION,FEATURE_ASCII,FEATURE_LATIN1,FEATURE_UTF7,FEATURE_UTF32,MONO_HYBRID_ENCODING_SUPPORT,FEATURE_ASYNC_IO,NEW_EXPERIMENTAL_ASYNC_IO,FEATURE_UTF32,FEATURE_EXCEPTIONDISPATCHINFO,FEATURE_CORRUPTING_EXCEPTIONS,FEATURE_EXCEPTION_NOTIFICATIONS,FEATURE_STRONGNAME_MIGRATION
+REFERENCE_SOURCES_FLAGS = -d:FEATURE_PAL,GENERICS_WORK,FEATURE_LIST_PREDICATES,FEATURE_SERIALIZATION,FEATURE_ASCII,FEATURE_LATIN1,FEATURE_UTF7,FEATURE_UTF32,MONO_HYBRID_ENCODING_SUPPORT,FEATURE_ASYNC_IO,NEW_EXPERIMENTAL_ASYNC_IO,FEATURE_UTF32,FEATURE_EXCEPTIONDISPATCHINFO,FEATURE_CORRUPTING_EXCEPTIONS,FEATURE_EXCEPTION_NOTIFICATIONS,FEATURE_STRONGNAME_MIGRATION,FEATURE_USE_LCID,FEATURE_FUSION
MOBILE_STATIC := $(filter mobile_static monotouch monotouch_runtime, $(PROFILE))
ifndef MOBILE_STATIC
-REFERENCE_SOURCES_FLAGS += -d:FEATURE_REMOTING,MONO_COM,FEATURE_USE_LCID
+REFERENCE_SOURCES_FLAGS += -d:FEATURE_REMOTING,MONO_COM
endif
LOCAL_MCS_FLAGS = -unsafe -nostdlib -nowarn:612,618 -d:INSIDE_CORLIB,MONO_CULTURE_DATA -d:LIBC $(REFERENCE_SOURCES_FLAGS)
--- /dev/null
+namespace System
+{
+ partial class Buffer
+ {
+ public static int ByteLength (Array array)
+ {
+ // note: the other methods in this class also use ByteLength to test for
+ // null and non-primitive arguments as a side-effect.
+
+ if (array == null)
+ throw new ArgumentNullException ("array");
+
+ int length = _ByteLength (array);
+ if (length < 0)
+ throw new ArgumentException (Locale.GetText ("Object must be an array of primitives."));
+
+ return length;
+ }
+
+ public static byte GetByte (Array array, int index)
+ {
+ if (index < 0 || index >= ByteLength (array))
+ throw new ArgumentOutOfRangeException ("index");
+
+ return _GetByte (array, index);
+ }
+
+ public static void SetByte (Array array, int index, byte value)
+ {
+ if (index < 0 || index >= ByteLength (array))
+ throw new ArgumentOutOfRangeException ("index");
+
+ _SetByte (array, index, value);
+ }
+
+ public static void BlockCopy (Array src, int srcOffset, Array dst, int dstOffset, int count)
+ {
+ if (src == null)
+ throw new ArgumentNullException ("src");
+
+ if (dst == null)
+ throw new ArgumentNullException ("dst");
+
+ if (srcOffset < 0)
+ throw new ArgumentOutOfRangeException ("srcOffset", Locale.GetText(
+ "Non-negative number required."));
+
+ if (dstOffset < 0)
+ throw new ArgumentOutOfRangeException ("dstOffset", Locale.GetText (
+ "Non-negative number required."));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", Locale.GetText (
+ "Non-negative number required."));
+
+ // We do the checks in unmanaged code for performance reasons
+ bool res = InternalBlockCopy (src, srcOffset, dst, dstOffset, count);
+ if (!res) {
+ // watch for integer overflow
+ if ((srcOffset > ByteLength (src) - count) || (dstOffset > ByteLength (dst) - count))
+ throw new ArgumentException (Locale.GetText (
+ "Offset and length were out of bounds for the array or count is greater than " +
+ "the number of elements from index to the end of the source collection."));
+ }
+ }
+
+ internal static unsafe void memcpy4 (byte *dest, byte *src, int size) {
+ /*while (size >= 32) {
+ // using long is better than int and slower than double
+ // FIXME: enable this only on correct alignment or on platforms
+ // that can tolerate unaligned reads/writes of doubles
+ ((double*)dest) [0] = ((double*)src) [0];
+ ((double*)dest) [1] = ((double*)src) [1];
+ ((double*)dest) [2] = ((double*)src) [2];
+ ((double*)dest) [3] = ((double*)src) [3];
+ dest += 32;
+ src += 32;
+ size -= 32;
+ }*/
+ while (size >= 16) {
+ ((int*)dest) [0] = ((int*)src) [0];
+ ((int*)dest) [1] = ((int*)src) [1];
+ ((int*)dest) [2] = ((int*)src) [2];
+ ((int*)dest) [3] = ((int*)src) [3];
+ dest += 16;
+ src += 16;
+ size -= 16;
+ }
+ while (size >= 4) {
+ ((int*)dest) [0] = ((int*)src) [0];
+ dest += 4;
+ src += 4;
+ size -= 4;
+ }
+ while (size > 0) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ dest += 1;
+ src += 1;
+ --size;
+ }
+ }
+ internal static unsafe void memcpy2 (byte *dest, byte *src, int size) {
+ while (size >= 8) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ ((short*)dest) [1] = ((short*)src) [1];
+ ((short*)dest) [2] = ((short*)src) [2];
+ ((short*)dest) [3] = ((short*)src) [3];
+ dest += 8;
+ src += 8;
+ size -= 8;
+ }
+ while (size >= 2) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ dest += 2;
+ src += 2;
+ size -= 2;
+ }
+ if (size > 0)
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ }
+ static unsafe void memcpy1 (byte *dest, byte *src, int size) {
+ while (size >= 8) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ ((byte*)dest) [1] = ((byte*)src) [1];
+ ((byte*)dest) [2] = ((byte*)src) [2];
+ ((byte*)dest) [3] = ((byte*)src) [3];
+ ((byte*)dest) [4] = ((byte*)src) [4];
+ ((byte*)dest) [5] = ((byte*)src) [5];
+ ((byte*)dest) [6] = ((byte*)src) [6];
+ ((byte*)dest) [7] = ((byte*)src) [7];
+ dest += 8;
+ src += 8;
+ size -= 8;
+ }
+ while (size >= 2) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ ((byte*)dest) [1] = ((byte*)src) [1];
+ dest += 2;
+ src += 2;
+ size -= 2;
+ }
+ if (size > 0)
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ }
+
+ internal static unsafe void Memcpy (byte *dest, byte *src, int size) {
+ // FIXME: if pointers are not aligned, try to align them
+ // so a faster routine can be used. Handle the case where
+ // the pointers can't be reduced to have the same alignment
+ // (just ignore the issue on x86?)
+ if ((((int)dest | (int)src) & 3) != 0) {
+ if (((int)dest & 1) != 0 && ((int)src & 1) != 0 && size >= 1) {
+ dest [0] = src [0];
+ ++dest;
+ ++src;
+ --size;
+ }
+ if (((int)dest & 2) != 0 && ((int)src & 2) != 0 && size >= 2) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ dest += 2;
+ src += 2;
+ size -= 2;
+ }
+ if ((((int)dest | (int)src) & 1) != 0) {
+ memcpy1 (dest, src, size);
+ return;
+ }
+ if ((((int)dest | (int)src) & 2) != 0) {
+ memcpy2 (dest, src, size);
+ return;
+ }
+ }
+ memcpy4 (dest, src, size);
+ }
+ }
+}
\ No newline at end of file
int numberIndex;
+ int iDefaultAnsiCodePage;
+ int iDefaultOemCodePage;
+ int iDefaultMacCodePage;
+ int iDefaultEbcdicCodePage;
+ bool isRightToLeft;
+ string sListSeparator;
+
private CultureData (string name)
{
this.sRealName = name;
// Store for specific data about each calendar
invariant.calendars = new CalendarData[CalendarData.MAX_CALENDARS];
invariant.calendars[0] = CalendarData.Invariant;
+
+ invariant.iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP)
+ invariant.iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM)
+ invariant.iDefaultMacCodePage = 10000; // default macintosh code page
+ invariant.iDefaultEbcdicCodePage = 037; // default EBCDIC code page
+
+ invariant.sListSeparator = ",";
Interlocked.CompareExchange (ref s_Invariant, invariant, null);
}
}
}
- public static CultureData GetCultureData (string cultureName, bool useUserOverride, int datetimeIndex, int calendarId, int numberIndex, string iso2lang)
+ public static CultureData GetCultureData (string cultureName, bool useUserOverride, int datetimeIndex, int calendarId, int numberIndex, string iso2lang,
+ int ansiCodePage, int oemCodePage, int macCodePage, int ebcdicCodePage, bool rightToLeft, string listSeparator)
{
if (string.IsNullOrEmpty (cultureName))
return Invariant;
cd.calendarId = calendarId;
cd.numberIndex = numberIndex;
cd.sISO639Language = iso2lang;
+ cd.iDefaultAnsiCodePage = ansiCodePage;
+ cd.iDefaultOemCodePage = oemCodePage;
+ cd.iDefaultMacCodePage = macCodePage;
+ cd.iDefaultEbcdicCodePage = ebcdicCodePage;
+ cd.isRightToLeft = rightToLeft;
+ cd.sListSeparator = listSeparator;
return cd;
}
}
}
- internal String SCOMPAREINFO {
- get {
- return "";
+ internal String SCOMPAREINFO {
+ get {
+ return "";
+ }
+ }
+
+ internal String STEXTINFO {
+ get {
+ return sRealName;
+ }
}
- }
internal int ILANGUAGE {
get {
}
}
+ internal int IDEFAULTANSICODEPAGE {
+ get {
+ return iDefaultAnsiCodePage;
+ }
+ }
+
+ internal int IDEFAULTOEMCODEPAGE {
+ get {
+ return iDefaultOemCodePage;
+ }
+ }
+
+ internal int IDEFAULTMACCODEPAGE {
+ get {
+ return iDefaultMacCodePage;
+ }
+ }
+
+ internal int IDEFAULTEBCDICCODEPAGE {
+ get {
+ return iDefaultEbcdicCodePage;
+ }
+ }
+
+ internal bool IsRightToLeft {
+ get {
+ return isRightToLeft;
+ }
+ }
+
+ internal String SLIST {
+ get {
+ return sListSeparator;
+ }
+ }
+
#region from reference sources
// Are overrides enabled?
default: return codePage.ToString (CultureInfo.InvariantCulture);
}
}
+
+ internal static bool IsWindows8OrAbove {
+ get {
+ return false;
+ }
+ }
}
}
\ No newline at end of file
{
static internal T UnsafeCast<T>(Object o) where T : class
{
- return (T)o;
+ return Array.UnsafeMov<object, T> (o);
+ }
+
+ static internal int UnsafeEnumCast<T>(T val) where T : struct
+ {
+ return Array.UnsafeMov<T, int> (val);
+ }
+
+ static internal long UnsafeEnumCastLong<T>(T val) where T : struct
+ {
+ throw new NotImplementedException ();
}
}
}
\ No newline at end of file
}
}
+ // Value from which a new base 16 digit can cause an overflow.
+ const ulong base16MaxOverflowFreeValue = ulong.MaxValue / (16 * 16);
+
+ // From ulong we can only cast to positive long.
+ // As |long.MinValue| > |long.MaxValue| we need to do this to avoid an overflow.
+ const ulong longMinValue = ((ulong) long.MaxValue) + (ulong) -(long.MinValue + long.MaxValue);
+
public unsafe static long StringToLong (string value, int fromBase, int flags, int* parsePos)
{
if ((flags & (IsTight | NoSpace)) == 0)
return 0;
int chars = 0;
- int digitValue = -1;
- long result = 0;
+ ulong fromBaseULong = (ulong) fromBase;
+ ulong digitValue = 0;
+ ulong result = 0;
int len = value.Length;
bool negative = false;
+ bool treatAsUnsigned = (flags & ParseNumbers.TreatAsUnsigned) != 0;
if (len == 0) {
// Mimic broken .net behaviour
if (fromBase != 10)
throw new ArgumentException ("String cannot contain a minus sign if the base is not 10.");
- if ((flags & TreatAsUnsigned) != 0)
+ if (treatAsUnsigned)
throw new OverflowException ("Negative number");
negative = true;
while (i < len) {
char c = value[i];
if (Char.IsNumber (c)) {
- digitValue = c - '0';
+ digitValue = (ulong) (c - '0');
} else if (Char.IsLetter (c)) {
- digitValue = Char.ToLowerInvariant (c) - 'a' + 10;
+ digitValue = (ulong) (Char.ToLowerInvariant (c) - 'a' + 10);
} else {
if (i == 0)
throw new FormatException ("Could not find any parsable digits.");
break;
}
- if (digitValue >= fromBase) {
+ if (digitValue >= fromBaseULong) {
if (chars > 0) {
throw new FormatException ("Additional unparsable "
+ "characters are at the end of the string.");
}
}
- result = fromBase * result + digitValue;
+ if (result <= base16MaxOverflowFreeValue) {
+ result = result * (ulong) fromBaseULong + digitValue;
+ } else {
+ // decompose 64 bit operation into 32 bit operations so we can check for overflows
+ ulong a = (result >> 32) * fromBaseULong;
+ ulong b = (result & uint.MaxValue) * fromBaseULong + digitValue;
+ if (((b >> 32) + a) > uint.MaxValue)
+ throw new OverflowException ();
+
+ result = (a << 32) + b;
+ }
+
chars++;
++i;
}
if (parsePos != null)
*parsePos = i;
- return negative ? -result : result;
+ if (treatAsUnsigned)
+ return (long) result;
+
+ if (!negative) {
+ if (fromBase == 10 && result > ((ulong) long.MaxValue))
+ throw new OverflowException ();
+
+ return (long)result;
+ }
+
+ if (result <= (ulong) long.MaxValue)
+ return -((long) result);
+
+ if (result > longMinValue)
+ throw new OverflowException ();
+
+ // Avoids overflow of -result when result > long.MaxValue
+ return long.MinValue + (long) (longMinValue - result);
}
public static string IntToString (int value, int toBase, int width, char paddingChar, int flags)
return constraints;
}
- public override Type MakeGenericType (params Type[] typeArguments)
+ internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
{
- if (IsUserType)
- throw new NotSupportedException ();
- if (!IsGenericTypeDefinition)
- throw new InvalidOperationException ("not a generic type definition");
- if (typeArguments == null)
- throw new ArgumentNullException ("typeArguments");
- if (GetGenericArguments().Length != typeArguments.Length)
- throw new ArgumentException (String.Format ("The type or method has {0} generic parameter(s) but {1} generic argument(s) where provided. A generic argument must be provided for each generic parameter.", GetGenericArguments ().Length, typeArguments.Length), "typeArguments");
-
- bool hasUserType = false;
-
- Type[] systemTypes = new Type[typeArguments.Length];
- for (int i = 0; i < typeArguments.Length; ++i) {
- Type t = typeArguments [i];
- if (t == null)
- throw new ArgumentNullException ("typeArguments");
-
- if (!(t is MonoType))
- hasUserType = true;
- systemTypes [i] = t;
- }
-
- if (hasUserType) {
-#if FULL_AOT_RUNTIME
- throw new NotSupportedException ("User types are not supported under full aot");
-#else
- return new MonoGenericClass (this, typeArguments);
-#endif
- }
-
- Type res = MakeGenericType (this, systemTypes);
- if (res == null)
- throw new TypeLoadException ();
- return res;
+ var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
+ var ctor = gt.GetDefaultConstructor ();
+ return ctor.InternalInvoke (null, null);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern string getFullName(bool full_name, bool assembly_qualified);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- public extern override Type [] GetGenericArguments ();
+ extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern GenericParameterAttributes GetGenericParameterAttributes ();
{
Buffer.Memcpy (dest, src, size);
}
+
+ /* Used by the runtime */
+ internal static unsafe void bzero (byte *dest, int len) {
+ memset (dest, 0, len);
+ }
+
+ internal static unsafe void bzero_aligned_1 (byte *dest, int len) {
+ ((byte*)dest) [0] = 0;
+ }
+
+ internal static unsafe void bzero_aligned_2 (byte *dest, int len) {
+ ((short*)dest) [0] = 0;
+ }
+
+ internal static unsafe void bzero_aligned_4 (byte *dest, int len) {
+ ((int*)dest) [0] = 0;
+ }
+
+ internal static unsafe void bzero_aligned_8 (byte *dest, int len) {
+ ((long*)dest) [0] = 0;
+ }
+
+ internal static unsafe void memcpy_aligned_1 (byte *dest, byte *src, int size) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ }
+
+ internal static unsafe void memcpy_aligned_2 (byte *dest, byte *src, int size) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ }
+
+ internal static unsafe void memcpy_aligned_4 (byte *dest, byte *src, int size) {
+ ((int*)dest) [0] = ((int*)src) [0];
+ }
+
+ internal static unsafe void memcpy_aligned_8 (byte *dest, byte *src, int size) {
+ ((long*)dest) [0] = ((long*)src) [0];
+ }
+
#endregion
// Certain constructors are redirected to CreateString methods with
--- /dev/null
+using System.Runtime.CompilerServices;
+
+namespace System.Globalization
+{
+ partial class TextInfo
+ {
+ unsafe static ushort *to_lower_data_low;
+ unsafe static ushort *to_lower_data_high;
+ unsafe static ushort *to_upper_data_low;
+ unsafe static ushort *to_upper_data_high;
+
+ [MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ unsafe static extern void GetDataTablePointersLite (out ushort *to_lower_data_low, out ushort *to_lower_data_high, out ushort *to_upper_data_low, out ushort *to_upper_data_high);
+
+ static readonly object cookie = new object ();
+
+ unsafe static void ReadDataTable ()
+ {
+ if (to_lower_data_low == null) {
+ lock (cookie) {
+ if (to_lower_data_low != null)
+ return;
+
+ GetDataTablePointersLite (out to_lower_data_low, out to_lower_data_high, out to_upper_data_low, out to_upper_data_high);
+ }
+ }
+ }
+
+ unsafe string ToUpperInternal (string str)
+ {
+ if (str.Length == 0)
+ return String.Empty;
+
+ string tmp = String.FastAllocateString (str.Length);
+ fixed (char* source = str, dest = tmp) {
+
+ char* destPtr = (char*)dest;
+ char* sourcePtr = (char*)source;
+
+ for (int n = 0; n < str.Length; n++) {
+ *destPtr = ToUpper (*sourcePtr);
+ sourcePtr++;
+ destPtr++;
+ }
+ }
+ return tmp;
+ }
+
+ unsafe string ToLowerInternal (string str)
+ {
+ if (str.Length == 0)
+ return String.Empty;
+
+ string tmp = String.FastAllocateString (str.Length);
+ fixed (char* source = str, dest = tmp) {
+
+ char* destPtr = (char*)dest;
+ char* sourcePtr = (char*)source;
+
+ for (int n = 0; n < str.Length; n++) {
+ *destPtr = ToLower (*sourcePtr);
+ sourcePtr++;
+ destPtr++;
+ }
+ }
+ return tmp;
+ }
+
+ char ToUpperInternal (char c)
+ {
+ switch (c) {
+ case '\u0069': // Latin lowercase i
+ if (!IsAsciiCasingSameAsInvariant)
+ return '\u0130'; // dotted capital I
+ break;
+ case '\u0131': // dotless i
+ return '\u0049'; // I
+
+ case '\u01c5': // see ToLower()
+ return '\u01c4';
+ case '\u01c8': // see ToLower()
+ return '\u01c7';
+ case '\u01cb': // see ToLower()
+ return '\u01ca';
+ case '\u01f2': // see ToLower()
+ return '\u01f1';
+ case '\u0390': // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+ return '\u03aa'; // it is not in ICU
+ case '\u03b0': // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+ return '\u03ab'; // it is not in ICU
+ case '\u03d0': // GREEK BETA
+ return '\u0392';
+ case '\u03d1': // GREEK THETA
+ return '\u0398';
+ case '\u03d5': // GREEK PHI
+ return '\u03a6';
+ case '\u03d6': // GREEK PI
+ return '\u03a0';
+ case '\u03f0': // GREEK KAPPA
+ return '\u039a';
+ case '\u03f1': // GREEK RHO
+ return '\u03a1';
+ // am not sure why miscellaneous GREEK symbols are
+ // not handled here.
+ }
+
+ return ToUpperInvariant (c);
+ }
+
+ char ToLowerInternal (char c)
+ {
+ switch (c) {
+ case '\u0049': // Latin uppercase I
+ if (!IsAsciiCasingSameAsInvariant)
+ return '\u0131'; // I becomes dotless i
+ break;
+ case '\u0130': // I-dotted
+ return '\u0069'; // i
+
+ case '\u01c5': // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+ return '\u01c6';
+ // \u01c7 -> \u01c9 (LJ) : invariant
+ case '\u01c8': // LATIN CAPITAL LETTER L WITH SMALL LETTER J
+ return '\u01c9';
+ // \u01ca -> \u01cc (NJ) : invariant
+ case '\u01cb': // LATIN CAPITAL LETTER N WITH SMALL LETTER J
+ return '\u01cc';
+ // WITH CARON : invariant
+ // WITH DIAERESIS AND * : invariant
+
+ case '\u01f2': // LATIN CAPITAL LETTER D WITH SMALL LETTER Z
+ return '\u01f3';
+ case '\u03d2': // ? it is not in ICU
+ return '\u03c5';
+ case '\u03d3': // ? it is not in ICU
+ return '\u03cd';
+ case '\u03d4': // ? it is not in ICU
+ return '\u03cb';
+ }
+ return ToLowerInvariant (c);
+ }
+
+ static char ToLowerInvariant (char c)
+ {
+ ReadDataTable ();
+
+ unsafe {
+ if (c <= ((char)0x24cf))
+ return (char) to_lower_data_low [c];
+ if (c >= ((char)0xff21))
+ return (char) to_lower_data_high[c - 0xff21];
+ }
+ return c;
+ }
+
+ static char ToUpperInvariant (char c)
+ {
+ ReadDataTable ();
+
+ unsafe {
+ if (c <= ((char)0x24e9))
+ return (char) to_upper_data_low [c];
+ if (c >= ((char)0xff21))
+ return (char) to_upper_data_high [c - 0xff21];
+ }
+ return c;
+ }
+
+ static unsafe int InternalCompareStringOrdinalIgnoreCase (String strA, int indexA, String strB, int indexB, int lenA, int lenB)
+ {
+ if (strA == null) {
+ return strB == null ? 0 : -1;
+ }
+ if (strB == null) {
+ return 1;
+ }
+ int lengthA = Math.Min (lenA, strA.Length - indexA);
+ int lengthB = Math.Min (lenB, strB.Length - indexB);
+
+ if (lengthA == lengthB && Object.ReferenceEquals (strA, strB))
+ return 0;
+
+ fixed (char* aptr = strA, bptr = strB) {
+ char* ap = aptr + indexA;
+ char* end = ap + Math.Min (lengthA, lengthB);
+ char* bp = bptr + indexB;
+ while (ap < end) {
+ if (*ap != *bp) {
+ char c1 = Char.ToUpperInvariant (*ap);
+ char c2 = Char.ToUpperInvariant (*bp);
+ if (c1 != c2)
+ return c1 - c2;
+ }
+ ap++;
+ bp++;
+ }
+ return lengthA - lengthB;
+ }
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-namespace System
-{
- [Flags]
- internal enum TimeZoneInfoOptions {
- None = 1,
- NoThrowOnInvalidTime = 2
- };
-}
\ No newline at end of file
--- /dev/null
+namespace System.Reflection.Emit
+{
+ abstract class TypeBuilderInstantiation : TypeInfo
+ {
+ internal static Type MakeGenericType (Type type, Type[] typeArguments)
+ {
+#if FULL_AOT_RUNTIME
+ throw new NotSupportedException ("User types are not supported under full aot");
+#else
+ return new MonoGenericClass (type, typeArguments);
+#endif
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-//
-// Comparer.cs
-//
-// Authors:
-// Ben Maurer (bmaurer@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
-//
-// 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.
-//
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace System.Collections.Generic {
- [Serializable]
- public abstract class Comparer<T> : IComparer<T>, IComparer
- {
- static readonly Comparer <T> _default = typeof (IComparable<T>).IsAssignableFrom (typeof (T)) ?
- (Comparer<T>) Activator.CreateInstance (typeof (GenericComparer <>).MakeGenericType (typeof (T))) :
- new DefaultComparer ();
-
- public abstract int Compare (T x, T y);
-
- public static Comparer<T> Default {
- get {
- return _default;
- }
- }
-
- public static Comparer<T> Create (Comparison<T> comparison)
- {
- if (comparison == null)
- throw new ArgumentNullException ("comparison");
-
- return new ComparisonComparer<T> (comparison);
- }
-
- int IComparer.Compare (object x, object y)
- {
- if (x == y)
- return 0;
- if (x == null)
- return y == null ? 0 : -1;
- if (y == null)
- return 1;
-
- if (x is T && y is T)
- return Compare ((T) x, (T) y);
-
- throw new ArgumentException ();
- }
-
- [Serializable]
- sealed class DefaultComparer : Comparer<T>
- {
- public override int Compare (T x, T y)
- {
- // `null' is less than any other ref type
- if (x == null)
- return y == null ? 0 : -1;
- if (y == null)
- return 1;
-
- var i = x as IComparable;
- if (i != null)
- return i.CompareTo (y);
-
- i = y as IComparable;
- if (i != null)
- return -i.CompareTo (x);
-
- throw new ArgumentException ("At least one argument has to implement IComparable interface");
- }
- }
- }
-
- [Serializable]
- sealed class GenericComparer<T> : Comparer<T> where T : IComparable<T>
- {
- public override int Compare (T x, T y)
- {
- // `null' is less than any other ref type
- if (x == null)
- return y == null ? 0 : -1;
- if (y == null)
- return 1;
-
- return x.CompareTo (y);
- }
- }
- [Serializable]
- sealed class ComparisonComparer<T> : Comparer<T>
- {
- readonly Comparison<T> comparison;
-
- public ComparisonComparer (Comparison<T> comparison)
- {
- this.comparison = comparison;
- }
-
- public override int Compare (T x, T y)
- {
- return comparison (x, y);
- }
- }
-}
+++ /dev/null
-//
-// EqualityComparer.cs
-//
-// Authors:
-// Ben Maurer (bmaurer@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
-//
-// 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.
-//
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace System.Collections.Generic {
- [Serializable]
- public abstract class EqualityComparer <T> : IEqualityComparer, IEqualityComparer <T> {
-
- static EqualityComparer ()
- {
- var t = typeof (T);
- if (t == typeof (string)) {
- _default = (EqualityComparer<T>) (object) new InternalStringComparer ();
- return;
- }
-
- if (t == typeof (int)) {
- _default = (EqualityComparer<T>) (object) new IntEqualityComparer ();
- return;
- }
-
- if (t.IsEnum && Enum.GetUnderlyingType (t) == typeof (int)) {
- _default = new EnumIntEqualityComparer<T> ();
- return;
- }
-
- if (typeof (IEquatable <T>).IsAssignableFrom (t))
- _default = (EqualityComparer <T>) Activator.CreateInstance (typeof (GenericEqualityComparer <>).MakeGenericType (t));
- else
- _default = new DefaultComparer<T> ();
- }
-
- public abstract int GetHashCode (T obj);
- public abstract bool Equals (T x, T y);
-
- static readonly EqualityComparer <T> _default;
-
- public static EqualityComparer <T> Default {
- get {
- return _default;
- }
- }
-
- int IEqualityComparer.GetHashCode (object obj)
- {
- if (obj == null)
- return 0;
-
- if (!(obj is T))
- throw new ArgumentException ("Argument is not compatible", "obj");
-
- return GetHashCode ((T)obj);
- }
-
- bool IEqualityComparer.Equals (object x, object y)
- {
- if (x == y)
- return true;
-
- if (x == null || y == null)
- return false;
-
- if (!(x is T))
- throw new ArgumentException ("Argument is not compatible", "x");
- if (!(y is T))
- throw new ArgumentException ("Argument is not compatible", "y");
- return Equals ((T)x, (T)y);
- }
-
- internal virtual int IndexOf (T[] array, T value, int startIndex, int endIndex)
- {
- for (int i = startIndex; i < endIndex; ++i) {
- if (Equals (Array.UnsafeLoad (array, i), value))
- return i;
- }
-
- return -1;
- }
- }
-
- [Serializable]
- sealed class DefaultComparer<T> : EqualityComparer<T> {
-
- public override int GetHashCode (T obj)
- {
- if (obj == null)
- return 0;
- return obj.GetHashCode ();
- }
-
- public override bool Equals (T x, T y)
- {
- if (x == null)
- return y == null;
-
- return x.Equals (y);
- }
- }
-
- [Serializable]
- sealed class InternalStringComparer : EqualityComparer<string> {
-
- public override int GetHashCode (string obj)
- {
- if (obj == null)
- return 0;
- return obj.GetHashCode ();
- }
-
- public override bool Equals (string x, string y)
- {
- if (x == null)
- return y == null;
-
- if ((object) x == (object) y)
- return true;
-
- return x.Equals (y);
- }
-
- internal override int IndexOf (string[] array, string value, int startIndex, int endIndex)
- {
- for (int i = startIndex; i < endIndex; ++i) {
- if (Array.UnsafeLoad (array, i) == value)
- return i;
- }
-
- return -1;
- }
- }
-
- [Serializable]
- sealed class IntEqualityComparer : EqualityComparer<int>
- {
- public override int GetHashCode (int obj)
- {
- return obj;
- }
-
- public override bool Equals (int x, int y)
- {
- return x == y;
- }
-
- internal override int IndexOf (int[] array, int value, int startIndex, int endIndex)
- {
- for (int i = startIndex; i < endIndex; ++i) {
- if (Array.UnsafeLoad (array, i) == value)
- return i;
- }
-
- return -1;
- }
- }
-
- [Serializable]
- sealed class EnumIntEqualityComparer<T> : EqualityComparer<T>
- {
- public override int GetHashCode (T obj)
- {
- return Array.UnsafeMov<T, int> (obj);
- }
-
- public override bool Equals (T x, T y)
- {
- return Array.UnsafeMov<T, int> (x) == Array.UnsafeMov<T, int> (y);
- }
-
- internal override int IndexOf (T[] array, T value, int startIndex, int endIndex)
- {
- int v = Array.UnsafeMov<T, int> (value);
- var a = Array.UnsafeMov<T[], int[]> (array);
- for (int i = startIndex; i < endIndex; ++i) {
- if (Array.UnsafeLoad (a, i) == v)
- return i;
- }
-
- return -1;
- }
- }
-
- [Serializable]
- sealed class GenericEqualityComparer <T> : EqualityComparer <T> where T : IEquatable <T> {
-
- public override int GetHashCode (T obj)
- {
- if (obj == null)
- return 0;
- return obj.GetHashCode ();
- }
-
- public override bool Equals (T x, T y)
- {
- if (x == null)
- return y == null;
-
- return x.Equals (y);
- }
- }
-}
+++ /dev/null
-/CodePageDataItem.cs -crlf
+++ /dev/null
-// ::MONO
-//
-// System.Globalization.CalendarAlgorithmType.cs
-//
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-
-namespace System.Globalization
-{
- [System.Runtime.InteropServices.ComVisible(true)]
- public enum CalendarAlgorithmType
- {
- Unknown = 0,
- SolarCalendar = 1,
- LunarCalendar = 2,
- LunisolarCalendar = 3,
- }
-
-}
+++ /dev/null
-// ::MONO
-//
-// System.Globalization.CalendarWeekRule.cs
-//
-// Copyright (C) Wictor Wilén 2001 (wictor@iBizkit.se)
-//
-// Contributors: Wictor Wilén
-//
-// Revisions
-// 2001-09-14: First draft
-// 2001-09-15: First release
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-
-namespace System.Globalization
-{
- /// <summary>
- /// The System.Globalization.CalendarWeekRule enumeration
- /// </summary>
- [System.Runtime.InteropServices.ComVisible(true)]
- [System.Serializable]
- public enum CalendarWeekRule
- {
- FirstDay = 0,
- FirstFullWeek = 1,
- FirstFourDayWeek = 2
-
- }
-
-}
[NonSerialized]
private unsafe readonly void *textinfo_data;
+ [StructLayout (LayoutKind.Sequential)]
+ struct Data {
+ public int ansi;
+ public int ebcdic;
+ public int mac;
+ public int oem;
+ public bool right_to_left;
+ public byte list_sep;
+ }
+
int m_dataItem; // MS.NET serializes this.
#pragma warning restore 169, 649
// The runtime returns a NULL in the first position of the array when
// 'neutral' is true. We fill it in with a clone of InvariantCulture
// since it must not be read-only
+ int i = 0;
if (neutral && infos.Length > 0 && infos [0] == null) {
- infos [0] = (CultureInfo) InvariantCulture.Clone ();
+ infos [i++] = (CultureInfo) InvariantCulture.Clone ();
}
- for (int i = 1; i < infos.Length; ++i) {
+ for (; i < infos.Length; ++i) {
var ci = infos [i];
- infos [i].m_cultureData = CultureData.GetCultureData (ci.m_name, false, ci.datetime_index, ci.CalendarType, ci.number_index, ci.iso2lang);
+ var ti = ci.GetTextInfoData ();
+ infos [i].m_cultureData = CultureData.GetCultureData (ci.m_name, false, ci.datetime_index, ci.CalendarType, ci.number_index, ci.iso2lang,
+ ti.ansi, ti.oem, ti.mac, ti.ebcdic, ti.right_to_left, ((char)ti.list_sep).ToString ());
}
return infos;
}
+ unsafe Data GetTextInfoData ()
+ {
+ return *(Data*) textinfo_data;
+ }
+
public override int GetHashCode ()
{
return cultureID.GetHashCode ();
private unsafe TextInfo CreateTextInfo (bool readOnly)
{
- return new TextInfo (this, cultureID, this.textinfo_data, readOnly);
+ TextInfo tempTextInfo = new TextInfo (this.m_cultureData);
+ tempTextInfo.SetReadOnlyState (readOnly);
+ return tempTextInfo;
}
public CultureInfo (int culture) : this (culture, true) {}
if (culture == InvariantCultureId) {
/* Short circuit the invariant culture */
- ConstructInvariant (read_only);
m_cultureData = CultureData.Invariant;
+ ConstructInvariant (read_only);
return;
}
throw new CultureNotFoundException ("culture", msg);
}
- m_cultureData = CultureData.GetCultureData (m_name, m_useUserOverride, datetime_index, CalendarType, number_index, iso2lang);
+ var ti = GetTextInfoData ();
+ m_cultureData = CultureData.GetCultureData (m_name, m_useUserOverride, datetime_index, CalendarType, number_index, iso2lang,
+ ti.ansi, ti.oem, ti.mac, ti.ebcdic, ti.right_to_left, ((char)ti.list_sep).ToString ());
}
public CultureInfo (string name) : this (name, true) {}
if (name.Length == 0) {
/* Short circuit the invariant culture */
- ConstructInvariant (read_only);
m_cultureData = CultureData.Invariant;
+ ConstructInvariant (read_only);
return;
}
throw CreateNotFoundException (name);
}
- m_cultureData = CultureData.GetCultureData (m_name, useUserOverride, datetime_index, CalendarType, number_index, iso2lang);
+ var ti = GetTextInfoData ();
+ m_cultureData = CultureData.GetCultureData (m_name, useUserOverride, datetime_index, CalendarType, number_index, iso2lang,
+ ti.ansi, ti.oem, ti.mac, ti.ebcdic, ti.right_to_left, ((char)ti.list_sep).ToString ());
}
// This is used when creating by specific name and creating by
if (ci.IsNeutralCulture)
ci = CreateSpecificCultureFromNeutral (ci.Name);
- ci.m_cultureData = CultureData.GetCultureData (ci.m_name, false, ci.datetime_index, ci.CalendarType, ci.number_index, ci.iso2lang);
+ var ti = ci.GetTextInfoData ();
+
+ ci.m_cultureData = CultureData.GetCultureData (ci.m_name, false, ci.datetime_index, ci.CalendarType, ci.number_index, ci.iso2lang,
+ ti.ansi, ti.oem, ti.mac, ti.ebcdic, ti.right_to_left, ((char)ti.list_sep).ToString ());
return ci;
}
+++ /dev/null
-// DateTimeStyles.cs
-//
-// This code was automatically generated from
-// ECMA CLI XML Library Specification.
-// Generator: libgen.xsl [1.0; (C) Sergey Chaban (serge@wildwestsoftware.com)]
-// Created: Fri, 7 Sep 2001 16:32:07 UTC
-// Source file: AllTypes.xml
-// URL: http://msdn.microsoft.com/net/ecma/AllTypes.xml
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-
-namespace System.Globalization {
-
- [Flags]
- [Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
- public enum DateTimeStyles {
- None = 0x00000000,
- AllowLeadingWhite = 0x00000001,
- AllowTrailingWhite = 0x00000002,
- AllowInnerWhite = 0x00000004,
- AllowWhiteSpaces = AllowLeadingWhite | AllowTrailingWhite | AllowInnerWhite,
- NoCurrentDateDefault = 0x00000008,
- AdjustToUniversal = 0x00000010,
- AssumeLocal = 0x00000020,
- AssumeUniversal = 0x00000040,
- RoundtripKind = 0x00000080,
- } // DateTimeStyles
-
-} // System.Globalization
+++ /dev/null
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System.Globalization {
-
- [System.Runtime.InteropServices.ComVisible(true)]
- [Serializable]
- public enum DigitShapes {
- Context = 0,
- None = 1,
- NativeNational = 2
- }
-}
+++ /dev/null
-// GregorianCalendarTypes.cs
-//
-// This code was automatically generated from
-// ECMA CLI XML Library Specification.
-// Generator: libgen.xsl [1.0; (C) Sergey Chaban (serge@wildwestsoftware.com)]
-// Created: Wed, 5 Sep 2001 06:35:19 UTC
-// Source file: all.xml
-// URL: http://devresource.hp.com/devresource/Docs/TechPapers/CSharp/all.xml
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-
-namespace System.Globalization {
-
-
- [System.Runtime.InteropServices.ComVisible(true)]
- [System.Serializable]
- public enum GregorianCalendarTypes {
-
- /// <summary>
- /// </summary>
- Localized = 1,
-
- /// <summary>
- /// </summary>
- USEnglish = 2,
-
- /// <summary>
- /// </summary>
- MiddleEastFrench = 9,
-
- /// <summary>
- /// </summary>
- Arabic = 10,
-
- /// <summary>
- /// </summary>
- TransliteratedEnglish = 11,
-
- /// <summary>
- /// </summary>
- TransliteratedFrench = 12,
- } // GregorianCalendarTypes
-
-} // System.Globalization
+++ /dev/null
-//
-// System.Globalization.TextInfo.cs
-//
-// Authors:
-// Dick Porter (dick@ximian.com)
-// Duncan Mak (duncan@ximian.com)
-// Atsushi Enomoto (atsushi@ximian.com)
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2002 Ximian, Inc.
-// (C) 2005 Novell, Inc.
-//
-// TODO:
-// Missing the various code page mappings.
-// Missing the OnDeserialization implementation.
-//
-// Copyright (C) 2004, 2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Diagnostics.Contracts;
-
-namespace System.Globalization {
-
- [Serializable]
- [ComVisible (true)]
- [MonoTODO ("IDeserializationCallback isn't implemented.")]
- public class TextInfo: IDeserializationCallback, ICloneable
- {
- static TextInfo ()
- {
- unsafe {
- GetDataTablePointersLite (out to_lower_data_low, out to_lower_data_high, out to_upper_data_low, out to_upper_data_high);
- }
- }
-
- private readonly unsafe static ushort *to_lower_data_low;
- private readonly unsafe static ushort *to_lower_data_high;
- private readonly unsafe static ushort *to_upper_data_low;
- private readonly unsafe static ushort *to_upper_data_high;
- [MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
- private unsafe static extern void GetDataTablePointersLite (out ushort *to_lower_data_low, out ushort *to_lower_data_high,
- out ushort *to_upper_data_low, out ushort *to_upper_data_high);
-
- static char ToLowerInvariant (char c)
- {
- unsafe {
- if (c <= ((char)0x24cf))
- return (char) to_lower_data_low [c];
- if (c >= ((char)0xff21))
- return (char) to_lower_data_high[c - 0xff21];
- }
- return c;
- }
-
- static char ToUpperInvariant (char c)
- {
- unsafe {
- if (c <= ((char)0x24e9))
- return (char) to_upper_data_low [c];
- if (c >= ((char)0xff21))
- return (char) to_upper_data_high [c - 0xff21];
- }
- return c;
- }
-
- [StructLayout (LayoutKind.Sequential)]
- struct Data {
- public int ansi;
- public int ebcdic;
- public int mac;
- public int oem;
- public bool right_to_left;
- public byte list_sep;
- }
-
- string m_listSeparator;
- bool m_isReadOnly;
- string customCultureName;
-
-#pragma warning disable 169
- [NonSerialized]
- int m_nDataItem;
- bool m_useUserOverride;
-#pragma warning restore 169
-
- int m_win32LangID;
-
- [NonSerialized]
- readonly CultureInfo ci;
-
- [NonSerialized]
- readonly bool handleDotI;
-
- [NonSerialized]
- readonly Data data;
-
- internal unsafe TextInfo (CultureInfo ci, int lcid, void* data, bool read_only)
- {
- this.m_isReadOnly = read_only;
- this.m_win32LangID = lcid;
- this.ci = ci;
- if (data != null)
- this.data = *(Data*) data;
- else {
- this.data = new Data ();
- this.data.list_sep = (byte) ',';
- }
-
- CultureInfo tmp = ci;
- while (tmp.Parent != null && tmp.Parent.LCID != 0x7F && tmp.Parent != tmp)
- tmp = tmp.Parent;
-
- if (tmp != null) {
- switch (tmp.LCID) {
- case 44: // Azeri (az)
- case 31: // Turkish (tr)
- handleDotI = true;
- break;
- }
- }
- }
-
- private TextInfo (TextInfo textInfo)
- {
- m_win32LangID = textInfo.m_win32LangID;
- m_nDataItem = textInfo.m_nDataItem;
- m_useUserOverride = textInfo.m_useUserOverride;
- m_listSeparator = textInfo.ListSeparator;
- customCultureName = textInfo.CultureName;
- ci = textInfo.ci;
- handleDotI = textInfo.handleDotI;
- data = textInfo.data;
- }
-
- public virtual int ANSICodePage
- {
- get {
- return data.ansi;
- }
- }
-
- public virtual int EBCDICCodePage
- {
- get {
- return data.ebcdic;
- }
- }
-
- [ComVisible (false)]
- public int LCID {
- get { return m_win32LangID; }
- }
-
- public virtual string ListSeparator {
- get {
- if (m_listSeparator == null)
- m_listSeparator = ((char) data.list_sep).ToString ();
- return m_listSeparator;
- }
- [ComVisible (false)]
- set { m_listSeparator = value; }
- }
-
- public virtual int MacCodePage
- {
- get {
- return data.mac;
- }
- }
-
- public virtual int OEMCodePage
- {
- get {
- return data.oem;
- }
- }
-
- [ComVisible (false)]
- public string CultureName {
- get {
- if (customCultureName == null)
- customCultureName = ci == null ? String.Empty : ci.Name;
- return customCultureName;
- }
- }
-
- [ComVisible (false)]
- public bool IsReadOnly {
- get { return m_isReadOnly; }
- }
-
- [ComVisible (false)]
- public bool IsRightToLeft {
- get {
- return data.right_to_left;
- }
- }
-
- public override bool Equals (object obj)
- {
- if (obj == null)
- return false;
- TextInfo other = obj as TextInfo;
- if (other == null)
- return false;
- if (other.m_win32LangID != m_win32LangID)
- return false;
- if (other.ci != ci)
- return false;
- return true;
- }
-
- public override int GetHashCode()
- {
- return (m_win32LangID);
- }
-
- public override string ToString()
- {
- return "TextInfo - " + m_win32LangID;
- }
-
- public string ToTitleCase (string str)
- {
- if(str == null)
- throw new ArgumentNullException ("str");
-
- StringBuilder sb = null;
- int i = 0;
- int start = 0;
- while (i < str.Length) {
- if (!Char.IsLetter (str [i++]))
- continue;
- i--;
- char t = ToTitleCase (str [i]);
- bool capitalize = true;
- if (t == str [i]) {
- capitalize = false;
- bool allTitle = true;
- // if the word is all titlecase,
- // then don't capitalize it.
- int saved = i;
- while (++i < str.Length) {
- var ch = str [i];
- var category = char.GetUnicodeCategory (ch);
- if (IsSeparator (category))
- break;
- t = ToTitleCase (ch);
- if (t != ch) {
- allTitle = false;
- break;
- }
- }
- if (allTitle)
- continue;
- i = saved;
-
- // still check if all remaining
- // characters are lowercase,
- // where we don't have to modify
- // the source word.
- while (++i < str.Length) {
- var ch = str [i];
- var category = char.GetUnicodeCategory (ch);
- if (IsSeparator (category))
- break;
- if (ToLower (ch) != ch) {
- capitalize = true;
- i = saved;
- break;
- }
- }
- }
-
- if (capitalize) {
- if (sb == null)
- sb = new StringBuilder (str.Length);
- sb.Append (str, start, i - start);
- sb.Append (ToTitleCase (str [i]));
- start = i + 1;
- while (++i < str.Length) {
- var ch = str [i];
- var category = char.GetUnicodeCategory (ch);
- if (IsSeparator (category))
- break;
- sb.Append (ToLower (ch));
- }
- start = i;
- }
- }
- if (sb != null)
- sb.Append (str, start, str.Length - start);
-
- return sb != null ? sb.ToString () : str;
- }
-
- static bool IsSeparator (UnicodeCategory category)
- {
- switch (category) {
- case UnicodeCategory.SpaceSeparator:
- case UnicodeCategory.LineSeparator:
- case UnicodeCategory.ParagraphSeparator:
- case UnicodeCategory.Control:
- case UnicodeCategory.Format:
- case UnicodeCategory.ConnectorPunctuation:
- case UnicodeCategory.DashPunctuation:
- case UnicodeCategory.OpenPunctuation:
- case UnicodeCategory.ClosePunctuation:
- case UnicodeCategory.InitialQuotePunctuation:
- case UnicodeCategory.FinalQuotePunctuation:
- case UnicodeCategory.OtherPunctuation:
- return true;
- }
-
- return false;
- }
-
- // Only Azeri and Turkish have their own special cases.
- // Other than them, all languages have common special case
- // (enumerable enough).
- public virtual char ToLower (char c)
- {
- // quick ASCII range check
- if (c < 0x40 || 0x60 < c && c < 128)
- return c;
- else if ('A' <= c && c <= 'Z' && (!handleDotI || c != 'I'))
- return (char) (c + 0x20);
-
- if (ci == null || ci.LCID == 0x7F)
- return ToLowerInvariant (c);
-
- switch (c) {
- case '\u0049': // Latin uppercase I
- if (handleDotI)
- return '\u0131'; // I becomes dotless i
- break;
- case '\u0130': // I-dotted
- return '\u0069'; // i
-
- case '\u01c5': // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
- return '\u01c6';
- // \u01c7 -> \u01c9 (LJ) : invariant
- case '\u01c8': // LATIN CAPITAL LETTER L WITH SMALL LETTER J
- return '\u01c9';
- // \u01ca -> \u01cc (NJ) : invariant
- case '\u01cb': // LATIN CAPITAL LETTER N WITH SMALL LETTER J
- return '\u01cc';
- // WITH CARON : invariant
- // WITH DIAERESIS AND * : invariant
-
- case '\u01f2': // LATIN CAPITAL LETTER D WITH SMALL LETTER Z
- return '\u01f3';
- case '\u03d2': // ? it is not in ICU
- return '\u03c5';
- case '\u03d3': // ? it is not in ICU
- return '\u03cd';
- case '\u03d4': // ? it is not in ICU
- return '\u03cb';
- }
- return ToLowerInvariant (c);
- }
-
- public virtual char ToUpper (char c)
- {
- // quick ASCII range check
- if (c < 0x60)
- return c;
- else if ('a' <= c && c <= 'z' && (!handleDotI || c != 'i'))
- return (char) (c - 0x20);
-
- if (ci == null || ci.LCID == 0x7F)
- return ToUpperInvariant (c);
-
- switch (c) {
- case '\u0069': // Latin lowercase i
- if (handleDotI)
- return '\u0130'; // dotted capital I
- break;
- case '\u0131': // dotless i
- return '\u0049'; // I
-
- case '\u01c5': // see ToLower()
- return '\u01c4';
- case '\u01c8': // see ToLower()
- return '\u01c7';
- case '\u01cb': // see ToLower()
- return '\u01ca';
- case '\u01f2': // see ToLower()
- return '\u01f1';
- case '\u0390': // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
- return '\u03aa'; // it is not in ICU
- case '\u03b0': // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
- return '\u03ab'; // it is not in ICU
- case '\u03d0': // GREEK BETA
- return '\u0392';
- case '\u03d1': // GREEK THETA
- return '\u0398';
- case '\u03d5': // GREEK PHI
- return '\u03a6';
- case '\u03d6': // GREEK PI
- return '\u03a0';
- case '\u03f0': // GREEK KAPPA
- return '\u039a';
- case '\u03f1': // GREEK RHO
- return '\u03a1';
- // am not sure why miscellaneous GREEK symbols are
- // not handled here.
- }
-
- return ToUpperInvariant (c);
- }
-
- private char ToTitleCase (char c)
- {
- // Handle some Latin characters.
- switch (c) {
- case '\u01c4':
- case '\u01c5':
- case '\u01c6':
- return '\u01c5';
- case '\u01c7':
- case '\u01c8':
- case '\u01c9':
- return '\u01c8';
- case '\u01ca':
- case '\u01cb':
- case '\u01cc':
- return '\u01cb';
- case '\u01f1':
- case '\u01f2':
- case '\u01f3':
- return '\u01f2';
- }
- if ('\u2170' <= c && c <= '\u217f' || // Roman numbers
- '\u24d0' <= c && c <= '\u24e9')
- return c;
- return ToUpper (c);
- }
-
- public unsafe virtual string ToLower (string str)
- {
- // In ICU (3.2) there are a few cases that one single
- // character results in multiple characters in e.g.
- // tr-TR culture. So I tried brute force conversion
- // test with single character as a string input, but
- // there was no such conversion. So I think it just
- // invokes ToLower(char).
- if (str == null)
- throw new ArgumentNullException ("str");
-
- if (str.Length == 0)
- return String.Empty;
-
- string tmp = String.FastAllocateString (str.Length);
- fixed (char* source = str, dest = tmp) {
-
- char* destPtr = (char*)dest;
- char* sourcePtr = (char*)source;
-
- for (int n = 0; n < str.Length; n++) {
- *destPtr = ToLower (*sourcePtr);
- sourcePtr++;
- destPtr++;
- }
- }
- return tmp;
- }
-
- public unsafe virtual string ToUpper (string str)
- {
- // In ICU (3.2) there is a case that string
- // is handled beyond per-character conversion, but
- // it is only lt-LT culture where MS.NET does not
- // handle any special transliteration. So I keep
- // ToUpper() just as character conversion.
- if (str == null)
- throw new ArgumentNullException ("str");
-
- if (str.Length == 0)
- return String.Empty;
-
- string tmp = String.FastAllocateString (str.Length);
- fixed (char* source = str, dest = tmp) {
-
- char* destPtr = (char*)dest;
- char* sourcePtr = (char*)source;
-
- for (int n = 0; n < str.Length; n++) {
- *destPtr = ToUpper (*sourcePtr);
- sourcePtr++;
- destPtr++;
- }
- }
- return tmp;
- }
-
- [ComVisible (false)]
- public static TextInfo ReadOnly (TextInfo textInfo)
- {
- if (textInfo == null)
- throw new ArgumentNullException ("textInfo");
-
- TextInfo ti = new TextInfo (textInfo);
- ti.m_isReadOnly = true;
- return ti;
- }
-
- /* IDeserialization interface */
- [MonoTODO]
- void IDeserializationCallback.OnDeserialization(object sender)
- {
- // FIXME: we need to re-create "data" in order to get most properties working
- }
-
- /* IClonable */
- [ComVisible (false)]
- public virtual object Clone ()
- {
- return new TextInfo (this);
- }
-
- internal int GetCaseInsensitiveHashCode (string str)
- {
- return StringComparer.CurrentCultureIgnoreCase.GetHashCode (str);
- }
-
- internal static unsafe int GetHashCodeOrdinalIgnoreCase (string s)
- {
- var length = s.Length;
- fixed (char * c = s) {
- char * cc = c;
- char * end = cc + length - 1;
- int h = 0;
- for (;cc < end; cc += 2) {
- h = (h << 5) - h + Char.ToUpperInvariant (*cc);
- h = (h << 5) - h + Char.ToUpperInvariant (cc [1]);
- }
- ++end;
- if (cc < end)
- h = (h << 5) - h + Char.ToUpperInvariant (*cc);
- return h;
- }
- }
-
- internal static unsafe int CompareOrdinalIgnoreCase(String str1, String str2)
- {
- return CompareOrdinalIgnoreCaseEx (str1, 0, str2, 0, str1.Length, str2.Length);
- }
-
- internal static int CompareOrdinalIgnoreCaseEx (String strA, int indexA, String strB, int indexB, int lenA, int lenB)
- {
- return CompareOrdinalCaseInsensitiveUnchecked (strA, indexA, lenA, strB, indexB, lenB);
- }
-
- static unsafe int CompareOrdinalCaseInsensitiveUnchecked (String strA, int indexA, int lenA, String strB, int indexB, int lenB)
- {
- if (strA == null) {
- return strB == null ? 0 : -1;
- }
- if (strB == null) {
- return 1;
- }
- int lengthA = Math.Min (lenA, strA.Length - indexA);
- int lengthB = Math.Min (lenB, strB.Length - indexB);
-
- if (lengthA == lengthB && Object.ReferenceEquals (strA, strB))
- return 0;
-
- fixed (char* aptr = strA, bptr = strB) {
- char* ap = aptr + indexA;
- char* end = ap + Math.Min (lengthA, lengthB);
- char* bp = bptr + indexB;
- while (ap < end) {
- if (*ap != *bp) {
- char c1 = Char.ToUpperInvariant (*ap);
- char c2 = Char.ToUpperInvariant (*bp);
- if (c1 != c2)
- return c1 - c2;
- }
- ap++;
- bp++;
- }
- return lengthA - lengthB;
- }
- }
-
- internal static unsafe int LastIndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count)
- {
- int valueLen = value.Length;
- if (count < valueLen)
- return -1;
-
- if (valueLen == 0)
- return startIndex;
-
- fixed (char* thisptr = source, valueptr = value) {
- char* ap = thisptr + startIndex - valueLen + 1;
- char* thisEnd = ap - count + valueLen - 1;
- while (ap != thisEnd) {
- for (int i = 0; i < valueLen; i++) {
- if (Char.ToUpperInvariant (ap[i]) != Char.ToUpperInvariant (valueptr[i]))
- goto NextVal;
- }
- return (int)(ap - thisptr);
- NextVal:
- ap--;
- }
- }
- return -1;
- }
-
- internal static int IndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count)
- {
- Contract.Assert(source != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated source != null");
- Contract.Assert(value != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated value != null");
- Contract.Assert(startIndex + count <= source.Length, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex + count <= source.Length");
-
- // We return 0 if both inputs are empty strings
- if (source.Length == 0 && value.Length == 0)
- {
- return 0;
- }
-
- // the search space within [source] starts at offset [startIndex] inclusive and includes
- // [count] characters (thus the last included character is at index [startIndex + count -1]
- // [end] is the index of the next character after the search space
- // (it points past the end of the search space)
- int end = startIndex + count;
-
- // maxStartIndex is the index beyond which we never *start* searching, inclusive; in other words;
- // a search could include characters beyond maxStartIndex, but we'd never begin a search at an
- // index strictly greater than maxStartIndex.
- int maxStartIndex = end - value.Length;
-
- for (; startIndex <= maxStartIndex; startIndex++)
- {
- // We should always have the same or more characters left to search than our actual pattern
- Contract.Assert(end - startIndex >= value.Length);
- // since this is an ordinal comparison, we can assume that the lengths must match
- if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0)
- {
- return startIndex;
- }
- }
-
- // Not found
- return -1;
- }
- }
-}
+++ /dev/null
-//
-// System.IO.DirectoryNotFoundException.cs
-//
-// Author:
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.Serialization;
-using System.Runtime.InteropServices;
-
-namespace System.IO {
-
- [Serializable]
- [ComVisible (true)]
- public class DirectoryNotFoundException : IOException {
-
- // Constructors
- public DirectoryNotFoundException ()
- : base ("Directory not found")
- {
- }
-
- public DirectoryNotFoundException (string message)
- : base (message)
- {
- }
-
- public DirectoryNotFoundException (string message, Exception innerException)
- : base (message, innerException)
- {
- }
-
- protected DirectoryNotFoundException (SerializationInfo info, StreamingContext context)
- : base (info, context)
- {
- }
- }
-}
+++ /dev/null
-//
-// System.IO.DriveNotFoundException.cs
-//
-// Author:
-// Kornél Pál <http://www.kornelpal.hu/>
-//
-// Copyright (C) 2006 Kornél Pál
-//
-
-//
-// 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.
-//
-
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-
-namespace System.IO
-{
- [Serializable]
- [ComVisible (true)]
- public class DriveNotFoundException : IOException
- {
- private const int ErrorCode = unchecked((int)0x80070003);
-
- // Constructors
- public DriveNotFoundException ()
- : base ("Attempted to access a drive that is not available.")
- {
- this.HResult = ErrorCode;
- }
-
- public DriveNotFoundException (string message)
- : base (message)
- {
- this.HResult = ErrorCode;
- }
-
- public DriveNotFoundException (string message, Exception innerException)
- : base (message, innerException)
- {
- this.HResult = ErrorCode;
- }
-
- protected DriveNotFoundException (SerializationInfo info, StreamingContext context)
- : base (info, context)
- {
- }
- }
-}
+++ /dev/null
-//
-// System.IO.EndOfStreamException.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 2002 (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-using System.Globalization;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Runtime.InteropServices;
-
-namespace System.IO
-{
- [Serializable]
- [ComVisible (true)]
- public class EndOfStreamException : IOException
- {
- // Constructors
- public EndOfStreamException ()
- : base (Locale.GetText ("Failed to read past end of stream."))
- {
- }
-
- public EndOfStreamException (string message)
- : base (message)
- {
- }
-
- protected EndOfStreamException (SerializationInfo info,
- StreamingContext context)
- : base (info, context)
- {
- }
-
- public EndOfStreamException (string message, Exception innerException)
- :base (message, innerException)
- {
- }
-
- }
-}
+++ /dev/null
-//
-// System.IO.FileLoadException.cs
-//
-// Author:
-// Paolo Molaro (lupus@ximian.com)
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Globalization;
-using System.Runtime.Serialization;
-using System.Security;
-using System.Security.Permissions;
-using System.Text;
-using System.Runtime.InteropServices;
-
-namespace System.IO {
-
- [Serializable]
- [ComVisible (true)]
- public class FileLoadException : IOException {
-
- // Fields
- const int Result = unchecked ((int)0x80070002);
- string msg;
- string fileName;
- string fusionLog;
-
- // Constructors
- public FileLoadException ()
- : base (Locale.GetText ("I/O Error"))
- {
- HResult = Result;
- msg = Locale.GetText ("I/O Error");
- }
-
- public FileLoadException (string message)
- : base (message)
- {
- HResult = Result;
- msg = message;
- }
-
- public FileLoadException (string message, string fileName)
- : base (message)
- {
- HResult = Result;
- this.msg = message;
- this.fileName = fileName;
- }
-
- public FileLoadException (string message, Exception inner)
- : base (message, inner)
- {
- HResult = Result;
- msg = message;
- }
-
- public FileLoadException (string message, string fileName, Exception inner)
- : base (message, inner)
- {
- HResult = Result;
- this.msg = message;
- this.fileName = fileName;
- }
-
- protected FileLoadException (SerializationInfo info, StreamingContext context)
- {
- fileName = info.GetString ("FileLoad_FileName");
- fusionLog = info.GetString ("FileLoad_FusionLog");
- }
-
- // Properties
- public override string Message {
- get { return msg; }
- }
-
- public string FileName
- {
- get { return fileName; }
- }
-
- public string FusionLog {
- // note: MS runtime throws a SecurityException when the Exception is created
- // but a FileLoadException once the exception as been thrown. Mono always
- // throw a SecurityException in both case (anyway fusionLog is currently empty)
- [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
- get { return fusionLog; }
- }
-
- // Methods
- public override void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData (info, context);
- info.AddValue ("FileLoad_FileName", fileName);
- info.AddValue ("FileLoad_FusionLog", fusionLog);
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder (GetType ().FullName);
- sb.AppendFormat (": {0}", msg);
-
- if (fileName != null)
- sb.AppendFormat (" : {0}", fileName);
-
- if (this.InnerException != null)
- sb.AppendFormat (" ----> {0}", InnerException);
-
- if (this.StackTrace != null) {
- sb.Append (Environment.NewLine);
- sb.Append (StackTrace);
- }
-
- return sb.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// System.IO.FileNotFoundException.cs
-//
-// Author:
-// Paolo Molaro (lupus@ximian.com)
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Globalization;
-using System.Runtime.Serialization;
-using System.Security.Permissions;
-using System.Text;
-using System.Runtime.InteropServices;
-
-namespace System.IO {
-
- [Serializable]
- [ComVisible (true)]
- public class FileNotFoundException : IOException {
-
- const int Result = unchecked ((int)0x80131621);
-
- private string fileName;
- private string fusionLog;
-
- // Constructors
- public FileNotFoundException ()
- : base (Locale.GetText ("Unable to find the specified file."))
- {
- HResult = Result;
- }
-
- public FileNotFoundException (string message)
- : base (message)
- {
- HResult = Result;
- }
-
- public FileNotFoundException (string message, Exception innerException)
- : base (message, innerException)
- {
- HResult = Result;
- }
-
- public FileNotFoundException (string message, string fileName)
- : base (message)
- {
- HResult = Result;
- this.fileName = fileName;
- }
-
- public FileNotFoundException (string message, string fileName, Exception innerException)
- : base (message, innerException)
- {
- HResult = Result;
- this.fileName = fileName;
- }
-
- protected FileNotFoundException (SerializationInfo info, StreamingContext context)
- : base (info, context)
- {
- fileName = info.GetString ("FileNotFound_FileName");
- fusionLog = info.GetString ("FileNotFound_FusionLog");
- }
-
- public string FileName
- {
- get { return fileName; }
- }
-
- public string FusionLog {
- // note: MS runtime throws a SecurityException when the Exception is created
- // but a FileLoadException once the exception as been thrown. Mono always
- // throw a SecurityException in both case (anyway fusionLog is currently empty)
- [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
- get { return fusionLog; }
- }
-
- public override string Message {
- get {
- if (base.message == null) {
- if (fileName != null) {
- string message = string.Format (
- "Could not load file or assembly '{0}' or one of"
- + " its dependencies. The system cannot find the"
- + " file specified.", fileName);
- return message;
- }
- }
- return base.message;
- }
- }
-
- public override void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData (info, context);
- info.AddValue ("FileNotFound_FileName", fileName);
- info.AddValue ("FileNotFound_FusionLog", fusionLog);
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder (GetType ().FullName);
- sb.AppendFormat (": {0}", Message);
-
- if (fileName != null && fileName.Length > 0) {
- sb.Append (Environment.NewLine);
- sb.AppendFormat ("File name: '{0}'", fileName);
- }
-
- if (this.InnerException != null)
- sb.AppendFormat (" ---> {0}", InnerException);
-
- if (this.StackTrace != null) {
- sb.Append (Environment.NewLine);
- sb.Append (StackTrace);
- }
-
- return sb.ToString ();
- }
- }
-}
if (count > 0) {
// Use the fastest method, all range checks has been done
- Buffer.BlockCopyInternal (buf, buf_offset, dest, dest_offset, count);
+ Buffer.InternalBlockCopy (buf, buf_offset, dest, dest_offset, count);
buf_offset += count;
}
+++ /dev/null
-//
-// System.IO.IOException.cs
-//
-// Author:
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.Serialization;
-using System.Runtime.InteropServices;
-
-namespace System.IO {
- [Serializable]
- [ComVisible (true)]
- public class IOException : SystemException {
-
- // Constructors
- public IOException ()
- : base ("I/O Error")
- {
- }
-
- public IOException (string message)
- : base (message)
- {
- }
-
- public IOException (string message, Exception innerException)
- : base (message, innerException)
- {
- }
-
- protected IOException (SerializationInfo info, StreamingContext context)
- : base (info, context)
- {
- }
-
- public IOException (string message, int hresult)
- : base (message)
- {
- this.HResult = hresult;
- }
- }
-}
+++ /dev/null
-//
-// System.IO.PathTooLongException.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 2002 (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-using System.Globalization;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Runtime.InteropServices;
-
-namespace System.IO
-{
- [Serializable]
- [ComVisible (true)]
- public class PathTooLongException : IOException
- {
- // Constructors
- public PathTooLongException ()
- : base (Locale.GetText ("Pathname is longer than the maximum length"))
- {
- }
-
- public PathTooLongException (string message)
- : base (message)
- {
- }
-
- protected PathTooLongException (SerializationInfo info,
- StreamingContext context)
- : base (info, context)
- {
- }
-
- public PathTooLongException (string message, Exception innerException)
- :base (message, innerException)
- {
- }
-
- }
-}
+++ /dev/null
-//
-// System.Runtime.ConstrainedExecution.Consistency.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-
-namespace System.Runtime.ConstrainedExecution {
-
- [Serializable]
- public enum Cer {
- None,
- MayFail,
- Success
- }
-}
+++ /dev/null
-2008-04-02 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
-
- * ReliabilityContractAttribute.cs: Fix parameter names
-
-2005-10-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * CriticialFinalizerObject.cs: Added [ReliabilityContract] to ctor.
- * ReliabilityContractAttribute.cs: Removed (obsoleted) default ctor.
-
-2005-05-24 Sebastien Pouliot <sebastien@ximian.com>
-
- * CriticialFinalizerObject.cs: Changed ComVisible to true.
- * ReliabilityContractAttribute.cs: Default constructor is obsolete.
- Properties don't have setters.
-
-2005-03-04 Kazuki Oikawa <kazuki@panicode.com>
-
- * PrePrepareMethodAttribute.cs:
- * ReliabilityContractAttribute.cs: Fixed attributes.
-
-2004-08-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * CER.cs: Copied from System.Runtime.Reliability. Fixed attributes.
- * Consistency.cs: Copied from System.Runtime.Reliability. Fixed
- attributes.
- * PrePrepareMethodAttribute.cs: Copied from System.Runtime.Reliability.
- Fixed attributes.
- * CriticialFinalizerObject.cs: Added missing finalizer and attributes.
- * ReliabilityContractAttribute.cs: Copied from System.Runtime.
- Reliability. Fixed attributes.
-
-2004-08-03 Sebastien Pouliot <sebastien@ximian.com>
-
- * CriticalFinalizerObject.cs: Moved from System.Runtime.Reliability to
- match Fx 2.0 beta 1.
+++ /dev/null
-//
-// System.Runtime.ConstrainedExecution.Consistency.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-
-namespace System.Runtime.ConstrainedExecution {
-
- [Serializable]
- public enum Consistency {
- MayCorruptAppDomain = 1,
- MayCorruptInstance = 2,
- MayCorruptProcess = 0,
- WillNotCorruptState = 3
- }
-}
+++ /dev/null
-//
-// System.Runtime.ConstrainedExecution.CriticalFinalizerObject class
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-
-using System.Runtime.InteropServices;
-
-namespace System.Runtime.ConstrainedExecution
-{
- [ComVisible (true)]
- public abstract class CriticalFinalizerObject
- {
- //
- // WARNING: If you add any fields here, update the definition
- // for the runtime structures as well
- //
-
- [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
- protected CriticalFinalizerObject ()
- {
- }
-
- [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
- ~CriticalFinalizerObject ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-
-namespace System.Runtime.ConstrainedExecution
-{
- [AttributeUsage ((AttributeTargets.Constructor | AttributeTargets.Method), Inherited=false)]
- public sealed class PrePrepareMethodAttribute : Attribute
- {
- public PrePrepareMethodAttribute ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-
-namespace System.Runtime.ConstrainedExecution
-{
- [AttributeUsage ((AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct |
- AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Interface), Inherited=false)]
- public sealed class ReliabilityContractAttribute : Attribute
- {
- Consistency consistency;
- Cer cer;
-
- public ReliabilityContractAttribute (Consistency consistencyGuarantee, Cer cer)
- {
- this.consistency = consistencyGuarantee;
- this.cer = cer;
- }
-
- public Cer Cer {
- get { return cer; }
- }
-
- public Consistency ConsistencyGuarantee {
- get { return consistency; }
- }
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.BINDPTR.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct BINDPTR {
- [FieldOffset (0)]
- public IntPtr lpfuncdesc;
- [FieldOffset (0)]
- public IntPtr lptcomp;
- [FieldOffset (0)]
- public IntPtr lpvardesc;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.BIND_OPTS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential)]
- public struct BIND_OPTS
- {
- public int cbStruct;
- public int grfFlags;
- public int grfMode;
- public int dwTickCountDeadline;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.CALLCONV.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable]
- public enum CALLCONV
- {
- CC_CDECL = 1,
- CC_PASCAL = 2,
- CC_MSCPASCAL = 2,
- CC_MACPASCAL = 3,
- CC_STDCALL = 4,
- CC_RESERVED = 5,
- CC_SYSCALL = 6,
- CC_MPWCDECL = 7,
- CC_MPWPASCAL = 8,
- CC_MAX = 9
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.CONNECTDATA.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct CONNECTDATA
- {
- [MarshalAs (UnmanagedType.Interface)]
- public object pUnk;
- public int dwCookie;
- }
-}
+++ /dev/null
-2008-04-02 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
-
- * IEnumVARIANT.cs: Fix parameter names
-
-2007-08-10 Atsushi Enomoto <atsushi@ximian.com>
-
- * ITypeInfo2.cs, ITypeLib2.cs : added missing 2.0 members.
- It is so strange that many of them overlap the base interfaces.
-
-2007-08-08 Atsushi Enomoto <atsushi@ximian.com>
-
- * IMoniker.cs ELEMDESC.cs VARDESC.cs IRunningObjectTable.cs :
- cosmetic 2.0 API fixes.
-
-2005-09-21 Kornél Pál <kornelpal@hotmail.com>
-
- * IEnumConnections.cs, IEnumMoniker.cs, IEnumString.cs, IStream.cs,
- ITypeInfo.cs, ITypeLib.cs:
- Removed UnmanagedType_80 that was required because mcs bug #75945
- was not discovered.
-
-2005-03-04 Kazuki Oikawa <kazuki@panicode.com>
-
- * IBindCtx.cs
- * IEnumConnectionPoints.cs
- * IEnumMoniker.cs
- * IEnumString.cs
- * IEnumVARIANT.cs
- * IMoniker.cs
- * IRunningObjectTable.cs: Added missing attributes and corrected the wrong declarations.
-
-2005-03-03 Kazuki Oikawa <kazuki@panicode.com>
-
- * IBindCtx.cs
- * IConnectionPoint.cs
- * IConnectionPointContainer.cs
- * IEnumConnectionPoints.cs
- * IEnumConnections.cs
- * IEnumMoniker.cs
- * IEnumString.cs
- * IEnumVARIANT.cs
- * IMoniker.cs
- * IPersistFile.cs
- * IRunningObjectTable.cs
- * IStream.cs
- * ITypeComp.cs
- * ITypeInfo.cs
- * ITypeInfo2.cs
- * ITypeLib.cs
- * ITypeLib2.cs
- * EXCEPINFO.cs
- * IDLDESC.cs
- * TYPELIBATTR.cs
- * VARDESC.cs
- * INVOKEKIND.cs
- * SYSKIND.cs: Added missing attributes and corrected wrong declaration.
-
-2005-02-26 Kazuki Oikawa <kazuki@panicode.com>
-
- * BINDPTR.cs
- * BIND_OPTS.cs
- * CALLCONV.cs
- * CONNECTDATA.cs
- * DESCKIND.cs
- * DISPPARAMS.cs
- * ELEMDESC.cs
- * EXCEPINFO.cs
- * FILETIME.cs
- * FUNCDESC.cs
- * FUNCFLAGS.cs
- * FUNCKIND.cs
- * IBindCtx.cs
- * IConnectionPoint.cs
- * IConnectionPointContainer.cs
- * IDLDESC.cs
- * IDLFLAG.cs
- * IEnumConnectionPoints.cs
- * IEnumConnections.cs
- * IEnumMoniker.cs
- * IEnumString.cs
- * IEnumVARIANT.cs
- * IMoniker.cs
- * IMPLTYPEFLAGS.cs
- * INVOKEKIND.cs
- * IPersistFile.cs
- * IRunningObjectTable.cs
- * IStream.cs
- * ITypeComp.cs
- * ITypeInfo.cs
- * ITypeInfo2.cs
- * ITypeLib.cs
- * ITypeLib2.cs
- * LIBFLAGS.cs
- * PARAMDESC.cs
- * PARAMFLAG.cs
- * STATSTG.cs
- * SYSKIND.cs
- * TYPEATTR.cs
- * TYPEDESC.cs
- * TYPEFLAGS.cs
- * TYPEKIND.cs
- * TYPELIBATTR.cs
- * VARDESC.cs
- * VARFLAGS.cs
- * VARKIND.cs: Added
\ No newline at end of file
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.DESCKIND.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
-
- [Serializable]
- public enum DESCKIND {
- DESCKIND_NONE = 0,
- DESCKIND_FUNCDESC = 1,
- DESCKIND_VARDESC = 2,
- DESCKIND_TYPECOMP = 3,
- DESCKIND_IMPLICITAPPOBJ = 4,
- DESCKIND_MAX = 5
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.DISPPARAMS.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct DISPPARAMS {
- public IntPtr rgvarg;
- public IntPtr rgdispidNamedArgs;
- public int cArgs;
- public int cNamedArgs;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.ELEMDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct ELEMDESC
- {
- public TYPEDESC tdesc;
- public DESCUNION desc;
-
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct DESCUNION
- {
- [FieldOffset (0)]
- public IDLDESC idldesc;
- [FieldOffset (0)]
- public PARAMDESC paramdesc;
- }
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.EXCEPINFO.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-#if !FULL_AOT_RUNTIME
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct EXCEPINFO {
- public short wCode;
- public short wReserved;
- [MarshalAs (UnmanagedType.BStr)]
- public string bstrSource;
- [MarshalAs (UnmanagedType.BStr)]
- public string bstrDescription;
- [MarshalAs (UnmanagedType.BStr)]
- public string bstrHelpFile;
- public int dwHelpContext;
- public IntPtr pvReserved;
- public IntPtr pfnDeferredFillIn;
- public int scode;
- }
-}
-#endif
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.FILETIME.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential)]
- public struct FILETIME
- {
- public int dwLowDateTime;
- public int dwHighDateTime;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.FUNCDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential)]
- public struct FUNCDESC
- {
- public int memid;
- public IntPtr lprgscode;
- public IntPtr lprgelemdescParam;
- public FUNCKIND funckind;
- public INVOKEKIND invkind;
- public CALLCONV callconv;
- public short cParams;
- public short cParamsOpt;
- public short oVft;
- public short cScodes;
- public ELEMDESC elemdescFunc;
- public short wFuncFlags;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.FUNCFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Flags, Serializable]
- public enum FUNCFLAGS
- {
- FUNCFLAG_FRESTRICTED = 1,
- FUNCFLAG_FSOURCE = 2,
- FUNCFLAG_FBINDABLE = 4,
- FUNCFLAG_FREQUESTEDIT = 8,
- FUNCFLAG_FDISPLAYBIND = 16,
- FUNCFLAG_FDEFAULTBIND = 32,
- FUNCFLAG_FHIDDEN = 64,
- FUNCFLAG_FUSESGETLASTERROR = 128,
- FUNCFLAG_FDEFAULTCOLLELEM = 256,
- FUNCFLAG_FUIDEFAULT = 512,
- FUNCFLAG_FNONBROWSABLE = 1024,
- FUNCFLAG_FREPLACEABLE = 2048,
- FUNCFLAG_FIMMEDIATEBIND = 4096
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.FUNCKIND.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable]
- public enum FUNCKIND
- {
- FUNC_VIRTUAL = 0,
- FUNC_PUREVIRTUAL = 1,
- FUNC_NONVIRTUAL = 2,
- FUNC_STATIC = 3,
- FUNC_DISPATCH = 4
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IBindCtx.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("0000000e-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IBindCtx
- {
- void RegisterObjectBound ([MarshalAs(UnmanagedType.Interface)] object punk);
- void RevokeObjectBound ([MarshalAs(UnmanagedType.Interface)] object punk);
- void ReleaseBoundObjects ();
- void SetBindOptions ([In] ref BIND_OPTS pbindopts);
- void GetBindOptions (ref BIND_OPTS pbindopts);
- void GetRunningObjectTable (out IRunningObjectTable pprot);
- void RegisterObjectParam ([MarshalAs (UnmanagedType.LPWStr)] string pszKey, [MarshalAs (UnmanagedType.Interface)] object punk);
- void GetObjectParam ([MarshalAs (UnmanagedType.LPWStr)] string pszKey, [MarshalAs (UnmanagedType.Interface)] out object ppunk);
- void EnumObjectParam (out IEnumString ppenum);
- [PreserveSig]
- int RevokeObjectParam ([MarshalAs(UnmanagedType.LPWStr)] string pszKey);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IConnectionPoint.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("b196b286-bab4-101a-b69c-00aa00341d07")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IConnectionPoint
- {
- void GetConnectionInterface (out Guid pIID);
- void GetConnectionPointContainer (out IConnectionPointContainer ppCPC);
- void Advise ([MarshalAs(UnmanagedType.Interface)] object pUnkSink, out int pdwCookie);
- void Unadvise (int dwCookie);
- void EnumConnections (out IEnumConnections ppEnum);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IConnectionPointContainer.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("b196b284-bab4-101a-b69c-00aa00341d07")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IConnectionPointContainer
- {
- void EnumConnectionPoints (out IEnumConnectionPoints ppEnum);
- void FindConnectionPoint ([In] ref Guid riid, out IConnectionPoint ppCP);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IDLDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct IDLDESC
- {
- public IntPtr dwReserved;
- public IDLFLAG wIDLFlags;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IDLFLAG.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Flags, Serializable]
- public enum IDLFLAG
- {
- IDLFLAG_NONE = 0,
- IDLFLAG_FIN = 1,
- IDLFLAG_FOUT = 2,
- IDLFLAG_FLCID = 4,
- IDLFLAG_FRETVAL = 8
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("b196b285-bab4-101a-b69c-00aa00341d07")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IEnumConnectionPoints
- {
- [PreserveSigAttribute]
- int Next (int celt, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 0)] IConnectionPoint[] rgelt, IntPtr pceltFetched);
- [PreserveSigAttribute]
- int Skip (int celt);
- void Reset ();
- void Clone (out IEnumConnectionPoints ppenum);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IEnumConnections.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("b196b287-bab4-101a-b69c-00aa00341d07")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IEnumConnections
- {
- [PreserveSigAttribute]
- int Next (int celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] CONNECTDATA[] rgelt, IntPtr pceltFetched);
- [PreserveSigAttribute]
- int Skip (int celt);
- void Reset ();
- void Clone (out IEnumConnections ppenum);
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IEnumMoniker.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("00000102-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IEnumMoniker
- {
- [PreserveSigAttribute]
- int Next (int celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IMoniker[] rgelt, IntPtr pceltFetched);
- [PreserveSigAttribute]
- int Skip (int celt);
- void Reset ();
- void Clone (out IEnumMoniker ppenum);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IEnumString.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("00000101-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IEnumString
- {
- [PreserveSigAttribute]
- int Next (int celt, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 0)] string[] rgelt, IntPtr pceltFetched);
- [PreserveSigAttribute]
- int Skip (int celt);
- void Reset ();
- void Clone (out IEnumString ppenum);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IEnumVARIANT.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("00020404-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IEnumVARIANT
- {
- [PreserveSigAttribute]
- int Next (int celt, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex=0)] object[] rgVar, IntPtr pceltFetched);
- [PreserveSigAttribute]
- int Skip (int celt);
- [PreserveSigAttribute]
- int Reset ();
- IEnumVARIANT Clone ();
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Flags, Serializable]
- public enum IMPLTYPEFLAGS
- {
- IMPLTYPEFLAG_FDEFAULT = 1,
- IMPLTYPEFLAG_FSOURCE = 2,
- IMPLTYPEFLAG_FRESTRICTED = 4,
- IMPLTYPEFLAG_FDEFAULTVTABLE = 8
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IMoniker.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("0000000f-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IMoniker
- {
- void GetClassID (out Guid pClassID);
- [PreserveSig]
- int IsDirty ();
- void Load (IStream pStm);
- void Save (IStream pStm, [MarshalAs (UnmanagedType.Bool)] bool fClearDirty);
- void GetSizeMax (out long pcbSize);
- void BindToObject (IBindCtx pbc, IMoniker pmkToLeft, [In] ref Guid riidResult, [MarshalAs (UnmanagedType.Interface)] out object ppvResult);
- void BindToStorage (IBindCtx pbc, IMoniker pmkToLeft, [In] ref Guid riid, [MarshalAs (UnmanagedType.Interface)] out object ppvObj);
- void Reduce (IBindCtx pbc, int dwReduceHowFar, ref IMoniker ppmkToLeft, out IMoniker ppmkReduced);
- void ComposeWith (IMoniker pmkRight, [MarshalAs (UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out IMoniker ppmkComposite);
- void Enum ([MarshalAs(UnmanagedType.Bool)] bool fForward, out IEnumMoniker ppenumMoniker);
- [PreserveSig]
- int IsEqual (IMoniker pmkOtherMoniker);
- void Hash (out int pdwHash);
- [PreserveSig]
- int IsRunning (IBindCtx pbc, IMoniker pmkToLeft, IMoniker pmkNewlyRunning);
- void GetTimeOfLastChange (IBindCtx pbc, IMoniker pmkToLeft, out FILETIME pFileTime);
- void Inverse (out IMoniker ppmk);
- void CommonPrefixWith (IMoniker pmkOther, out IMoniker ppmkPrefix);
- void RelativePathTo (IMoniker pmkOther, out IMoniker ppmkRelPath);
- void GetDisplayName (IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs (UnmanagedType.LPWStr)] out string ppszDisplayName);
- void ParseDisplayName (IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs (UnmanagedType.LPWStr)] string pszDisplayName, out int pchEaten, out IMoniker ppmkOut);
- [PreserveSig]
- int IsSystemMoniker (out int pdwMksys);
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.INVOKEKIND.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Flags]
- [Serializable]
- public enum INVOKEKIND {
- INVOKE_FUNC = 1,
- INVOKE_PROPERTYGET = 2,
- INVOKE_PROPERTYPUT = 4,
- INVOKE_PROPERTYPUTREF = 8
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IPersistFile.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("0000010b-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IPersistFile
- {
- void GetClassID (out Guid pClassID);
- [PreserveSig]
- int IsDirty ();
- void Load ([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, int dwMode);
- void Save ([MarshalAs (UnmanagedType.LPWStr)] string pszFileName, [MarshalAs (UnmanagedType.Bool)] bool fRemember);
- void SaveCompleted ([MarshalAs (UnmanagedType.LPWStr)]string pszFileName);
- void GetCurFile ([MarshalAs(UnmanagedType.LPWStr)] out string ppszFileName);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IRunningObjectTable.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("00000010-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IRunningObjectTable
- {
- int Register (int grfFlags, [MarshalAs (UnmanagedType.Interface)] object punkObject, IMoniker pmkObjectName);
- void Revoke (int dwRegister);
- [PreserveSig]
- int IsRunning (IMoniker pmkObjectName);
- [PreserveSig]
- int GetObject (IMoniker pmkObjectName, [MarshalAs (UnmanagedType.Interface)] out object ppunkObject);
- void NoteChangeTime (int dwRegister, ref FILETIME pfiletime);
- [PreserveSig]
- int GetTimeOfLastChange (IMoniker pmkObjectName, out FILETIME pfiletime);
- void EnumRunning (out IEnumMoniker ppenumMoniker);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.IStream.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-using System.Runtime.InteropServices.ComTypes;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("0000000c-0000-0000-c000-000000000046")]
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- public interface IStream
- {
- void Read ([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);
- void Write ([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);
- void Seek (long dlibMove, int dwOrigin, IntPtr plibNewPosition);
- void SetSize (long libNewSize);
- void CopyTo (IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);
- void Commit (int grfCommitFlags);
- void Revert ();
- void LockRegion (long libOffset, long cb, int dwLockType);
- void UnlockRegion (long libOffset, long cb, int dwLockType);
- void Stat (out STATSTG pstatstg, int grfStatFlag);
- void Clone (out IStream ppstm);
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.ITypeComp.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid("00020403-0000-0000-c000-000000000046")]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITypeComp {
- void Bind([MarshalAs(UnmanagedType.LPWStr)] string szName, int lHashVal, short wFlags, out ITypeInfo ppTInfo, out DESCKIND pDescKind, out BINDPTR pBindPtr);
- void BindType([MarshalAs(UnmanagedType.LPWStr)] string szName, int lHashVal, out ITypeInfo ppTInfo, out ITypeComp ppTComp);
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.ITypeInfo.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid("00020401-0000-0000-c000-000000000046")]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITypeInfo {
- void GetTypeAttr (out IntPtr ppTypeAttr);
- void GetTypeComp (out ITypeComp ppTComp);
- void GetFuncDesc (int index, out IntPtr ppFuncDesc);
- void GetVarDesc (int index, out IntPtr ppVarDesc);
- void GetNames (int memid, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex=2)] string[] rgBstrNames, int cMaxNames, out int pcNames);
- void GetRefTypeOfImplType (int index, out int href);
- void GetImplTypeFlags (int index, out IMPLTYPEFLAGS pImplTypeFlags);
- void GetIDsOfNames ([In, MarshalAs(UnmanagedType.LPArray, ArraySubType = (UnmanagedType.LPWStr), SizeParamIndex=1)] string[] rgszNames, int cNames, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex=1)] int[] pMemId);
- void Invoke ([MarshalAs (UnmanagedType.IUnknown)] object pvInstance, int memid, short wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr);
- void GetDocumentation (int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
- void GetDllEntry (int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal);
- void GetRefTypeInfo (int hRef, out ITypeInfo ppTI);
- void AddressOfMember (int memid, INVOKEKIND invKind, out IntPtr ppv);
- void CreateInstance ([MarshalAs (UnmanagedType.IUnknown)] object pUnkOuter, [In] ref Guid riid, [MarshalAs (UnmanagedType.IUnknown)] out object ppvObj);
- void GetMops (int memid, out string pBstrMops);
- void GetContainingTypeLib (out ITypeLib ppTLB, out int pIndex);
- [PreserveSig]
- void ReleaseTypeAttr (IntPtr pTypeAttr);
- [PreserveSig]
- void ReleaseFuncDesc (IntPtr pFuncDesc);
- [PreserveSig]
- void ReleaseVarDesc (IntPtr pVarDesc);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.ITypeInfo2.cs
-//
-// Author:
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid("00020412-0000-0000-C000-000000000046")]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITypeInfo2 : ITypeInfo
- {
- new void AddressOfMember (int memid, INVOKEKIND invKind, out IntPtr ppv);
- new void CreateInstance ([MarshalAs (UnmanagedType.IUnknown)] object pUnkOuter, [In] ref Guid riid, [MarshalAs (UnmanagedType.IUnknown)] out object ppvObj);
- new void GetContainingTypeLib (out ITypeLib ppTLB, out int pIndex);
- new void GetDllEntry (int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal);
- new void GetDocumentation (int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
- new void GetIDsOfNames ([In, MarshalAs(UnmanagedType.LPArray, ArraySubType = (UnmanagedType.LPWStr), SizeParamIndex=1)] string[] rgszNames, int cNames, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex=1)] int[] pMemId);
-
- new void GetImplTypeFlags (int index, out IMPLTYPEFLAGS pImplTypeFlags);
- void GetTypeKind (out TYPEKIND pTypeKind);
- void GetTypeFlags (out int pTypeFlags);
- new void GetFuncDesc (int index, out IntPtr ppFuncDesc);
- new void GetMops (int memid, out string pBstrMops);
- new void GetNames (int memid, [Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex=2)] string[] rgBstrNames, int cMaxNames, out int pcNames);
- new void GetRefTypeInfo (int hRef, out ITypeInfo ppTI);
- new void GetRefTypeOfImplType (int index, out int href);
- new void GetTypeAttr (out IntPtr ppTypeAttr);
- new void GetTypeComp (out ITypeComp ppTComp);
- new void GetVarDesc (int index, out IntPtr ppVarDesc);
- void GetFuncIndexOfMemId (int memid, INVOKEKIND invKind, out int pFuncIndex);
- void GetVarIndexOfMemId (int memid, out int pVarIndex);
- void GetCustData (ref Guid guid, out object pVarVal);
- void GetFuncCustData(int index, ref Guid guid, out object pVarVal);
- void GetParamCustData(int indexFunc, int indexParam, ref Guid guid, out object pVarVal);
- void GetVarCustData(int index, ref Guid guid, out object pVarVal);
- void GetImplTypeCustData(int index, ref Guid guid, out object pVarVal);
- [LCIDConversion (1)]
- void GetDocumentation2(int memid, out string pbstrHelpString, out int pdwHelpStringContext, out string pbstrHelpStringDll);
- void GetAllCustData(IntPtr pCustData);
- void GetAllFuncCustData(int index, IntPtr pCustData);
- void GetAllParamCustData(int indexFunc, int indexParam, IntPtr pCustData);
- void GetAllVarCustData(int index, IntPtr pCustData);
- void GetAllImplTypeCustData(int index, IntPtr pCustData);
- new void Invoke ([MarshalAs (UnmanagedType.IUnknown)] object pvInstance, int memid, short wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr);
- [PreserveSig]
- new void ReleaseTypeAttr (IntPtr pTypeAttr);
- [PreserveSig]
- new void ReleaseFuncDesc (IntPtr pFuncDesc);
- [PreserveSig]
- new void ReleaseVarDesc (IntPtr pVarDesc);
- }
-}
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes.ITypeLib.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-using System;
-using System.Runtime.InteropServices.ComTypes;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid("00020402-0000-0000-c000-000000000046")]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITypeLib {
- [PreserveSig]
- int GetTypeInfoCount ();
- void GetTypeInfo (int index, out ITypeInfo ppTI);
- void GetTypeInfoType (int index, out TYPEKIND pTKind);
- void GetTypeInfoOfGuid (ref Guid guid, out ITypeInfo ppTInfo);
- void GetLibAttr (out IntPtr ppTLibAttr);
- void GetTypeComp (out ITypeComp ppTComp);
- void GetDocumentation (int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
- [return: MarshalAs (UnmanagedType.Bool)]
- bool IsName ([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal);
- void FindName ([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal, [Out, MarshalAs (UnmanagedType.LPArray)] ITypeInfo[] ppTInfo, [Out, MarshalAs (UnmanagedType.LPArray)] int[] rgMemId, ref short pcFound);
- [PreserveSig]
- void ReleaseTLibAttr (IntPtr pTLibAttr);
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.ITypeLib2.cs
-//
-// Author:
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [ComImport]
- [Guid ("00020411-0000-0000-C000-000000000046")]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITypeLib2 : ITypeLib
- {
- new void FindName ([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal, [Out, MarshalAs (UnmanagedType.LPArray)] ITypeInfo[] ppTInfo, [Out, MarshalAs (UnmanagedType.LPArray)] int[] rgMemId, ref short pcFound);
- void GetCustData(ref Guid guid, out object pVarVal);
- new void GetDocumentation (int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
- new void GetLibAttr (out IntPtr ppTLibAttr);
- void GetLibStatistics(IntPtr pcUniqueNames, out int pcchUniqueNames);
- [LCIDConversion(1)]
- void GetDocumentation2(int index, out string pbstrHelpString, out int pdwHelpStringContext, out string pbstrHelpStringDll);
- void GetAllCustData(IntPtr pCustData);
- new void GetTypeComp (out ITypeComp ppTComp);
- new void GetTypeInfo (int index, out ITypeInfo ppTI);
- new void GetTypeInfoOfGuid (ref Guid guid, out ITypeInfo ppTInfo);
- new void GetTypeInfoType (int index, out TYPEKIND pTKind);
- [return: MarshalAs (UnmanagedType.Bool)]
- new bool IsName ([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal);
- [PreserveSig]
- new void ReleaseTLibAttr (IntPtr pTLibAttr);
- // undocumented
- [PreserveSig]
- new int GetTypeInfoCount ();
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.LIBFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Flags, Serializable]
- public enum LIBFLAGS
- {
- LIBFLAG_FRESTRICTED = 1,
- LIBFLAG_FCONTROL = 2,
- LIBFLAG_FHIDDEN = 4,
- LIBFLAG_FHASDISKIMAGE = 8
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.PARAMDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct PARAMDESC
- {
- public IntPtr lpVarValue;
- public PARAMFLAG wParamFlags;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.PARAMFLAG.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Flags, Serializable]
- public enum PARAMFLAG
- {
- PARAMFLAG_NONE = 0,
- PARAMFLAG_FIN = 1,
- PARAMFLAG_FOUT = 2,
- PARAMFLAG_FLCID = 4,
- PARAMFLAG_FRETVAL = 8,
- PARAMFLAG_FOPT = 16,
- PARAMFLAG_FHASDEFAULT = 32,
- PARAMFLAG_FHASCUSTDATA = 64
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.STATSTG.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct STATSTG
- {
- public string pwcsName;
- public int type;
- public long cbSize;
- public FILETIME mtime;
- public FILETIME ctime;
- public FILETIME atime;
- public int grfMode;
- public int grfLocksSupported;
- public Guid clsid;
- public int grfStateBits;
- public int reserved;
- }
-
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.SYSKIND.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable]
- public enum SYSKIND
- {
- SYS_WIN16 = 0,
- SYS_WIN32 = 1,
- SYS_MAC = 2,
- SYS_WIN64 = 3
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.TYPEATTR.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct TYPEATTR
- {
- public const int MEMBER_ID_NIL = -1;
-
- public Guid guid;
- public int lcid;
- public int dwReserved;
- public int memidConstructor;
- public int memidDestructor;
- public IntPtr lpstrSchema;
- public int cbSizeInstance;
- public TYPEKIND typekind;
- public short cFuncs;
- public short cVars;
- public short cImplTypes;
- public short cbSizeVft;
- public short cbAlignment;
- public TYPEFLAGS wTypeFlags;
- public short wMajorVerNum;
- public short wMinorVerNum;
- public TYPEDESC tdescAlias;
- public IDLDESC idldescType;
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.TYPEDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct TYPEDESC
- {
- public IntPtr lpValue;
- public short vt;
- }
-}
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.TYPEFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable, Flags]
- public enum TYPEFLAGS
- {
- TYPEFLAG_FAPPOBJECT = 1,
- TYPEFLAG_FCANCREATE = 2,
- TYPEFLAG_FLICENSED = 4,
- TYPEFLAG_FPREDECLID = 8,
- TYPEFLAG_FHIDDEN = 16,
- TYPEFLAG_FCONTROL = 32,
- TYPEFLAG_FDUAL = 64,
- TYPEFLAG_FNONEXTENSIBLE = 128,
- TYPEFLAG_FOLEAUTOMATION = 256,
- TYPEFLAG_FRESTRICTED = 512,
- TYPEFLAG_FAGGREGATABLE = 1024,
- TYPEFLAG_FREPLACEABLE = 2048,
- TYPEFLAG_FDISPATCHABLE = 4096,
- TYPEFLAG_FREVERSEBIND = 8192,
- TYPEFLAG_FPROXY = 16384
- }
-}
-
+++ /dev/null
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-// System.Runtime.InteropServices.ComTypes/TYPEKIND.cs
-//
-// Paolo Molaro (lupus@ximian.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-// (C) 2002 Ximian, Inc.
-
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
-
- [Serializable]
- public enum TYPEKIND {
- TKIND_ENUM = 0,
- TKIND_RECORD = 1,
- TKIND_MODULE = 2,
- TKIND_INTERFACE = 3,
- TKIND_DISPATCH = 4,
- TKIND_COCLASS = 5,
- TKIND_ALIAS = 6,
- TKIND_UNION = 7,
- TKIND_MAX = 8
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.TYPELIBATTR.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable]
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct TYPELIBATTR
- {
- public Guid guid;
- public int lcid;
- public SYSKIND syskind;
- public short wMajorVerNum;
- public short wMinorVerNum;
- public LIBFLAGS wLibFlags;
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.VARDESC.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct VARDESC
- {
- public int memid;
- public string lpstrSchema;
- public DESCUNION desc;
- public ELEMDESC elemdescVar;
- public short wVarFlags;
- public VARKIND varkind;
-
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct DESCUNION
- {
- [FieldOffset (0)]
- public IntPtr lpvarValue;
- [FieldOffset (0)]
- public int oInst;
- }
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.VARFLAGS.cs
-//
-// Author:
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable, Flags]
- public enum VARFLAGS
- {
- VARFLAG_FREADONLY = 1,
- VARFLAG_FSOURCE = 2,
- VARFLAG_FBINDABLE = 4,
- VARFLAG_FREQUESTEDIT = 8,
- VARFLAG_FDISPLAYBIND = 16,
- VARFLAG_FDEFAULTBIND = 32,
- VARFLAG_FHIDDEN = 64,
- VARFLAG_FRESTRICTED = 128,
- VARFLAG_FDEFAULTCOLLELEM = 256,
- VARFLAG_FUIDEFAULT = 512,
- VARFLAG_FNONBROWSABLE = 1024,
- VARFLAG_FREPLACEABLE = 2048,
- VARFLAG_FIMMEDIATEBIND = 4096
- }
-}
-
+++ /dev/null
-//
-// System.Runtime.InteropServices.ComTypes.VARKIND.cs
-//
-// Author:
-// Kazuki Oikawa (kazuki@panicode.com)
-//
-
-
-namespace System.Runtime.InteropServices.ComTypes
-{
- [Serializable]
- public enum VARKIND
- {
- VAR_PERINSTANCE = 0,
- VAR_STATIC = 1,
- VAR_CONST = 2,
- VAR_DISPATCH = 3
- }
-}
-
+++ /dev/null
-2007-08-08 Atsushi Enomoto <atsushi@ximian.com>
-
- * IExpando.cs : [ComVisible]
-
-2003-11-13 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
-
- * IExpando.cs: Added attribute
-
-2002-11-20 Alejandro Sánchez Acosta <raciel@es.gnu.org>
-
- * IExpando.cs added.
+++ /dev/null
-//
-// System.Runtime.InteropServices.Expando.IExpando.cs
-//
-// Author:
-// Alejandro Sánchez Acosta (raciel@es.gnu.org)
-//
-// (C) Alejandro Sánchez Acosta
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Reflection;
-
-namespace System.Runtime.InteropServices.Expando
-{
- [Guid("afbf15e6-c37c-11d2-b88e-00a0c9b471b8")]
- [System.Runtime.InteropServices.ComVisible (true)]
- public interface IExpando : IReflect
- {
- FieldInfo AddField (string name);
-
- MethodInfo AddMethod (string name, Delegate method);
-
- PropertyInfo AddProperty(string name);
-
- void RemoveMember(MemberInfo m);
- }
-}
+++ /dev/null
-//
-// System.Runtime.Reliability.Consistency.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-
-using System.Runtime.InteropServices;
-namespace System.Runtime.Reliability
-{
- [Serializable]
- [ComVisible (false)]
- public enum CER
- {
- MayFail = 1,
- None = 0,
- Success = 2
- }
-}
+++ /dev/null
-2005-03-04 Kazuki Oikawa <kazuki@panicode.com>
-
- * CER.cs:
- * Consistency.cs:
- * PrePrepareMethodAttribute.cs:
- * ReliabilityContractAttribute.cs: Added missing attributes.
-
-2004-08-03 Sebastien Pouliot <sebastien@ximian.com>
-
- * CriticialFinalizerObject.cs: Moved to System.Runtime.
- ConstrainedExecution to match Fx 2.0 beta 1.
-
-2004-07-12 Duncan Mak <duncan@ximian.com>
-
- * CER.cs:
- * Consistency.cs:
- * CriticialFinalizerObject.cs:
- * PrePrepareMethodAttribute.cs:
- * ReliabilityContractAttribute.cs: Added.
-
+++ /dev/null
-//
-// System.Runtime.Reliability.Consistency.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-
-using System.Runtime.InteropServices;
-namespace System.Runtime.Reliability
-{
- [ComVisible (false)]
- [Serializable]
- public enum Consistency
- {
- MayCorruptAppDomain = 1,
- MayCorruptInstance = 2,
- MayCorruptProcess = 0,
- WillNotCorruptState = 3
- }
-}
+++ /dev/null
-//
-// System.Runtime.Reliability.PrePrepareMethodAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-
-using System.Runtime.InteropServices;
-namespace System.Runtime.Reliability
-{
- [Obsolete]
- [AttributeUsage (AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
- [ComVisible (false)]
- public sealed class PrePrepareMethodAttribute : Attribute
- {
- public PrePrepareMethodAttribute ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.Runtime.Reliability.ReliabilityContractAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// 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.
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-
-using System.Runtime.InteropServices;
-namespace System.Runtime.Reliability
-{
- [AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class |
- AttributeTargets.Struct | AttributeTargets.Constructor |
- AttributeTargets.Method | AttributeTargets.Interface, Inherited = false)]
- [ComVisible (false)]
- [Obsolete]
- public sealed class ReliabilityContractAttribute : Attribute
- {
- Consistency consistency;
- CER cer;
-
- public ReliabilityContractAttribute ()
- {
- }
-
- public ReliabilityContractAttribute (Consistency consistency, CER cer)
- {
- this.consistency = consistency;
- this.cer = cer;
- }
-
- public CER CER {
- get { return cer; }
- set { cer = value;}
- }
-
- public Consistency ConsistencyGuarantee {
-
- get { return consistency; }
-
- set { consistency = value; }
- }
- }
-}
-
return rp.ObjectIdentity.ClientDynamicProperties;
}
else
+ {
+#if FEATURE_REMOTING
return obj.ObjectIdentity.ServerDynamicProperties;
+#else
+ throw new NotSupportedException ();
+#endif
+ }
}
else if (ctx != null && obj == null)
{
int baseCount = 0;
Type baseType = type.BaseType;
- while (baseType != typeof (MarshalByRefObject) && baseType != typeof(object))
+ while (baseType != typeof (MarshalByRefObject) && baseType != null)
{
baseType = baseType.BaseType;
baseCount++;
+++ /dev/null
-//
-// Action.cs
-//
-// Authors:
-// Ben Maurer (bmaurer@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004, 2010 Novell
-//
-// 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.
-//
-
-using System.Runtime.CompilerServices;
-
-namespace System
-{
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate void Action ();
-
- public delegate void Action <in T> (T obj);
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate void Action <in T1, in T2> (T1 arg1, T2 arg2);
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate void Action <in T1, in T2, in T3> (T1 arg1, T2 arg2, T3 arg3);
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate void Action <in T1, in T2, in T3, in T4> (T1 arg1, T2 arg2, T3 arg3, T4 arg4);
-
- public delegate void Action <in T1, in T2, in T3, in T4, in T5> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
- public delegate void Action <in T1, in T2, in T3, in T4, in T5, in T6> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
- public delegate void Action <in T1, in T2, in T3, in T4, in T5, in T6, in T7> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
- public delegate void Action <in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
-}
+++ /dev/null
-//
-// System.ApplicationId class
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace System {
-
- [Serializable]
- [ComVisible (true)]
- public sealed class ApplicationId {
-
- private byte[] _token;
- private string _name;
- private Version _version;
- private string _proc;
- private string _culture;
-
- public ApplicationId (byte[] publicKeyToken, string name, Version version, string processorArchitecture, string culture)
- {
- if (publicKeyToken == null)
- throw new ArgumentNullException ("publicKeyToken");
- if (name == null)
- throw new ArgumentNullException ("name");
- if (version == null)
- throw new ArgumentNullException ("version");
-
- _token = (byte[]) publicKeyToken.Clone ();
- _name = name;
- _version = version;
- _proc = processorArchitecture;
- _culture = culture;
- }
-
- // properties
-
- public string Culture {
- get { return _culture; }
- }
-
- public string Name {
- get { return _name; }
- }
-
- public string ProcessorArchitecture {
- get { return _proc; }
- }
-
- public byte[] PublicKeyToken {
- get { return (byte[]) _token.Clone (); }
- }
-
- public Version Version {
- get { return _version; }
- }
-
- // methods
-
- public ApplicationId Copy ()
- {
- return new ApplicationId (_token, _name, _version, _proc, _culture);
- }
-
- public override bool Equals (object o)
- {
- if (o == null)
- return false;
- ApplicationId appid = (o as ApplicationId);
- if (appid == null)
- return false;
- if (_name != appid._name)
- return false;
- if (_proc != appid._proc)
- return false;
- if (_culture != appid._culture)
- return false;
- if (!_version.Equals (appid._version))
- return false;
- if (_token.Length != appid._token.Length)
- return false;
- for (int i=0; i < _token.Length; i++)
- if (_token [i] != appid._token [i])
- return false;
- return true;
- }
-
- public override int GetHashCode ()
- {
- int code = _name.GetHashCode () ^ _version.GetHashCode ();
- for (int i=0; i < _token.Length; i++)
- code ^= _token [i];
- // ProcessorArchitecture and Culture aren't part of the hash code
- // Confirmed by Microsoft in FDBK13339
- return code;
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder ();
- sb.Append (_name);
- if (_culture != null)
- sb.AppendFormat (", culture=\"{0}\"", _culture);
- sb.AppendFormat (", version=\"{0}\", publicKeyToken=\"", _version);
- for (int i=0; i < _token.Length; i++)
- sb.Append (_token [i].ToString ("X2"));
- if (_proc != null)
- sb.AppendFormat ("\", processorArchitecture =\"{0}\"", _proc);
- else
- sb.Append ("\"");
- return sb.ToString ();
- }
- }
-}
if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
throw new ArgumentOutOfRangeException ();
- return EqualityComparer<T>.Default.IndexOf (array, value, startIndex, startIndex + count);
+ return EqualityComparer<T>.Default.IndexOf (array, value, startIndex, count);
}
public static int LastIndexOf<T> (T [] array, T value)
+++ /dev/null
-//
-// System.AsyncCallback.cs
-//
-// Author:
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System
-{
- [System.Runtime.InteropServices.ComVisible (true)]
- [Serializable]
- public delegate void AsyncCallback (IAsyncResult ar);
-}
+++ /dev/null
-//
-// System.AttributeTargets.cs
-//
-// This code was automatically generated from
-// ECMA CLI XML Library Specification.
-// Generator: libgen.xsl [1.0; (C) Sergey Chaban (serge@wildwestsoftware.com)]
-// Created: Fri, 7 Sep 2001 16:31:48 UTC
-// Source file: AllTypes.xml
-// URL: http://msdn.microsoft.com/net/ecma/AllTypes.xml
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible (true)]
- [Serializable]
- [Flags]
- public enum AttributeTargets
- {
- Assembly = 0x00000001,
- Module = 0x00000002,
- Class = 0x00000004,
- Struct = 0x00000008,
- Enum = 0x00000010,
- Constructor = 0x00000020,
- Method = 0x00000040,
- Property = 0x00000080,
- Field = 0x00000100,
- Event = 0x00000200,
- Interface = 0x00000400,
- Parameter = 0x00000800,
- Delegate = 0x00001000,
- ReturnValue = 0x00002000,
-
- GenericParameter = 0x00004000,
- All = Assembly | Module | Class | Struct | Enum | Constructor |
- Method | Property | Field | Event | Interface | Parameter | Delegate | ReturnValue | GenericParameter
- }
-}
-
+++ /dev/null
-//
-// System.BadImageFormatException.cs
-//
-// Authors:
-// Sean MacIsaac (macisaac@ximian.com)
-// Duncan Mak (duncan@ximian.com)
-// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
-//
-// (C) 2001 Ximian, Inc.
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Globalization;
-using System.Runtime.Serialization;
-using System.Security.Permissions;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace System
-{
- [Serializable]
- [ComVisible (true)]
- public class BadImageFormatException : SystemException
- {
- const int Result = unchecked ((int)0x8007000B);
-
- // Fields
- private string fileName;
- private string fusionLog;
-
- // Constructors
- public BadImageFormatException ()
- : base (Locale.GetText ("Format of the executable (.exe) or library (.dll) is invalid."))
- {
- HResult = Result;
- }
-
- public BadImageFormatException (string message)
- : base (message)
- {
- HResult = Result;
- }
-
- protected BadImageFormatException (SerializationInfo info, StreamingContext context)
- : base (info, context)
- {
- fileName = info.GetString ("BadImageFormat_FileName");
- fusionLog = info.GetString ("BadImageFormat_FusionLog");
- }
-
- public BadImageFormatException (string message, Exception inner)
- : base (message, inner)
- {
- HResult = Result;
- }
-
- public BadImageFormatException (string message, string fileName)
- : base (message)
- {
- this.fileName = fileName;
- HResult = Result;
- }
-
- public BadImageFormatException (string message, string fileName, Exception inner)
- : base (message, inner)
- {
- this.fileName = fileName;
- HResult = Result;
- }
-
- // Properties
- public override string Message
- {
- get {
- if (base.message == null) {
- return string.Format (
- "Could not load file or assembly '{0}' or one of"
- + " its dependencies. An attempt was made to load"
- + " a program with an incorrect format.", fileName);
- }
- return base.Message;
- }
- }
-
- public string FileName
- {
- get { return fileName; }
- }
-
- [MonoTODO ("Probably not entirely correct. fusionLog needs to be set somehow (we are probably missing internal constuctor)")]
- public string FusionLog {
- // note: MS runtime throws a SecurityException when the Exception is created
- // but a FileLoadException once the exception as been thrown. Mono always
- // throw a SecurityException in both case (anyway fusionLog is currently empty)
- [SecurityPermission (SecurityAction.Demand, ControlEvidence=true, ControlPolicy=true)]
- get { return fusionLog; }
- }
-
- // Methods
- public override void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData (info, context);
- info.AddValue ("BadImageFormat_FileName", fileName);
- info.AddValue ("BadImageFormat_FusionLog", fusionLog);
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder (GetType ().FullName);
- sb.AppendFormat (": {0}", Message);
-
- if (fileName != null && fileName.Length > 0) {
- sb.Append (Environment.NewLine);
- sb.AppendFormat ("File name: '{0}'", fileName);
- }
-
- if (this.InnerException != null)
- sb.AppendFormat (" ---> {0}", InnerException);
-
- if (this.StackTrace != null) {
- sb.Append (Environment.NewLine);
- sb.Append (StackTrace);
- }
-
- return sb.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// System.Buffer.cs
-//
-// Authors:
-// Paolo Molaro (lupus@ximian.com)
-// Dan Lewis (dihlewis@yahoo.co.uk)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Diagnostics.Contracts;
-
-namespace System {
- [ComVisible (true)]
- public static class Buffer {
-
- public static int ByteLength (Array array)
- {
- // note: the other methods in this class also use ByteLength to test for
- // null and non-primitive arguments as a side-effect.
-
- if (array == null)
- throw new ArgumentNullException ("array");
-
- int length = ByteLengthInternal (array);
- if (length < 0)
- throw new ArgumentException (Locale.GetText ("Object must be an array of primitives."));
-
- return length;
- }
-
- public static byte GetByte (Array array, int index)
- {
- if (index < 0 || index >= ByteLength (array))
- throw new ArgumentOutOfRangeException ("index", Locale.GetText(
- "Value must be non-negative and less than the size of the collection."));
-
- return GetByteInternal (array, index);
- }
-
- public static void SetByte (Array array, int index, byte value)
- {
- if (index < 0 || index >= ByteLength (array))
- throw new ArgumentOutOfRangeException ("index", Locale.GetText(
- "Value must be non-negative and less than the size of the collection."));
-
- SetByteInternal (array, index, value);
- }
-
- public static void BlockCopy (Array src, int srcOffset, Array dst, int dstOffset, int count)
- {
- if (src == null)
- throw new ArgumentNullException ("src");
-
- if (dst == null)
- throw new ArgumentNullException ("dst");
-
- if (srcOffset < 0)
- throw new ArgumentOutOfRangeException ("srcOffset", Locale.GetText(
- "Non-negative number required."));
-
- if (dstOffset < 0)
- throw new ArgumentOutOfRangeException ("dstOffset", Locale.GetText (
- "Non-negative number required."));
-
- if (count < 0)
- throw new ArgumentOutOfRangeException ("count", Locale.GetText (
- "Non-negative number required."));
-
- // We do the checks in unmanaged code for performance reasons
- bool res = BlockCopyInternal (src, srcOffset, dst, dstOffset, count);
- if (!res) {
- // watch for integer overflow
- if ((srcOffset > ByteLength (src) - count) || (dstOffset > ByteLength (dst) - count))
- throw new ArgumentException (Locale.GetText (
- "Offset and length were out of bounds for the array or count is greater than " +
- "the number of elements from index to the end of the source collection."));
- }
- }
-
- // private
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static int ByteLengthInternal (Array array);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static byte GetByteInternal (Array array, int index);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static void SetByteInternal (Array array, int index, int value);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal extern static bool BlockCopyInternal (Array src, int src_offset, Array dest, int dest_offset, int count);
-
- internal static bool InternalBlockCopy (Array src, int src_offset, Array dest, int dest_offset, int count)
- {
- return BlockCopyInternal (src, src_offset, dest, dest_offset, count);
- }
-
- internal unsafe static void ZeroMemory (byte* src, long len)
- {
- while(len-- > 0)
- *(src + len) = 0;
- }
-
- internal unsafe static void Memcpy (byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
- {
- Contract.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
- Contract.Assert(src.Length - srcIndex >= len, "not enough bytes in src");
- // If dest has 0 elements, the fixed statement will throw an
- // IndexOutOfRangeException. Special-case 0-byte copies.
- if (len==0)
- return;
- fixed(byte* pSrc = src) {
- Memcpy(pDest + destIndex, pSrc + srcIndex, len);
- }
- }
-
- internal unsafe static void Memcpy(byte[] dest, int destIndex, byte* src, int srcIndex, int len) {
- Contract.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
- Contract.Assert(dest.Length - destIndex >= len, "not enough bytes in dest");
- // If dest has 0 elements, the fixed statement will throw an
- // IndexOutOfRangeException. Special-case 0-byte copies.
- if (len==0)
- return;
- fixed(byte* pDest = dest) {
- Memcpy(pDest + destIndex, src + srcIndex, len);
- }
- }
-
- internal static unsafe void memcpy4 (byte *dest, byte *src, int size) {
- /*while (size >= 32) {
- // using long is better than int and slower than double
- // FIXME: enable this only on correct alignment or on platforms
- // that can tolerate unaligned reads/writes of doubles
- ((double*)dest) [0] = ((double*)src) [0];
- ((double*)dest) [1] = ((double*)src) [1];
- ((double*)dest) [2] = ((double*)src) [2];
- ((double*)dest) [3] = ((double*)src) [3];
- dest += 32;
- src += 32;
- size -= 32;
- }*/
- while (size >= 16) {
- ((int*)dest) [0] = ((int*)src) [0];
- ((int*)dest) [1] = ((int*)src) [1];
- ((int*)dest) [2] = ((int*)src) [2];
- ((int*)dest) [3] = ((int*)src) [3];
- dest += 16;
- src += 16;
- size -= 16;
- }
- while (size >= 4) {
- ((int*)dest) [0] = ((int*)src) [0];
- dest += 4;
- src += 4;
- size -= 4;
- }
- while (size > 0) {
- ((byte*)dest) [0] = ((byte*)src) [0];
- dest += 1;
- src += 1;
- --size;
- }
- }
- internal static unsafe void memcpy2 (byte *dest, byte *src, int size) {
- while (size >= 8) {
- ((short*)dest) [0] = ((short*)src) [0];
- ((short*)dest) [1] = ((short*)src) [1];
- ((short*)dest) [2] = ((short*)src) [2];
- ((short*)dest) [3] = ((short*)src) [3];
- dest += 8;
- src += 8;
- size -= 8;
- }
- while (size >= 2) {
- ((short*)dest) [0] = ((short*)src) [0];
- dest += 2;
- src += 2;
- size -= 2;
- }
- if (size > 0)
- ((byte*)dest) [0] = ((byte*)src) [0];
- }
- static unsafe void memcpy1 (byte *dest, byte *src, int size) {
- while (size >= 8) {
- ((byte*)dest) [0] = ((byte*)src) [0];
- ((byte*)dest) [1] = ((byte*)src) [1];
- ((byte*)dest) [2] = ((byte*)src) [2];
- ((byte*)dest) [3] = ((byte*)src) [3];
- ((byte*)dest) [4] = ((byte*)src) [4];
- ((byte*)dest) [5] = ((byte*)src) [5];
- ((byte*)dest) [6] = ((byte*)src) [6];
- ((byte*)dest) [7] = ((byte*)src) [7];
- dest += 8;
- src += 8;
- size -= 8;
- }
- while (size >= 2) {
- ((byte*)dest) [0] = ((byte*)src) [0];
- ((byte*)dest) [1] = ((byte*)src) [1];
- dest += 2;
- src += 2;
- size -= 2;
- }
- if (size > 0)
- ((byte*)dest) [0] = ((byte*)src) [0];
- }
-
- internal static unsafe void Memcpy (byte *dest, byte *src, int size) {
- // FIXME: if pointers are not aligned, try to align them
- // so a faster routine can be used. Handle the case where
- // the pointers can't be reduced to have the same alignment
- // (just ignore the issue on x86?)
- if ((((int)dest | (int)src) & 3) != 0) {
- if (((int)dest & 1) != 0 && ((int)src & 1) != 0 && size >= 1) {
- dest [0] = src [0];
- ++dest;
- ++src;
- --size;
- }
- if (((int)dest & 2) != 0 && ((int)src & 2) != 0 && size >= 2) {
- ((short*)dest) [0] = ((short*)src) [0];
- dest += 2;
- src += 2;
- size -= 2;
- }
- if ((((int)dest | (int)src) & 1) != 0) {
- memcpy1 (dest, src, size);
- return;
- }
- if ((((int)dest | (int)src) & 2) != 0) {
- memcpy2 (dest, src, size);
- return;
- }
- }
- memcpy4 (dest, src, size);
- }
- }
-}
+++ /dev/null
-//
-// System.CLSCompliantAttribute.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- /// <summary>
- /// Used to indicate if an element of a program is CLS compliant.
- /// </summary>
- [AttributeUsage (AttributeTargets.All)]
- [Serializable]
- [ComVisible (true)]
- public sealed class CLSCompliantAttribute : Attribute
- {
- bool is_compliant;
-
- public CLSCompliantAttribute (bool isCompliant)
- {
- this.is_compliant = isCompliant;
- }
-
- public bool IsCompliant {
- get {
- return is_compliant;
- }
- }
- }
-}
+++ /dev/null
-//
-// Comparison.cs
-//
-// Authors:
-// Ben Maurer (bmaurer@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell
-//
-// 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.
-//
-
-namespace System
-{
- public delegate int Comparison <in T> (T x, T y);
-}
-
+++ /dev/null
-//
-// System.ConsoleCancelEventArgs
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-
-namespace System {
- [Serializable]
- public sealed class ConsoleCancelEventArgs : EventArgs {
- bool cancel;
- ConsoleSpecialKey specialKey;
-
- internal ConsoleCancelEventArgs (ConsoleSpecialKey key)
- {
- specialKey = key;
- }
-
- public bool Cancel {
- get { return cancel; }
- set { cancel = value; }
- }
-
- public ConsoleSpecialKey SpecialKey {
- get { return specialKey; }
- }
- }
-}
-
+++ /dev/null
-//
-// System.ConsoleCancelEventHandler
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-namespace System {
- public delegate void ConsoleCancelEventHandler (object sender, ConsoleCancelEventArgs e);
-}
-
+++ /dev/null
-//
-// System.ConsoleColor
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-namespace System {
- [Serializable]
- public enum ConsoleColor {
- Black,
- DarkBlue,
- DarkGreen,
- DarkCyan,
- DarkRed,
- DarkMagenta,
- DarkYellow,
- Gray,
- DarkGray,
- Blue,
- Green,
- Cyan,
- Red,
- Magenta,
- Yellow,
- White
- }
-}
-
+++ /dev/null
-//
-// System.ConsoleKey
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-namespace System {
-
- [Serializable]
- public enum ConsoleKey {
- Backspace = 8,
- Tab = 9,
- Clear = 12,
- Enter = 13,
- Pause = 19,
- Escape = 27,
- Spacebar = 32,
- PageUp = 33,
- PageDown = 34,
- End = 35,
- Home = 36,
- LeftArrow = 37,
- UpArrow = 38,
- RightArrow = 39,
- DownArrow = 40,
- Select = 41,
- Print = 42,
- Execute = 43,
- PrintScreen = 44,
- Insert = 45,
- Delete = 46,
- Help = 47,
- D0 = 48,
- D1 = 49,
- D2 = 50,
- D3 = 51,
- D4 = 52,
- D5 = 53,
- D6 = 54,
- D7 = 55,
- D8 = 56,
- D9 = 57,
- A = 65,
- B = 66,
- C = 67,
- D = 68,
- E = 69,
- F = 70,
- G = 71,
- H = 72,
- I = 73,
- J = 74,
- K = 75,
- L = 76,
- M = 77,
- N = 78,
- O = 79,
- P = 80,
- Q = 81,
- R = 82,
- S = 83,
- T = 84,
- U = 85,
- V = 86,
- W = 87,
- X = 88,
- Y = 89,
- Z = 90,
- LeftWindows = 91,
- RightWindows = 92,
- Applications = 93,
- Sleep = 95,
- NumPad0 = 96,
- NumPad1 = 97,
- NumPad2 = 98,
- NumPad3 = 99,
- NumPad4 = 100,
- NumPad5 = 101,
- NumPad6 = 102,
- NumPad7 = 103,
- NumPad8 = 104,
- NumPad9 = 105,
- Multiply = 106,
- Add = 107,
- Separator = 108,
- Subtract = 109,
- Decimal = 110,
- Divide = 111,
- F1 = 112,
- F2 = 113,
- F3 = 114,
- F4 = 115,
- F5 = 116,
- F6 = 117,
- F7 = 118,
- F8 = 119,
- F9 = 120,
- F10 = 121,
- F11 = 122,
- F12 = 123,
- F13 = 124,
- F14 = 125,
- F15 = 126,
- F16 = 127,
- F17 = 128,
- F18 = 129,
- F19 = 130,
- F20 = 131,
- F21 = 132,
- F22 = 133,
- F23 = 134,
- F24 = 135,
- BrowserBack = 166,
- BrowserForward = 167,
- BrowserRefresh = 168,
- BrowserStop = 169,
- BrowserSearch = 170,
- BrowserFavorites = 171,
- BrowserHome = 172,
- VolumeMute = 173,
- VolumeDown = 174,
- VolumeUp = 175,
- MediaNext = 176,
- MediaPrevious = 177,
- MediaStop = 178,
- MediaPlay = 179,
- LaunchMail = 180,
- LaunchMediaSelect = 181,
- LaunchApp1 = 182,
- LaunchApp2 = 183,
- Oem1 = 186,
- OemPlus = 187,
- OemComma = 188,
- OemMinus = 189,
- OemPeriod = 190,
- Oem2 = 191,
- Oem3 = 192,
- Oem4 = 219,
- Oem5 = 220,
- Oem6 = 221,
- Oem7 = 222,
- Oem8 = 223,
- Oem102 = 226,
- Process = 229,
- Packet = 231,
- Attention = 246,
- CrSel = 247,
- ExSel = 248,
- EraseEndOfFile = 249,
- Play = 250,
- Zoom = 251,
- NoName = 252,
- Pa1 = 253,
- OemClear = 254,
- }
-}
-
+++ /dev/null
-//
-// System.ConsoleKeyInfo.cs
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-namespace System {
- [Serializable]
- public struct ConsoleKeyInfo {
- internal static ConsoleKeyInfo Empty = new ConsoleKeyInfo ('\0', 0, false, false, false);
- ConsoleKey _key;
- char _keyChar;
- ConsoleModifiers _mods;
-
- public ConsoleKeyInfo (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
- {
- _key = key;
- _keyChar = keyChar;
- _mods = 0;
- SetModifiers (shift, alt, control);
- }
-
- internal ConsoleKeyInfo (ConsoleKeyInfo other)
- {
- _key = other._key;
- _keyChar = other._keyChar;
- _mods = other._mods;
- }
-
- internal void SetKey (ConsoleKey key)
- {
- _key = key;
- }
-
- internal void SetKeyChar (char keyChar)
- {
- _keyChar = keyChar;
- }
-
- internal void SetModifiers (bool shift, bool alt, bool control)
- {
- _mods = (shift) ? ConsoleModifiers.Shift : 0;
- _mods |= (alt) ? ConsoleModifiers.Alt : 0;
- _mods |= (control) ? ConsoleModifiers.Control : 0;
- }
-
- public ConsoleKey Key
- {
- get { return _key; }
- }
-
- public char KeyChar
- {
- get { return _keyChar; }
- }
-
- public ConsoleModifiers Modifiers
- {
- get { return _mods; }
- }
-
- public override bool Equals (object value)
- {
- if (!(value is ConsoleKeyInfo))
- return false;
-
- return Equals ((ConsoleKeyInfo) value);
- }
-
- public static bool operator == (ConsoleKeyInfo a, ConsoleKeyInfo b)
- {
- return a.Equals (b);
- }
-
- public static bool operator != (ConsoleKeyInfo a, ConsoleKeyInfo b)
- {
- return !a.Equals (b);
- }
-
- public bool Equals (ConsoleKeyInfo obj)
- {
- return _key == obj._key && _keyChar == obj._keyChar && _mods == obj._mods;
- }
-
- public override int GetHashCode ()
- {
- return _key.GetHashCode () ^ _keyChar.GetHashCode () ^ _mods.GetHashCode ();
- }
- }
-}
+++ /dev/null
-//
-// System.ConsoleModifiers
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-namespace System {
- [Flags]
- [Serializable]
- public enum ConsoleModifiers {
- Alt = 1,
- Shift = 2,
- Control = 4
- }
-}
-
+++ /dev/null
-//
-// System.ConsoleSpecialKey
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2005 Novell, Inc (http://www.novell.com)
-//
-
-//
-// 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.
-//
-namespace System {
- [Serializable]
- public enum ConsoleSpecialKey {
- ControlC,
- ControlBreak
- }
-}
-
-
+++ /dev/null
-//
-// System.ContextBoundObject.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [Serializable]
- [ComVisible (true)]
- public abstract class ContextBoundObject : MarshalByRefObject
- {
- protected ContextBoundObject ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.ContextStaticAttribute.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- /// <summary>
- /// The ContextStatic attribute is used to flag fields as being unique
- /// </summary>
- [AttributeUsage (AttributeTargets.Field, Inherited=false)]
- [Serializable]
- [ComVisible (true)]
- public class ContextStaticAttribute : Attribute
- {
- public ContextStaticAttribute ()
- : base ()
- {
- }
- }
-}
+++ /dev/null
-//
-// Converter.cs
-//
-// Authors:
-// Ben Maurer (bmaurer@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell
-//
-// 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.
-//
-
-namespace System
-{
- public delegate TOutput Converter <in TInput, out TOutput> (TInput input);
-}
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 125;
+ private const int mono_corlib_version = 127;
#pragma warning restore 169
[ComVisible (true)]
+++ /dev/null
-//
-// System.EventArgs.cs
-//
-// Author:
-// Michael Lambert (michaellambert@email.com)
-//
-// (C) 2001 Michael Lambert, All Rights Reserved
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [Serializable]
- [ComVisible (true)]
- public class EventArgs
- {
- public static readonly EventArgs Empty = new EventArgs ();
-
- public EventArgs ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.EventHandler.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System {
-
- [Serializable]
- public delegate void EventHandler<TEventArgs> (object sender, TEventArgs e)
- ;
-
- [Serializable]
- [System.Runtime.InteropServices.ComVisible (true)]
- public delegate void EventHandler (object sender, EventArgs e);
-}
(vtable/MRGCTX) of the frames. */
IntPtr [] trace_ips;
Exception inner_exception;
- internal string message;
+ internal string _message;
string help_link;
string class_name;
string stack_trace;
public Exception (string message)
{
- this.message = message;
+ this._message = message;
}
protected Exception (SerializationInfo info, StreamingContext context)
throw new ArgumentNullException ("info");
class_name = info.GetString ("ClassName");
- message = info.GetString ("Message");
+ _message = info.GetString ("Message");
help_link = info.GetString ("HelpURL");
stack_trace = info.GetString ("StackTraceString");
_remoteStackTraceString = info.GetString ("RemoteStackTraceString");
public Exception (string message, Exception innerException)
{
inner_exception = innerException;
- this.message = message;
+ this._message = message;
}
public Exception InnerException {
internal void SetMessage (string s)
{
- message = s;
+ _message = s;
}
internal void SetStackTrace (string s)
public virtual string Message {
get {
- if (message == null)
- message = string.Format (Locale.GetText ("Exception of type '{0}' was thrown."),
+ if (_message == null)
+ _message = string.Format (Locale.GetText ("Exception of type '{0}' was thrown."),
ClassName);
- return message;
+ return _message;
}
}
throw new ArgumentNullException ("info");
info.AddValue ("ClassName", ClassName);
- info.AddValue ("Message", message);
+ info.AddValue ("Message", _message);
info.AddValue ("InnerException", inner_exception);
info.AddValue ("HelpURL", help_link);
info.AddValue ("StackTraceString", StackTrace);
// For ExceptionDispatchInfo
internal void RestoreExceptionDispatchInfo (System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
{
- if (captured_traces != null) {
- Array.Resize (ref captured_traces, captured_traces.Length + 1);
- } else {
- captured_traces = new StackTrace [1];
- }
- captured_traces [captured_traces.Length - 1] = new StackTrace (this, 0, true, true);
-
+ captured_traces = (StackTrace[]) exceptionDispatchInfo.BinaryStackTraceArray;
trace_ips = null;
}
+++ /dev/null
-//
-// System.FlagsAttribute.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- /// <summary>
- /// The FlagsAttribute tags enumerations as bitfields.
- /// </summary>
- ///
- /// <remarks>
- /// The FlagsAttribute can be used to tag an enumeration to be
- /// a bit field. This will allow the compiler and visual tools
- /// to treat the bits in an enumeration as a set of flags.
- /// </remarks>
-
- [AttributeUsage (AttributeTargets.Enum, Inherited=false)]
- [Serializable]
- [ComVisible (true)]
- public class FlagsAttribute : Attribute {
-
- // No methods.
-
- }
-}
+++ /dev/null
-//
-// System.Func.cs
-//
-// Authors:
-// Alejandro Serrano "Serras" (trupill@yahoo.es)
-// Marek Safar (marek.safar@gmail.com)
-//
-
-// 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 TArg 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
-//
-
-using System.Runtime.CompilerServices;
-
-namespace System {
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate TResult Func<out TResult> ();
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate TResult Func<in T, out TResult> (T arg);
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate TResult Func<in T1, in T2, out TResult> (T1 arg1, T2 arg2);
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate TResult Func<in T1, in T2, in T3, out TResult> (T1 arg1, T2 arg2, T3 arg3);
-
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public delegate TResult Func<in T1, in T2, in T3, in T4, out TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4);
-
- public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, out TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
- public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, out TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
- public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, out TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
- public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, out TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
-}
// 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 !MONOTOUCH
+#if !(MONOTOUCH && FULL_AOT_RUNTIME)
using System.Security.Cryptography;
+++ /dev/null
-//
-// System.IAppDomainSetup.cs
-//
-// Author:
-// Dietmar Maurer (dietmar@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
- [Guid ("27FFF232-A7A8-40DD-8D4A-734AD59FCD41")]
- [ComVisible(true)]
- public interface IAppDomainSetup {
-
- string ApplicationBase { get; set; }
-
- string ApplicationName { get; set; }
-
- string CachePath { get; set; }
-
- string ConfigurationFile { get; set; }
-
- string DynamicBase { get; set; }
-
- string LicenseFile { get; set; }
-
- string PrivateBinPath { get; set; }
-
- string PrivateBinPathProbe { get; set; }
-
- string ShadowCopyDirectories { get; set; }
-
- string ShadowCopyFiles { get; set; }
- }
-}
+++ /dev/null
-//
-// System.IApplicationDescription interface
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System {
-
- public interface IApplicationDescription : ICloneable {
-
- string ApplicationCodeBase {
- get;
- }
-
- string ApplicationManifest {
- get;
- }
-
- string ApplicationManifestPath {
- get;
- }
-
- string DeploymentCodeBase {
- get;
- }
-
- string DeploymentManifest {
- get;
- }
-
- string DeploymentManifestPath {
- get;
- }
- }
-}
+++ /dev/null
-//------------------------------------------------------------------------------
-//
-// System.IAsyncResult.cs
-//
-// Copyright (C) 2001 Michael Lambert, All Rights Reserved
-//
-// Author: Michael Lambert, michaellambert@email.com
-// Created: Mon 08/24/2001
-//
-//------------------------------------------------------------------------------
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System;
-using System.Threading;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- public interface IAsyncResult
- {
- object AsyncState
- {
- get;
- }
-
- WaitHandle AsyncWaitHandle
- {
- get;
- }
-
- bool CompletedSynchronously
- {
- get;
- }
-
- bool IsCompleted
- {
- get;
- }
- }
-
-} // Namespace System
-
-
+++ /dev/null
-//
-// System.ICloneable.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
- [ComVisible(true)]
-#if INSIDE_CORLIB
- public
-#else
- internal
-#endif
- interface ICloneable {
- object Clone ();
- }
-}
+++ /dev/null
-//
-// System.IComparable.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- public interface IComparable {
- int CompareTo (object obj);
- }
-
- public interface IComparable <in T> {
- int CompareTo (T other);
- }
-}
+++ /dev/null
-//
-// System.IConvertible.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-//
-// Functions Implementing this interface should check out
-// System.Convert. Most of these methods are implemented
-// there for all these data types.
-//
-// System.Convert has ToType helper method for the object
-// ToType (Type conversionType, IFormatProvider provider)
-// method. In most cases you can specify your ToType function
-// as calling
-//
-// public Type value; // value of this data type
-// public object ToType(Type conversionType, IFormatProvider provider) {
-// Convert.ToType (value, conversionType, provider);
-// }
-//
-// Which is just a wrapper for your ToType methods.
-//
-// See http://lists.ximian.com/archives/public/mono-list/2001-July/000525.html
-// for more discussion on the topic
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- [CLSCompliant(false)]
- public interface IConvertible {
-
- TypeCode GetTypeCode ();
-
- bool ToBoolean (IFormatProvider provider);
- byte ToByte (IFormatProvider provider);
- char ToChar (IFormatProvider provider);
- DateTime ToDateTime (IFormatProvider provider);
- decimal ToDecimal (IFormatProvider provider);
- double ToDouble (IFormatProvider provider);
- short ToInt16 (IFormatProvider provider);
- int ToInt32 (IFormatProvider provider);
- long ToInt64 (IFormatProvider provider);
- sbyte ToSByte (IFormatProvider provider);
- float ToSingle (IFormatProvider provider);
- string ToString (IFormatProvider provider);
- object ToType (Type conversionType, IFormatProvider provider);
- ushort ToUInt16 (IFormatProvider provider);
- uint ToUInt32 (IFormatProvider provider);
- ulong ToUInt64 (IFormatProvider provider);
- }
-}
+++ /dev/null
-//
-// System.ICustomFormatter.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- public interface ICustomFormatter {
- string Format (string format, object arg, IFormatProvider formatProvider);
- }
-}
+++ /dev/null
-//
-// System.IDisposable.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- public interface IDisposable {
-
- void Dispose ();
-
- }
-}
+++ /dev/null
-//
-// System.IEquatable.cs
-//
-// Author:
-// Ben Maurer <bmaurer@novell.com>
-//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System {
- public interface IEquatable <T> {
- bool Equals (T other);
- }
-}
+++ /dev/null
-//
-// System.IFormatProvider.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- public interface IFormatProvider {
- object GetFormat (Type formatType);
- }
-}
+++ /dev/null
-//
-// System.IFormattable.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System {
-
- [ComVisible(true)]
- public interface IFormattable {
- string ToString (string format, IFormatProvider formatProvider);
- }
-}
+++ /dev/null
-//
-// System.IHostContext interface
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-namespace System {
-
- public interface IHostContext {
-
- bool AssumeTrust {
- get;
- }
-
- bool ExclusiveGrant {
- get;
- }
-
- bool IsFirstTimeInstall {
- get;
- }
-
- bool NoPrompt {
- get;
- }
-
- bool Persist {
- get;
- }
- }
-}
+++ /dev/null
-//
-// IObservable.cs
-//
-// Authors:
-// Marek Safar <marek.safar@gmail.com>
-//
-// Copyright (C) 2009 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-
-namespace System
-{
- public interface IObservable<out T>
- {
- IDisposable Subscribe (IObserver<T> observer);
- }
-}
-
+++ /dev/null
-//
-// IObserver.cs
-//
-// Authors:
-// Marek Safar <marek.safar@gmail.com>
-//
-// Copyright (C) 2009 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-
-namespace System
-{
- public interface IObserver<in T>
- {
- void OnCompleted ();
- void OnError (Exception error);
- void OnNext(T value);
- }
-}
-
+++ /dev/null
-//
-// IProgress.cs
-//
-// Authors:
-// Marek Safar <marek.safar@gmail.com>
-//
-// Copyright (C) 2011 Xamarin, Inc (http://www.xamarin.com)
-//
-// 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.
-//
-
-
-namespace System
-{
- public interface IProgress<in T>
- {
- void Report (T value);
- }
-}
-
+++ /dev/null
-//
-// System.IServiceProvider.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.InteropServices;
-
-namespace System
-{
- public interface IServiceProvider
- {
- object GetService (Type serviceType);
- }
-}
+++ /dev/null
-/*
- * System.InvalidimeZoneException
- *
- * Author(s)
- * Stephane Delcroix <stephane@delcroix.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.
- */
-
-using System.Runtime.CompilerServices;
-
-namespace System
-{
- [Serializable]
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public
- class InvalidTimeZoneException : Exception
- {
- public InvalidTimeZoneException () : base ()
- {}
-
- public InvalidTimeZoneException (string message) : base (message)
- {}
-
- public InvalidTimeZoneException (string message, Exception innerException) : base (message, innerException)
- {}
-
- protected InvalidTimeZoneException (Runtime.Serialization.SerializationInfo info, Runtime.Serialization.StreamingContext context) : base (info, context)
- {}
- }
-}
+++ /dev/null
-//
-// System.LoaderOptimization.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [ComVisible (true)]
- [Serializable]
- public enum LoaderOptimization
- {
- NotSpecified = 0,
- SingleDomain = 1,
- MultiDomain = 2,
- MultiDomainHost = 3,
-
- [Obsolete]
- DomainMask = 3,
-
- [Obsolete]
- DisallowBindings = 4
- }
-}
+++ /dev/null
-//
-// System.LoaderOptimizationAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [AttributeUsage (AttributeTargets.Method)]
- [ComVisible (true)]
- public sealed class LoaderOptimizationAttribute : Attribute
- {
- private LoaderOptimization lo;
-
- // Constructors
- public LoaderOptimizationAttribute (byte value)
- {
- lo = (LoaderOptimization) value;
- }
-
- public LoaderOptimizationAttribute (LoaderOptimization value)
- {
- lo = value;
- }
-
- // Properties
- public LoaderOptimization Value {
- get { return lo; }
- }
- }
-}
+++ /dev/null
-//
-// System.MTAThreadAttribute.cs
-//
-// Author: Duncan Mak (duncan@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [AttributeUsage (AttributeTargets.Method)]
- [ComVisible (true)]
- public sealed class MTAThreadAttribute : Attribute
- {
- // Constructors
- public MTAThreadAttribute () : base ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.NonSerializedAttribute.cs
-//
-// Author:
-// Paolo Molaro (lupus@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [ComVisible (true)]
- [AttributeUsage (AttributeTargets.Field, Inherited=false)]
- public sealed class NonSerializedAttribute : Attribute
- {
- public NonSerializedAttribute ()
- {
- }
- }
-}
using System.Runtime.InteropServices;
using System.Text;
namespace System {
- class NullConsoleDriver : IConsoleDriver {
+ class NullConsoleDriver : IConsoleDriver
+ {
+ static readonly ConsoleKeyInfo EmptyConsoleKeyInfo = new ConsoleKeyInfo ('\0', 0, false, false, false);
+
public ConsoleColor BackgroundColor {
get { return ConsoleColor.Black; }
set {
public ConsoleKeyInfo ReadKey (bool intercept)
{
- return ConsoleKeyInfo.Empty;
+ return EmptyConsoleKeyInfo;
}
public void ResetColor ()
+++ /dev/null
-//
-// System.ObsoleteAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct |
- AttributeTargets.Enum | AttributeTargets.Constructor |
- AttributeTargets.Method | AttributeTargets.Property |
- AttributeTargets.Field | AttributeTargets.Event |
- AttributeTargets.Interface | AttributeTargets.Delegate,
- Inherited=false)]
- [Serializable]
- [ComVisible (true)]
- public sealed class ObsoleteAttribute : Attribute
- {
- private string _message;
- private bool _error;
-
- // Constructors
- public ObsoleteAttribute ()
- : base ()
- {
- }
-
- public ObsoleteAttribute (string message)
- {
- _message = message;
- }
-
- public ObsoleteAttribute (string message, bool error)
- {
- _message = message;
- _error = error;
- }
-
- // Properties
- public string Message {
- get { return _message; }
- }
-
- public bool IsError {
- get { return _error; }
- }
- }
-}
+++ /dev/null
-//
-// System.ParamArrayAttribute.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- /// <summary>
- /// Used to flag that the method will take a variable number
- /// of arguments
- /// </summary>
- [AttributeUsage (AttributeTargets.Parameter)]
- [ComVisible (true)]
- public sealed class ParamArrayAttribute : Attribute
- {
- public ParamArrayAttribute ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.Predicate.cs
-//
-// Authors:
-// Ben Maurer (bmaurer@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell
-//
-// 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.
-//
-
-namespace System
-{
- public delegate bool Predicate <in T> (T obj);
-}
-
+++ /dev/null
-//
-// System.STAThreadAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [AttributeUsage (AttributeTargets.Method)]
- [ComVisible (true)]
- public sealed class STAThreadAttribute : Attribute
- {
- // Constructors
- public STAThreadAttribute ()
- : base ()
- {
- }
- }
-}
+++ /dev/null
-//
-// System.SerializableAttribute.cs
-//
-// Author:
-// Miguel de Icaza (miguel@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- /// <summary>
- /// Serialization Attribute for classes.
- /// </summary>
-
- /// <remarks>
- /// Use SerializableAttribute to mark classes that do not implement
- /// the ISerializable interface but that want to be serialized.
- ///
- /// Failing to do so will cause the system to throw an exception.
- ///
- /// When a class is market with the SerializableAttribute, all the
- /// fields are automatically serialized with the exception of those
- /// that are tagged with the NonSerializedAttribute.
- ///
- /// SerializableAttribute should only be used for classes that contain
- /// simple data types that can be serialized and deserialized by the
- /// runtime (typically you would use NonSerializedAttribute on data
- /// that can be reconstructed at any point: like caches or precomputed
- /// tables).
- /// </remarks>
-
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
- | AttributeTargets.Enum | AttributeTargets.Delegate,
- Inherited=false)]
- [ComVisible (true)]
- public sealed class SerializableAttribute : Attribute
- {
- }
-}
length++;
byte [] result = new byte [length];
- Buffer.BlockCopyInternal (buffer, offset, result, 0, length);
+ Buffer.InternalBlockCopy (buffer, offset, result, 0, length);
return result;
}
+++ /dev/null
-//
-// System.ThreadStaticAttribute.cs
-//
-// Author:
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [AttributeUsage (AttributeTargets.Field, Inherited=false)]
- [Serializable]
- [ComVisible (true)]
- public class ThreadStaticAttribute : Attribute
- {
- // Constructors
- public ThreadStaticAttribute ()
- : base ()
- {
- }
- }
-}
+++ /dev/null
-/*
- * System.TimeZoneInfo.AdjustmentRule
- *
- * Author(s)
- * Stephane Delcroix <stephane@delcroix.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.
- */
-
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-
-namespace System
-{
- public
- sealed partial class TimeZoneInfo {
- [SerializableAttribute]
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public sealed class AdjustmentRule : IEquatable<TimeZoneInfo.AdjustmentRule>, ISerializable, IDeserializationCallback
- {
- DateTime dateEnd;
- public DateTime DateEnd {
- get { return dateEnd; }
- }
-
- DateTime dateStart;
- public DateTime DateStart {
- get { return dateStart; }
- }
-
- TimeSpan daylightDelta;
- public TimeSpan DaylightDelta {
- get { return daylightDelta; }
- }
-
- TransitionTime daylightTransitionEnd;
- public TransitionTime DaylightTransitionEnd {
- get { return daylightTransitionEnd; }
- }
-
- TransitionTime daylightTransitionStart;
- public TransitionTime DaylightTransitionStart {
- get { return daylightTransitionStart; }
- }
-
- public static AdjustmentRule CreateAdjustmentRule (
- DateTime dateStart,
- DateTime dateEnd,
- TimeSpan daylightDelta,
- TransitionTime daylightTransitionStart,
- TransitionTime daylightTransitionEnd)
- {
- return new AdjustmentRule (dateStart, dateEnd, daylightDelta, daylightTransitionStart, daylightTransitionEnd);
- }
-
- private AdjustmentRule (SerializationInfo info, StreamingContext context)
- {
- if (info == null)
- throw new ArgumentNullException ("info");
- dateStart = (DateTime) info.GetValue ("DateStart", typeof (DateTime));
- dateEnd = (DateTime) info.GetValue ("DateEnd", typeof (DateTime));
- daylightDelta = (TimeSpan) info.GetValue ("DaylightDelta", typeof (TimeSpan));
- daylightTransitionStart = (TimeZoneInfo.TransitionTime) info.GetValue ("DaylightTransitionStart", typeof (TimeZoneInfo.TransitionTime));
- daylightTransitionEnd = (TimeZoneInfo.TransitionTime) info.GetValue ("DaylightTransitionEnd", typeof (TimeZoneInfo.TransitionTime));
- }
-
- private AdjustmentRule (
- DateTime dateStart,
- DateTime dateEnd,
- TimeSpan daylightDelta,
- TransitionTime daylightTransitionStart,
- TransitionTime daylightTransitionEnd)
- {
- if (dateStart.Kind != DateTimeKind.Unspecified || dateEnd.Kind != DateTimeKind.Unspecified)
- throw new ArgumentException ("the Kind property of dateStart or dateEnd parameter does not equal DateTimeKind.Unspecified");
-
- if (daylightTransitionStart == daylightTransitionEnd)
- throw new ArgumentException ("daylightTransitionStart parameter cannot equal daylightTransitionEnd parameter");
-
- if (dateStart.Ticks % TimeSpan.TicksPerDay != 0 || dateEnd.Ticks % TimeSpan.TicksPerDay != 0)
- throw new ArgumentException ("dateStart or dateEnd parameter includes a time of day value");
-
- if (dateEnd < dateStart)
- throw new ArgumentOutOfRangeException ("dateEnd is earlier than dateStart");
-
- if (daylightDelta > new TimeSpan (14, 0, 0) || daylightDelta < new TimeSpan (-14, 0, 0))
- throw new ArgumentOutOfRangeException ("daylightDelta is less than -14 or greater than 14 hours");
-
- if (daylightDelta.Ticks % TimeSpan.TicksPerSecond != 0)
- throw new ArgumentOutOfRangeException ("daylightDelta parameter does not represent a whole number of seconds");
-
- this.dateStart = dateStart;
- this.dateEnd = dateEnd;
- this.daylightDelta = daylightDelta;
- this.daylightTransitionStart = daylightTransitionStart;
- this.daylightTransitionEnd = daylightTransitionEnd;
- }
-
- public bool Equals (TimeZoneInfo.AdjustmentRule other)
- {
- return dateStart == other.dateStart &&
- dateEnd == other.dateEnd &&
- daylightDelta == other.daylightDelta &&
- daylightTransitionStart == other.daylightTransitionStart &&
- daylightTransitionEnd == other.daylightTransitionEnd;
- }
-
- public override int GetHashCode ()
- {
- return dateStart.GetHashCode () ^
- dateEnd.GetHashCode () ^
- daylightDelta.GetHashCode () ^
- daylightTransitionStart.GetHashCode () ^
- daylightTransitionEnd.GetHashCode ();
- }
-
- void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
- {
- if (info == null)
- throw new ArgumentNullException ("info");
- info.AddValue ("DateStart", DateStart);
- info.AddValue ("DateEnd", DateEnd);
- info.AddValue ("DaylightDelta", DaylightDelta);
- info.AddValue ("DaylightTransitionStart", DaylightTransitionStart);
- info.AddValue ("DaylightTransitionEnd", DaylightTransitionEnd);
- }
- void IDeserializationCallback.OnDeserialization (object sender)
- {
- try {
- TimeZoneInfo.AdjustmentRule.Validate (dateStart, dateEnd, daylightDelta,
- daylightTransitionStart, daylightTransitionEnd);
- } catch (ArgumentException ex) {
- throw new SerializationException ("invalid serialization data", ex);
- }
- }
-
- private static void Validate (
- DateTime dateStart,
- DateTime dateEnd,
- TimeSpan daylightDelta,
- TransitionTime daylightTransitionStart,
- TransitionTime daylightTransitionEnd)
- {
- if (dateStart.Kind != DateTimeKind.Unspecified || dateEnd.Kind != DateTimeKind.Unspecified)
- throw new ArgumentException ("the Kind property of dateStart or dateEnd parameter does not equal DateTimeKind.Unspecified");
-
- if (daylightTransitionStart == daylightTransitionEnd)
- throw new ArgumentException ("daylightTransitionStart parameter cannot equal daylightTransitionEnd parameter");
-
- if (dateStart.Ticks % TimeSpan.TicksPerDay != 0 || dateEnd.Ticks % TimeSpan.TicksPerDay != 0)
- throw new ArgumentException ("dateStart or dateEnd parameter includes a time of day value");
-
- if (dateEnd < dateStart)
- throw new ArgumentOutOfRangeException ("dateEnd is earlier than dateStart");
-
- if (daylightDelta > new TimeSpan (14, 0, 0) || daylightDelta < new TimeSpan (-14, 0, 0))
- throw new ArgumentOutOfRangeException ("daylightDelta is less than -14 or greater than 14 hours");
-
- if (daylightDelta.Ticks % TimeSpan.TicksPerSecond != 0)
- throw new ArgumentOutOfRangeException ("daylightDelta parameter does not represent a whole number of seconds");
- }
- }
- }
-}
+++ /dev/null
-/*
- * System.TimeZoneInfo.TransitionTime
- *
- * Author(s)
- * Stephane Delcroix <stephane@delcroix.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.
- */
-
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-
-namespace System
-{
- public
- sealed partial class TimeZoneInfo
- {
- [SerializableAttribute]
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public struct TransitionTime : IEquatable<TimeZoneInfo.TransitionTime>, ISerializable, IDeserializationCallback
- {
- DateTime timeOfDay;
- public DateTime TimeOfDay {
- get { return timeOfDay; }
- }
-
- int month;
- public int Month {
- get { return month; }
- }
-
- int day;
- public int Day {
- get {
-#if STRICT
- if (!isFixedDateRule)
- throw new Exception ("Day property is not valid for floating date rules");
-#endif
- return day;
- }
- }
-
- int week;
- public int Week {
- get {
-#if STRICT
- if (isFixedDateRule)
- throw new Exception ("Week property is not valid for fixed date rules");
-#endif
-
- return week;
- }
- }
-
- DayOfWeek dayOfWeek;
- public DayOfWeek DayOfWeek {
- get {
-#if STRICT
- if (isFixedDateRule)
- throw new Exception ("DayOfWeek property is not valid for fixed date rules");
-#endif
-
- return dayOfWeek;
- }
- }
-
- bool isFixedDateRule;
- public bool IsFixedDateRule {
- get { return isFixedDateRule; }
- }
-
- public static TransitionTime CreateFixedDateRule (
- DateTime timeOfDay,
- int month,
- int day)
- {
- return new TransitionTime (timeOfDay, month, day);
- }
-
- public static TransitionTime CreateFloatingDateRule (
- DateTime timeOfDay,
- int month,
- int week,
- DayOfWeek dayOfWeek)
- {
- return new TransitionTime (timeOfDay, month, week, dayOfWeek);
- }
-
- private TransitionTime (SerializationInfo info, StreamingContext context)
- {
- if (info == null)
- throw new ArgumentNullException ("info");
- timeOfDay = (DateTime) info.GetValue ("TimeOfDay", typeof (DateTime));
- month = (byte) info.GetValue ("Month", typeof (byte));
- week = (byte) info.GetValue ("Week", typeof (byte));
- day = (byte) info.GetValue ("Day", typeof (byte));
- dayOfWeek = (DayOfWeek) info.GetValue ("DayOfWeek", typeof (DayOfWeek));
- isFixedDateRule = (bool) info.GetValue ("IsFixedDateRule", typeof (bool));
-
- if (isFixedDateRule)
- {
- week = -1;
- dayOfWeek = (DayOfWeek) (-1);
- }
- if (!isFixedDateRule)
- day = -1;
- }
-
- private TransitionTime (
- DateTime timeOfDay,
- int month,
- int day) : this (timeOfDay, month)
- {
- if (day < 1 || day > 31)
- throw new ArgumentOutOfRangeException ("day parameter is less than 1 or greater than 31");
-
- this.day = day;
- this.isFixedDateRule = true;
- }
-
- private TransitionTime (
- DateTime timeOfDay,
- int month,
- int week,
- DayOfWeek dayOfWeek) : this (timeOfDay, month)
- {
- if (week < 1 || week > 5)
- throw new ArgumentOutOfRangeException ("week parameter is less than 1 or greater than 5");
-
- if (dayOfWeek != DayOfWeek.Sunday &&
- dayOfWeek != DayOfWeek.Monday &&
- dayOfWeek != DayOfWeek.Tuesday &&
- dayOfWeek != DayOfWeek.Wednesday &&
- dayOfWeek != DayOfWeek.Thursday &&
- dayOfWeek != DayOfWeek.Friday &&
- dayOfWeek != DayOfWeek.Saturday)
- throw new ArgumentOutOfRangeException ("dayOfWeek parameter is not a member od DayOfWeek enumeration");
-
- this.week = week;
- this.dayOfWeek = dayOfWeek;
- this.isFixedDateRule = false;
- }
-
- private TransitionTime (
- DateTime timeOfDay,
- int month)
- {
- if (timeOfDay.Year != 1 || timeOfDay.Month != 1 || timeOfDay.Day != 1)
- throw new ArgumentException ("timeOfDay parameter has a non-default date component");
-
- if (timeOfDay.Kind != DateTimeKind.Unspecified)
- throw new ArgumentException ("timeOfDay parameter Kind's property is not DateTimeKind.Unspecified");
-
- if (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0)
- throw new ArgumentException ("timeOfDay parameter does not represent a whole number of milliseconds");
-
- if (month < 1 || month > 12)
- throw new ArgumentOutOfRangeException ("month parameter is less than 1 or greater than 12");
-
- this.timeOfDay = timeOfDay;
- this.month = month;
-
- this.week = -1;
- this.dayOfWeek = (System.DayOfWeek)(-1);
- this.day = -1;
- this.isFixedDateRule = false;
- }
-
- public static bool operator == (TransitionTime t1, TransitionTime t2)
- {
- return ( t1.day == t2.day &&
- t1.dayOfWeek == t2.dayOfWeek &&
- t1.isFixedDateRule == t2.isFixedDateRule &&
- t1.month == t2.month &&
- t1.timeOfDay == t2.timeOfDay &&
- t1.week == t2.week);
- }
-
- public static bool operator != (TransitionTime t1, TransitionTime t2)
- {
- return !(t1 == t2);
- }
-
-
- void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
- {
- if (info == null)
- throw new ArgumentNullException ("info");
- info.AddValue ("TimeOfDay", TimeOfDay);
- info.AddValue ("Month", System.Convert.ToByte(Month));
- if (week > -1)
- info.AddValue ("Week", System.Convert.ToByte(week));
- else
- info.AddValue ("Week", (byte) 1);
- if (day > -1)
- info.AddValue ("Day", System.Convert.ToByte(day));
- else
- info.AddValue ("Day", (byte) 1);
- if (dayOfWeek != ((System.DayOfWeek) (-1)))
- info.AddValue ("DayOfWeek", dayOfWeek);
- else
- info.AddValue ("DayOfWeek", DayOfWeek.Sunday);
- info.AddValue ("IsFixedDateRule", IsFixedDateRule);
- }
-
- public override bool Equals (object obj)
- {
- if (obj is TransitionTime)
- return this == (TransitionTime) obj;
- return false;
- }
-
- public bool Equals (TimeZoneInfo.TransitionTime other)
- {
- return this == other;
- }
-
- public override int GetHashCode ()
- {
- return (day ^ (int)dayOfWeek ^ month ^ (int)timeOfDay.Ticks ^ week);
- }
-
- void IDeserializationCallback.OnDeserialization (object sender)
- {
- try {
- TimeZoneInfo.TransitionTime.Validate (timeOfDay, month, week, day, dayOfWeek, isFixedDateRule);
- } catch (ArgumentException ex) {
- throw new SerializationException ("invalid serialization data", ex);
- }
- }
-
- private static void Validate (DateTime timeOfDay, int month,int week, int day, DayOfWeek dayOfWeek, bool isFixedDateRule)
- {
- if (timeOfDay.Year != 1 || timeOfDay.Month != 1 || timeOfDay.Day != 1)
- throw new ArgumentException ("timeOfDay parameter has a non-default date component");
-
- if (timeOfDay.Kind != DateTimeKind.Unspecified)
- throw new ArgumentException ("timeOfDay parameter Kind's property is not DateTimeKind.Unspecified");
-
- if (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0)
- throw new ArgumentException ("timeOfDay parameter does not represent a whole number of milliseconds");
-
- if (day < 1 || day > 31) {
- if (!(!isFixedDateRule && day == -1))
- throw new ArgumentOutOfRangeException ("day parameter is less than 1 or greater than 31");
- }
-
- if (week < 1 || week > 5) {
- if (!(isFixedDateRule && week == -1))
- throw new ArgumentOutOfRangeException ("week parameter is less than 1 or greater than 5");
- }
-
- if (month < 1 || month > 12)
- throw new ArgumentOutOfRangeException ("month parameter is less than 1 or greater than 12");
-
- if (dayOfWeek != DayOfWeek.Sunday &&
- dayOfWeek != DayOfWeek.Monday &&
- dayOfWeek != DayOfWeek.Tuesday &&
- dayOfWeek != DayOfWeek.Wednesday &&
- dayOfWeek != DayOfWeek.Thursday &&
- dayOfWeek != DayOfWeek.Friday &&
- dayOfWeek != DayOfWeek.Saturday) {
- if (!(isFixedDateRule && dayOfWeek == (DayOfWeek) (-1)))
- throw new ArgumentOutOfRangeException ("dayOfWeek parameter is not a member od DayOfWeek enumeration");
- }
- }
- }
- }
-}
namespace System
{
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- [SerializableAttribute]
- public
- sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
+ partial class TimeZoneInfo
{
TimeSpan baseUtcOffset;
public TimeSpan BaseUtcOffset {
+++ /dev/null
-/*
- * System.TimeZoneNotFoundException
- *
- * Author(s)
- * Stephane Delcroix <stephane@delcroix.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.
- */
-
-
-using System.Runtime.CompilerServices;
-
-namespace System
-{
- [Serializable]
-#if MOBILE
- [TypeForwardedFrom (Consts.AssemblySystem_Core)]
-#else
- [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
-#endif
- public
- class TimeZoneNotFoundException : Exception
- {
- public TimeZoneNotFoundException () : base ()
- {}
-
- public TimeZoneNotFoundException (string message) : base (message)
- {}
-
- public TimeZoneNotFoundException (string message, Exception innerException) : base (message, innerException)
- {}
-
- protected TimeZoneNotFoundException (Runtime.Serialization.SerializationInfo info, Runtime.Serialization.StreamingContext context) : base (info, context)
- {}
- }
-}
+++ /dev/null
-//
-// System.TypeLoadException.cs
-//
-// Authors:
-// Sean MacIsaac (macisaac@ximian.com)
-// Duncan Mak (duncan@ximian.com)
-//
-// (C) 2001 Ximian, Inc. http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// 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.
-//
-
-using System.Runtime.Serialization;
-using System.Runtime.InteropServices;
-
-namespace System
-{
- [Serializable]
- [ComVisible (true)]
- [StructLayout (LayoutKind.Sequential)]
- public class TypeLoadException : SystemException
- {
- const int Result = unchecked ((int)0x80131522);
-
- // Fields
- private string className, assemblyName;
-
- // Constructors
- public TypeLoadException ()
- : base (Locale.GetText ("A type load exception has occurred."))
- {
- HResult = Result;
- }
-
- public TypeLoadException (string message)
- : base (message)
- {
- HResult = Result;
- }
-
- public TypeLoadException (string message, Exception inner)
- : base (message, inner)
- {
- HResult = Result;
- }
-
- internal TypeLoadException (string className, string assemblyName) : this ()
- {
- this.className = className;
- this.assemblyName = assemblyName;
- }
-
- protected TypeLoadException (SerializationInfo info, StreamingContext context)
- : base (info, context)
- {
- if (info == null)
- throw new ArgumentNullException ("info");
-
- className = info.GetString ("TypeLoadClassName");
- assemblyName = info.GetString ("TypeLoadAssemblyName");
- }
-
- // Properties
- public override string Message {
- get {
- if (className != null) {
- if ((assemblyName != null) && (assemblyName != String.Empty))
- return String.Format ("Could not load type '{0}' from assembly '{1}'.", className, assemblyName);
- else
- return String.Format ("Could not load type '{0}'.", className);
- }
- else
- return base.Message;
- }
- }
-
- public string TypeName {
- get {
- if (className == null)
- return String.Empty;
- else
- return className;
- }
- }
-
- // Methods
- public override void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- if (info == null)
- throw new ArgumentNullException ("info");
-
- base.GetObjectData (info, context);
- info.AddValue ("TypeLoadClassName", className, typeof (string));
- info.AddValue ("TypeLoadAssemblyName", assemblyName, typeof (string));
- info.AddValue ("TypeLoadMessageArg", "", typeof (string));
- info.AddValue ("TypeLoadResourceID", 0, typeof (int));
- }
- }
-}
}
}
+#if !MONO
+ [Test]
+ public void SerializationCompatibilty ()
+ {
+ /* Serialization output from .net
+
+ var dict = new Dictionary<string, string> ();
+ dict.Add ("key", "value");
+
+ var dictSerializedStream = new MemoryStream ();
+ fmt.Serialize (dictSerializedStream, dict);
+
+ dictSerializedStream.Seek (0, SeekOrigin.Begin);
+ var res = Convert.ToBase64String (dictSerializedStream.ToArray (), Base64FormattingOptions.InsertLineBreaks);
+
+ */
+
+ var x = "AAEAAAD/////AQAAAAAAAAAEAQAAAOIBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuRGljdGlv" +
+ "bmFyeWAyW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJl" +
+ "PW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uU3RyaW5n" +
+ "LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRv" +
+ "a2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAHVmVyc2lvbghDb21wYXJlcghIYXNoU2l6ZQ1LZXlW" +
+ "YWx1ZVBhaXJzAAMAAwiSAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkdlbmVyaWNFcXVhbGl0" +
+ "eUNvbXBhcmVyYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1" +
+ "bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCOYBU3lzdGVt" +
+ "LkNvbGxlY3Rpb25zLkdlbmVyaWMuS2V5VmFsdWVQYWlyYDJbW1N5c3RlbS5TdHJpbmcsIG1zY29y" +
+ "bGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3" +
+ "YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAs" +
+ "IEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dW10BAAAA" +
+ "CQIAAAADAAAACQMAAAAEAgAAAJIBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuR2VuZXJpY0Vx" +
+ "dWFsaXR5Q29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAu" +
+ "MCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0AAAAA" +
+ "BwMAAAAAAQAAAAEAAAAD5AFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5LZXlWYWx1ZVBhaXJg" +
+ "MltbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0" +
+ "cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XSxbU3lzdGVtLlN0cmluZywgbXNj" +
+ "b3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1i" +
+ "NzdhNWM1NjE5MzRlMDg5XV0E/P///+QBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuS2V5VmFs" +
+ "dWVQYWlyYDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1" +
+ "cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJp" +
+ "bmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5" +
+ "VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAgAAAANrZXkFdmFsdWUBAQYFAAAAA2tleQYGAAAABXZh" +
+ "bHVlCw==";
+
+ var dict = new Dictionary<string, string> ();
+ dict.Add ("key", "value");
+
+ BinaryFormatter fmt = new BinaryFormatter ();
+ var mdict = (Dictionary<string, string>) fmt.Deserialize (new MemoryStream (Convert.FromBase64String (x)));
+
+ Assert.AreEqual (1, dict.Count);
+ Assert.AreEqual (dict.Comparer.GetType (), mdict.Comparer.GetType ());
+ }
+#endif
+
[Test]
public void ZeroCapacity ()
{
[TestFixture]
public class EqualityComparerTest {
+ enum E
+ {
+ A,
+ B
+ }
[Test]
public void Default_GetHashCode_Null ()
IEqualityComparer comparer = EqualityComparer<object>.Default;
Assert.IsTrue (comparer.Equals (null, null));
}
+
+ [Test]
+ public void EnumComparison ()
+ {
+ Assert.IsFalse (EqualityComparer<E>.Default.Equals (E.A, E.B));
+ Assert.IsFalse (EqualityComparer<object>.Default.Equals (E.A, E.B));
+ }
}
}
Assert.Fail ("InvariantCulture not found in the array from GetCultures()");
}
+ [Test]
+ public void GetAllCultures_Specific ()
+ {
+ CultureInfo [] infos = CultureInfo.GetCultures (CultureTypes.SpecificCultures);
+ foreach (CultureInfo ci in infos) {
+ Assert.IsNotNull (ci.DateTimeFormat);
+ }
+ }
+
[Test]
#if !NET_4_0
[ExpectedException (typeof (NotSupportedException))]
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
-
using System;
using NUnit.Framework;
using System.Runtime.ExceptionServices;
Assert.Fail ("#0");
} catch (OperationCanceledException e) {
Assert.IsFalse (e.StackTrace.Contains ("---"));
+ Assert.AreEqual (2, e.StackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Length);
}
}
+ [Test]
+ public void LastThrowWins ()
+ {
+ Exception e;
+ try {
+ throw new Exception ("test");
+ } catch (Exception e2) {
+ e = e2;
+ }
+
+ var edi = ExceptionDispatchInfo.Capture (e);
+
+ try {
+ edi.Throw ();
+ } catch {
+ }
+
+ try {
+ edi.Throw ();
+ } catch (Exception ex) {
+ }
+
+ try {
+ edi.Throw ();
+ } catch (Exception ex) {
+ var split = ex.StackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
+ Assert.AreEqual (4, split.Length, "#1");
+ Assert.IsTrue (split [1].Contains ("---"), "#2");
+ }
+ }
}
}
-#endif
\ No newline at end of file
MemoryStream ms;
string uri;
+#if FEATURE_REMOTING
[Test]
- [Category ("MobileNotWorking")]
public void TestSerialization ()
{
MethodTester mt = new MethodTester();
RemotingServices.Disconnect (mt);
}
+#endif
#if !MONOTOUCH
[Test]
return 2;
}
+#if FEATURE_REMOTING
void WriteData ()
{
StreamingContext context = new StreamingContext (StreamingContextStates.Other);
CheckMessages ("MethodCall", originalMsgData, ProcessMessages (null, calls));
CheckMessages ("MethodResponse", originalMsgData, ProcessMessages (null, resps));
}
-
+#endif
BinderTester_A CreateBinderTestData ()
{
BinderTester_A bta = new BinderTester_A();
Convert.ToUInt64 ("-", 16);
}
+ [Test]
+ public void ToInt64_Base10_MaxValue ()
+ {
+ Assert.AreEqual (Int64.MaxValue, Convert.ToInt64 (Int64.MaxValue.ToString(), 10));
+ }
+
+ [Test]
+ [ExpectedException (typeof (OverflowException))]
+ public void ToInt64_Base10_MaxValueOverflow ()
+ {
+ var overflowValue = ((UInt64) Int64.MaxValue) + 1;
+ Convert.ToInt64 (overflowValue.ToString (), 10);
+ }
+
+ [Test]
+ public void ToInt64_Base10_MinValue ()
+ {
+ Assert.AreEqual (Int64.MinValue, Convert.ToInt64 (Int64.MinValue.ToString(), 10));
+ }
+
+ [Test]
+ [ExpectedException (typeof (OverflowException))]
+ public void ToInt64_Base10_MinValueOverflow ()
+ {
+ var overflowValue = ((UInt64) Int64.MaxValue) + 2;
+ Convert.ToInt64 ("-" + overflowValue.ToString (), 10);
+ }
+
+ [Test]
+ public void ToInt64_Base16_MaxValue ()
+ {
+ Assert.AreEqual (Int64.MaxValue, Convert.ToInt64 (Int64.MaxValue.ToString("x"), 16));
+ }
+
+ [Test]
+ public void ToInt64_Base16_MaxValueOverflow ()
+ {
+ var overflowValue = ((UInt64) Int64.MaxValue) + 1;
+ Assert.AreEqual (-9223372036854775808, Convert.ToInt64 (overflowValue.ToString("x"), 16));
+ }
+
+ [Test]
+ [ExpectedException (typeof (OverflowException))]
+ public void ToInt64_Base16_MaxValueOverflow2 ()
+ {
+ Convert.ToInt64 (UInt64.MaxValue.ToString ("x") + "0", 16);
+ }
+
+ [Test]
+ public void ToInt64_Base16_MinValue ()
+ {
+ Assert.AreEqual (Int64.MinValue, Convert.ToInt64 (Int64.MinValue.ToString ("x"), 16));
+ }
+
+ [Test]
+ public void ToUInt64_Base10_MaxValue ()
+ {
+ Assert.AreEqual (UInt64.MaxValue, Convert.ToUInt64 (UInt64.MaxValue.ToString (), 10));
+ }
+
+ [Test]
+ [ExpectedException (typeof (OverflowException))]
+ public void ToUInt64_Base10_MaxValueOverflow ()
+ {
+ Convert.ToUInt64 (UInt64.MaxValue.ToString () + "0", 10);
+ }
+
+ [Test]
+ public void ToUInt64_Base16_MaxValue ()
+ {
+ Assert.AreEqual (UInt64.MaxValue, Convert.ToUInt64 (UInt64.MaxValue.ToString ("x"), 16));
+ }
+
+ [Test]
+ [ExpectedException (typeof (OverflowException))]
+ public void ToUInt64_Base16_MaxValueOverflow ()
+ {
+ Convert.ToInt64 (UInt64.MaxValue.ToString ("x") + "0", 16);
+ }
+
[Test] // bug #481687
public void ChangeType_Value_IConvertible ()
{
}
[Test]
- [ExpectedException (typeof (ArgumentOutOfRangeException))]
public void EndBeforeStart ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- throw new ArgumentOutOfRangeException ();;
DateTime dateStart = new DateTime (2007,01,01);
DateTime dateEnd = new DateTime (2006,01,01);
TimeZoneInfo.TransitionTime daylightTransitionStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule (new DateTime (1,1,1,2,0,0), 03, 11);
TimeZoneInfo.TransitionTime daylightTransitionEnd = TimeZoneInfo.TransitionTime.CreateFixedDateRule (new DateTime (1,1,1,2,0,0), 10, 11);
- TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (dateStart, dateEnd, new TimeSpan (1,0,0), daylightTransitionStart, daylightTransitionEnd);
+ try {
+ TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (dateStart, dateEnd, new TimeSpan (1,0,0), daylightTransitionStart, daylightTransitionEnd);
+ Assert.Fail ();
+ } catch (ArgumentException) {
+ }
}
[Test]
}
[Test]
- [ExpectedException (typeof (ArgumentOutOfRangeException))]
public void DeltaNotInSeconds ()
{
if (Environment.OSVersion.Platform != PlatformID.Unix)
DateTime dateEnd = new DateTime (2008,01,01);
TimeZoneInfo.TransitionTime daylightTransitionStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule (new DateTime (1,1,1,2,0,0), 03, 11);
TimeZoneInfo.TransitionTime daylightTransitionEnd = TimeZoneInfo.TransitionTime.CreateFixedDateRule (new DateTime (1,1,1,2,0,0), 10, 11);
- TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (dateStart, dateEnd, new TimeSpan (55), daylightTransitionStart, daylightTransitionEnd);
+ try {
+ TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (dateStart, dateEnd, new TimeSpan (55), daylightTransitionStart, daylightTransitionEnd);
+ Assert.Fail ();
+ } catch (ArgumentException) {
+ }
}
}
System/AppDomainInitializer.cs
System/AppDomainManager.cs
System/AppDomainSetup.cs
-System/ApplicationId.cs
System/ApplicationIdentity.cs
System/ArgIterator.cs
System/Array.cs
System/AssemblyLoadEventArgs.cs
System/AssemblyLoadEventHandler.cs
-System/AsyncCallback.cs
-System/AttributeTargets.cs
-System/BadImageFormatException.cs
-System/Buffer.cs
-System/CLSCompliantAttribute.cs
System/CStreamReader.cs
System/CStreamWriter.cs
System/Console.cs
System/Console.iOS.cs
-System/ConsoleCancelEventArgs.cs
-System/ConsoleCancelEventHandler.cs
-System/ConsoleColor.cs
System/ConsoleDriver.cs
-System/ConsoleKey.cs
-System/ConsoleKeyInfo.cs
-System/ConsoleModifiers.cs
-System/ConsoleSpecialKey.cs
-System/ContextBoundObject.cs
-System/ContextStaticAttribute.cs
System/ControlCharacters.cs
System/CrossAppDomainDelegate.cs
System/Delegate.cs
System/EmptyArray.cs
System/Environment.cs
System/EnvironmentVariableTarget.cs
-System/EventArgs.cs
-System/EventHandler.cs
System/Exception.cs
-System/FlagsAttribute.cs
-System/Funcs.cs
System/GC.cs
System/GCCollectionMode.cs
System/GCNotificationStatus.cs
System/Guid.cs
System/Guid.MonoTouch.cs
-System/IAppDomainSetup.cs
-System/IAsyncResult.cs
-System/IObservable.cs
-System/IObserver.cs
-System/ICloneable.cs
-System/IComparable.cs
-System/IEquatable.cs
System/IConsoleDriver.cs
-System/IConvertible.cs
-System/ICustomFormatter.cs
-System/IDisposable.cs
-System/IFormatProvider.cs
-System/IFormattable.cs
System/IntPtr.cs
-System/InvalidTimeZoneException.cs
-System/IProgress.cs
-System/IServiceProvider.cs
System/KnownTerminals.cs
-System/LoaderOptimization.cs
-System/LoaderOptimizationAttribute.cs
System/LocalDataStoreSlot.cs
System/MarshalByRefObject.cs
System/Math.cs
System/MonoListItem.cs
System/MonoType.cs
System/MonoTouchAOTHelper.cs
-System/MTAThreadAttribute.cs
System/MulticastDelegate.cs
-System/NonSerializedAttribute.cs
System/NullConsoleDriver.cs
System/Nullable.cs
System/NumberFormatter.cs
System/Object.cs
-System/ObsoleteAttribute.cs
System/OperatingSystem.cs
-System/ParamArrayAttribute.cs
System/PlatformID.cs
System/ResolveEventArgs.cs
System/ResolveEventHandler.cs
System/RuntimeMethodHandle.cs
System/RuntimeTypeHandle.cs
System/ModuleHandle.cs
-System/SerializableAttribute.cs
System/Single.cs
-System/STAThreadAttribute.cs
System/StringComparison.cs
System/TermInfoBooleans.cs
System/TermInfoDriver.cs
System/TermInfoNumbers.cs
System/TermInfoReader.cs
System/TermInfoStrings.cs
-System/ThreadStaticAttribute.cs
System/TimeZone.cs
System/TimeZoneInfo.cs
-System/TimeZoneInfo.AdjustmentRule.cs
System/TimeZoneInfo.Android.cs
System/TimeZoneInfo.MonoTouch.cs
System/TimeZoneInfo.Serialization.cs
-System/TimeZoneInfo.TransitionTime.cs
-System/TimeZoneNotFoundException.cs
../../build/common/MonoTODOAttribute.cs
System/TypeSpec.cs
System/TypeCode.cs
-System/TypeLoadException.cs
System/UIntPtr.cs
System/ValueType.cs
System/Variant.cs
System/WeakReference.cs
System/WeakReference_T.cs
System/WindowsConsoleDriver.cs
-System/_AppDomain.cs
System/__ComObject.cs
System.Configuration.Assemblies/AssemblyHash.cs
System.Configuration.Assemblies/AssemblyHashAlgorithm.cs
System.Diagnostics.SymbolStore/SymDocumentType.cs
System.Diagnostics.SymbolStore/SymLanguageType.cs
System.Diagnostics.SymbolStore/SymLanguageVendor.cs
-System.Globalization/CalendarAlgorithmType.cs
-System.Globalization/CalendarWeekRule.cs
System.Globalization/CultureInfo.cs
-System.Globalization/DateTimeStyles.cs
-System.Globalization/DigitShapes.cs
-System.Globalization/GregorianCalendarTypes.cs
System.Globalization/IdnMapping.cs
System.Globalization/RegionInfo.cs
System.Globalization/RegionInfo.MonoTouch.cs
-System.Globalization/TextInfo.cs
System.IO/Directory.cs
System.IO/DirectoryInfo.cs
-System.IO/DirectoryNotFoundException.cs
System.IO/DriveInfo.cs
-System.IO/DriveNotFoundException.cs
System.IO/DriveType.cs
-System.IO/EndOfStreamException.cs
System.IO/File.cs
System.IO/FileAccess.cs
System.IO/FileAttributes.cs
System.IO/FileInfo.cs
-System.IO/FileLoadException.cs
System.IO/FileMode.cs
-System.IO/FileNotFoundException.cs
System.IO/FileOptions.cs
System.IO/FileShare.cs
System.IO/FileStream.cs
System.IO/FileStreamAsyncResult.cs
System.IO/FileSystemInfo.cs
System.IO/HGlobalUnmanagedMemoryStream.cs
-System.IO/IOException.cs
System.IO/LogcatTextWriter.cs
System.IO/MonoIO.cs
System.IO/MonoIOError.cs
System.IO/MonoFileType.cs
System.IO/MonoIOStat.cs
System.IO/Path.cs
-System.IO/PathTooLongException.cs
System.IO/SearchOption.cs
System.IO/SearchPattern.cs
System.IO/SeekOrigin.cs
System.Runtime/MemoryFailPoint.cs
System.Runtime.CompilerServices/ConditionalWeakTable.cs
System.Runtime.CompilerServices/RuntimeHelpers.cs
-System.Runtime.ConstrainedExecution/CriticialFinalizerObject.cs
-System.Runtime.ConstrainedExecution/CER.cs
-System.Runtime.ConstrainedExecution/Consistency.cs
-System.Runtime.ConstrainedExecution/PrePrepareMethodAttribute.cs
-System.Runtime.ConstrainedExecution/ReliabilityContractAttribute.cs
System.Runtime.Hosting/ActivationArguments.cs
System.Runtime.Hosting/ApplicationActivator.cs
System.Runtime.InteropServices/_Activator.cs
System.Runtime.InteropServices/VarEnum.cs
System.Runtime.InteropServices/VARFLAGS.cs
System.Runtime.InteropServices/VariantWrapper.cs
-System.Runtime.InteropServices.ComTypes/BINDPTR.cs
-System.Runtime.InteropServices.ComTypes/BIND_OPTS.cs
-System.Runtime.InteropServices.ComTypes/CALLCONV.cs
-System.Runtime.InteropServices.ComTypes/CONNECTDATA.cs
-System.Runtime.InteropServices.ComTypes/DESCKIND.cs
-System.Runtime.InteropServices.ComTypes/DISPPARAMS.cs
-System.Runtime.InteropServices.ComTypes/ELEMDESC.cs
-System.Runtime.InteropServices.ComTypes/EXCEPINFO.cs
-System.Runtime.InteropServices.ComTypes/FILETIME.cs
-System.Runtime.InteropServices.ComTypes/FUNCDESC.cs
-System.Runtime.InteropServices.ComTypes/FUNCFLAGS.cs
-System.Runtime.InteropServices.ComTypes/FUNCKIND.cs
-System.Runtime.InteropServices.ComTypes/IBindCtx.cs
-System.Runtime.InteropServices.ComTypes/IConnectionPoint.cs
-System.Runtime.InteropServices.ComTypes/IConnectionPointContainer.cs
-System.Runtime.InteropServices.ComTypes/IDLDESC.cs
-System.Runtime.InteropServices.ComTypes/IDLFLAG.cs
-System.Runtime.InteropServices.ComTypes/IEnumConnectionPoints.cs
-System.Runtime.InteropServices.ComTypes/IEnumConnections.cs
-System.Runtime.InteropServices.ComTypes/IEnumMoniker.cs
-System.Runtime.InteropServices.ComTypes/IEnumString.cs
-System.Runtime.InteropServices.ComTypes/IEnumVARIANT.cs
-System.Runtime.InteropServices.ComTypes/IMoniker.cs
-System.Runtime.InteropServices.ComTypes/IMPLTYPEFLAGS.cs
-System.Runtime.InteropServices.ComTypes/INVOKEKIND.cs
-System.Runtime.InteropServices.ComTypes/IPersistFile.cs
-System.Runtime.InteropServices.ComTypes/IRunningObjectTable.cs
-System.Runtime.InteropServices.ComTypes/IStream.cs
-System.Runtime.InteropServices.ComTypes/ITypeComp.cs
-System.Runtime.InteropServices.ComTypes/ITypeInfo.cs
-System.Runtime.InteropServices.ComTypes/ITypeInfo2.cs
-System.Runtime.InteropServices.ComTypes/ITypeLib.cs
-System.Runtime.InteropServices.ComTypes/ITypeLib2.cs
-System.Runtime.InteropServices.ComTypes/LIBFLAGS.cs
-System.Runtime.InteropServices.ComTypes/PARAMDESC.cs
-System.Runtime.InteropServices.ComTypes/PARAMFLAG.cs
-System.Runtime.InteropServices.ComTypes/STATSTG.cs
-System.Runtime.InteropServices.ComTypes/SYSKIND.cs
-System.Runtime.InteropServices.ComTypes/TYPEATTR.cs
-System.Runtime.InteropServices.ComTypes/TYPEDESC.cs
-System.Runtime.InteropServices.ComTypes/TYPEFLAGS.cs
-System.Runtime.InteropServices.ComTypes/TYPEKIND.cs
-System.Runtime.InteropServices.ComTypes/TYPELIBATTR.cs
-System.Runtime.InteropServices.ComTypes/VARDESC.cs
-System.Runtime.InteropServices.ComTypes/VARFLAGS.cs
-System.Runtime.InteropServices.ComTypes/VARKIND.cs
-System.Runtime.InteropServices.Expando/IExpando.cs
+
System.Runtime.InteropServices.WindowsRuntime/DefaultInterfaceAttribute.cs
System.Runtime.InteropServices.WindowsRuntime/DesignerNamespaceResolveEventArgs.cs
System.Runtime.InteropServices.WindowsRuntime/EventRegistrationToken.cs
System.Threading/TimerCallback.cs
System.Threading/Volatile.cs
System.Threading/WaitHandle.cs
-System/Action.cs
-System/Comparison.cs
-System/Converter.cs
-System/Predicate.cs
-System.Collections.Generic/Comparer.cs
-System.Collections.Generic/EqualityComparer.cs
System.Threading.Tasks/DecoupledTask.cs
../Mono.Parallel/Mono.Threading/AtomicBoolean.cs
ReferenceSources/ExecutionContext.cs
ReferenceSources/HashHelpers.cs
ReferenceSources/ParseNumbers.cs
-ReferenceSources/TimeZoneInfoOptions.cs
ReferenceSources/AppDomain.cs
ReferenceSources/CLRConfig.cs
ReferenceSources/JitHelpers.cs
ReferenceSources/MethodBase.cs
ReferenceSources/RuntimeHandles.cs
ReferenceSources/CompareInfo.cs
+ReferenceSources/TypeBuilderInstantiation.cs
+ReferenceSources/Buffer.cs
+ReferenceSources/TextInfo.cs
../../../external/referencesource/mscorlib/system/__filters.cs
../../../external/referencesource/mscorlib/system/__hresults.cs
../../../external/referencesource/mscorlib/system/accessviolationexception.cs
+../../../external/referencesource/mscorlib/system/action.cs
../../../external/referencesource/mscorlib/system/activator.cs
../../../external/referencesource/mscorlib/system/AggregateException.cs
+../../../external/referencesource/mscorlib/system/appdomainattributes.cs
../../../external/referencesource/mscorlib/system/appdomainunloadedexception.cs
../../../external/referencesource/mscorlib/system/applicationexception.cs
+../../../external/referencesource/mscorlib/system/applicationid.cs
../../../external/referencesource/mscorlib/system/argumentexception.cs
../../../external/referencesource/mscorlib/system/argumentnullexception.cs
../../../external/referencesource/mscorlib/system/argumentoutofrangeexception.cs
../../../external/referencesource/mscorlib/system/arithmeticexception.cs
../../../external/referencesource/mscorlib/system/arraysegment.cs
../../../external/referencesource/mscorlib/system/arraytypemismatchexception.cs
+../../../external/referencesource/mscorlib/system/asynccallback.cs
../../../external/referencesource/mscorlib/system/attribute.cs
+../../../external/referencesource/mscorlib/system/attributetargets.cs
../../../external/referencesource/mscorlib/system/attributeusageattribute.cs
+../../../external/referencesource/mscorlib/system/badimageformatexception.cs
../../../external/referencesource/mscorlib/system/bitconverter.cs
../../../external/referencesource/mscorlib/system/boolean.cs
+../../../external/referencesource/mscorlib/system/buffer.cs
../../../external/referencesource/mscorlib/system/byte.cs
../../../external/referencesource/mscorlib/system/cannotunloadappdomainexception.cs
../../../external/referencesource/mscorlib/system/char.cs
../../../external/referencesource/mscorlib/system/charenumerator.cs
+../../../external/referencesource/mscorlib/system/consolecanceleventargs.cs
+../../../external/referencesource/mscorlib/system/consolecolor.cs
+../../../external/referencesource/mscorlib/system/consolekey.cs
+../../../external/referencesource/mscorlib/system/consolekeyinfo.cs
+../../../external/referencesource/mscorlib/system/consolemodifiers.cs
+../../../external/referencesource/mscorlib/system/consolespecialkey.cs
+../../../external/referencesource/mscorlib/system/contextboundobject.cs
+../../../external/referencesource/mscorlib/system/contextstaticattribute.cs
+../../../external/referencesource/mscorlib/system/clscompliantattribute.cs
../../../external/referencesource/mscorlib/system/contextmarshalexception.cs
../../../external/referencesource/mscorlib/system/convert.cs
../../../external/referencesource/mscorlib/system/datamisalignedexception.cs
../../../external/referencesource/mscorlib/system/empty.cs
../../../external/referencesource/mscorlib/system/enum.cs
../../../external/referencesource/mscorlib/system/entrypointnotfoundexception.cs
+../../../external/referencesource/mscorlib/system/eventargs.cs
+../../../external/referencesource/mscorlib/system/eventhandler.cs
../../../external/referencesource/mscorlib/system/executionengineexception.cs
../../../external/referencesource/mscorlib/system/fieldaccessexception.cs
+../../../external/referencesource/mscorlib/system/flagsattribute.cs
../../../external/referencesource/mscorlib/system/formatexception.cs
../../../external/referencesource/mscorlib/system/guid.cs
+../../../external/referencesource/mscorlib/system/iappdomain.cs
+../../../external/referencesource/mscorlib/system/iappdomainsetup.cs
+../../../external/referencesource/mscorlib/system/iasyncresult.cs
+../../../external/referencesource/mscorlib/system/icloneable.cs
+../../../external/referencesource/mscorlib/system/icomparable.cs
+../../../external/referencesource/mscorlib/system/iconvertible.cs
+../../../external/referencesource/mscorlib/system/icustomformatter.cs
+../../../external/referencesource/mscorlib/system/idisposable.cs
+../../../external/referencesource/mscorlib/system/iequatable.cs
+../../../external/referencesource/mscorlib/system/iformatprovider.cs
+../../../external/referencesource/mscorlib/system/iformattable.cs
../../../external/referencesource/mscorlib/system/invalidcastexception.cs
../../../external/referencesource/mscorlib/system/indexoutofrangeexception.cs
../../../external/referencesource/mscorlib/system/invalidoperationexception.cs
../../../external/referencesource/mscorlib/system/int16.cs
../../../external/referencesource/mscorlib/system/int32.cs
../../../external/referencesource/mscorlib/system/int64.cs
+../../../external/referencesource/mscorlib/system/iobservable.cs
+../../../external/referencesource/mscorlib/system/iobserver.cs
+../../../external/referencesource/mscorlib/system/iprogress.cs
+../../../external/referencesource/mscorlib/system/iserviceobjectprovider.cs
+../../../external/referencesource/mscorlib/system/invalidtimezoneexception.cs
../../../external/referencesource/mscorlib/system/Lazy.cs
../../../external/referencesource/mscorlib/system/memberaccessexception.cs
../../../external/referencesource/mscorlib/system/methodaccessexception.cs
+../../../external/referencesource/mscorlib/system/midpointrounding.cs
../../../external/referencesource/mscorlib/system/missingfieldexception.cs
../../../external/referencesource/mscorlib/system/missingmemberexception.cs
../../../external/referencesource/mscorlib/system/missingmethodexception.cs
../../../external/referencesource/mscorlib/system/multicastnotsupportedexception.cs
+../../../external/referencesource/mscorlib/system/nonserializedattribute.cs
../../../external/referencesource/mscorlib/system/notfinitenumberexception.cs
../../../external/referencesource/mscorlib/system/notimplementedexception.cs
../../../external/referencesource/mscorlib/system/notsupportedexception.cs
-../../../external/referencesource/mscorlib/system/midpointrounding.cs
../../../external/referencesource/mscorlib/system/nullreferenceexception.cs
../../../external/referencesource/mscorlib/system/number.cs
../../../external/referencesource/mscorlib/system/objectdisposedexception.cs
+../../../external/referencesource/mscorlib/system/obsoleteattribute.cs
../../../external/referencesource/mscorlib/system/operationcanceledexception.cs
../../../external/referencesource/mscorlib/system/outofmemoryexception.cs
../../../external/referencesource/mscorlib/system/overflowexception.cs
+../../../external/referencesource/mscorlib/system/paramarrayattribute.cs
../../../external/referencesource/mscorlib/system/platformnotsupportedexception.cs
../../../external/referencesource/mscorlib/system/progress.cs
../../../external/referencesource/mscorlib/system/random.cs
../../../external/referencesource/mscorlib/system/resid.cs
../../../external/referencesource/mscorlib/system/rttype.cs
../../../external/referencesource/mscorlib/system/sbyte.cs
+../../../external/referencesource/mscorlib/system/serializableattribute.cs
../../../external/referencesource/mscorlib/system/stackoverflowexception.cs
../../../external/referencesource/mscorlib/system/string.cs
../../../external/referencesource/mscorlib/system/stringcomparer.cs
../../../external/referencesource/mscorlib/system/systemexception.cs
../../../external/referencesource/mscorlib/system/timeoutexception.cs
../../../external/referencesource/mscorlib/system/timespan.cs
+../../../external/referencesource/mscorlib/system/threadattributes.cs
+../../../external/referencesource/mscorlib/system/threadstaticattribute.cs
../../../external/referencesource/mscorlib/system/throwhelper.cs
+../../../external/referencesource/mscorlib/system/timezoneinfo.cs
+../../../external/referencesource/mscorlib/system/timezonenotfoundexception.cs
../../../external/referencesource/mscorlib/system/tuple.cs
../../../external/referencesource/mscorlib/system/type.cs
../../../external/referencesource/mscorlib/system/typeaccessexception.cs
../../../external/referencesource/mscorlib/system/typeinitializationexception.cs
+../../../external/referencesource/mscorlib/system/typeloadexception.cs
../../../external/referencesource/mscorlib/system/typedreference.cs
../../../external/referencesource/mscorlib/system/typeunloadedexception.cs
../../../external/referencesource/mscorlib/system/uint16.cs
../../../external/referencesource/mscorlib/system/collections/stack.cs
../../../external/referencesource/mscorlib/system/collections/structuralcomparisons.cs
+../../../external/referencesource/mscorlib/system/collections/generic/comparer.cs
../../../external/referencesource/mscorlib/system/collections/generic/debugview.cs
../../../external/referencesource/mscorlib/system/collections/generic/dictionary.cs
+../../../external/referencesource/mscorlib/system/collections/generic/equalitycomparer.cs
../../../external/referencesource/mscorlib/system/collections/generic/icollection.cs
../../../external/referencesource/mscorlib/system/collections/generic/icomparer.cs
../../../external/referencesource/mscorlib/system/collections/generic/idictionary.cs
../../../external/referencesource/mscorlib/system/globalization/bidicategory.cs
../../../external/referencesource/mscorlib/system/globalization/calendar.cs
+../../../external/referencesource/mscorlib/system/globalization/calendaralgorithmtype.cs
../../../external/referencesource/mscorlib/system/globalization/calendardata.cs
+../../../external/referencesource/mscorlib/system/globalization/calendarweekrule.cs
../../../external/referencesource/mscorlib/system/globalization/charunicodeinfo.cs
../../../external/referencesource/mscorlib/system/globalization/chineselunisolarcalendar.cs
../../../external/referencesource/mscorlib/system/globalization/compareinfo.cs
../../../external/referencesource/mscorlib/system/globalization/datetimeformatinfo.cs
../../../external/referencesource/mscorlib/system/globalization/datetimeformatinfoscanner.cs
../../../external/referencesource/mscorlib/system/globalization/datetimeparse.cs
+../../../external/referencesource/mscorlib/system/globalization/datetimestyles.cs
+../../../external/referencesource/mscorlib/system/globalization/daylighttime.cs
+../../../external/referencesource/mscorlib/system/globalization/digitshapes.cs
../../../external/referencesource/mscorlib/system/globalization/eastasianlunisolarcalendar.cs
../../../external/referencesource/mscorlib/system/globalization/globalizationassembly.cs
../../../external/referencesource/mscorlib/system/globalization/gregoriancalendar.cs
../../../external/referencesource/mscorlib/system/globalization/gregoriancalendarhelper.cs
+../../../external/referencesource/mscorlib/system/globalization/gregoriancalendartypes.cs
../../../external/referencesource/mscorlib/system/globalization/hebrewcalendar.cs
../../../external/referencesource/mscorlib/system/globalization/hebrewnumber.cs
../../../external/referencesource/mscorlib/system/globalization/hijricalendar.cs
../../../external/referencesource/mscorlib/system/globalization/textelementenumerator.cs
../../../external/referencesource/mscorlib/system/globalization/timespanformat.cs
../../../external/referencesource/mscorlib/system/globalization/timespanparse.cs
+../../../external/referencesource/mscorlib/system/globalization/textinfo.cs
../../../external/referencesource/mscorlib/system/globalization/thaibuddhistcalendar.cs
../../../external/referencesource/mscorlib/system/globalization/umalquracalendar.cs
../../../external/referencesource/mscorlib/system/globalization/unicodecategory.cs
../../../external/referencesource/mscorlib/system/io/__error.cs
+../../../external/referencesource/mscorlib/system/io/__hresults.cs
../../../external/referencesource/mscorlib/system/io/binaryreader.cs
../../../external/referencesource/mscorlib/system/io/binarywriter.cs
../../../external/referencesource/mscorlib/system/io/bufferedstream.cs
+../../../external/referencesource/mscorlib/system/io/directorynotfoundexception.cs
+../../../external/referencesource/mscorlib/system/io/drivenotfoundexception.cs
+../../../external/referencesource/mscorlib/system/io/endofstreamexception.cs
+../../../external/referencesource/mscorlib/system/io/ioexception.cs
+../../../external/referencesource/mscorlib/system/io/fileloadexception.cs
+../../../external/referencesource/mscorlib/system/io/filenotfoundexception.cs
../../../external/referencesource/mscorlib/system/io/memorystream.cs
+../../../external/referencesource/mscorlib/system/io/pathtoolongexception.cs
../../../external/referencesource/mscorlib/system/io/pinnedbuffermemorystream.cs
../../../external/referencesource/mscorlib/system/io/stream.cs
../../../external/referencesource/mscorlib/system/io/streamreader.cs
../../../external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionnotification.cs
../../../external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ibindctx.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/iconnectionpoint.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/iconnectionpointcontainer.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienumconnectionpoints.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienumconnections.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienumerable.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienumerator.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienummoniker.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienumstring.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ienumvariant.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/iexpando.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/imoniker.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ipersistfile.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/ireflect.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/irunningobjecttable.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/istream.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/itypecomp.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/itypeinfo.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/itypeinfo2.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/itypelib.cs
+../../../external/referencesource/mscorlib/system/runtime/interopservices/ComTypes/itypelib2.cs
+
+../../../external/referencesource/mscorlib/system/runtime/interopservices/expando/iexpando.cs
+
+../../../external/referencesource/mscorlib//system/runtime/reliability/criticalfinalizerobject.cs
+../../../external/referencesource/mscorlib//system/runtime/reliability/prepreparemethodattribute.cs
+../../../external/referencesource/mscorlib//system/runtime/reliability/reliabilitycontractattribute.cs
+
../../../external/referencesource/mscorlib/system/runtime/versioning/binarycompatibility.cs
../../../external/referencesource/mscorlib/system/runtime/versioning/multitargetinghelpers.cs
../../../external/referencesource/mscorlib/system/runtime/versioning/targetframeworkid.cs
../../../external/referencesource/mscorlib/system/runtime/compilerservices/unsafevaluetypeattribute.cs
../../../external/referencesource/mscorlib/system/runtime/compilerservices/YieldAwaitable.cs
+../../../external/referencesource/mscorlib/system/security/util/hex.cs
+
../../../external/referencesource/mscorlib/system/text/asciiencoding.cs
../../../external/referencesource/mscorlib/system/text/codepageencoding.cs
../../../external/referencesource/mscorlib/system/text/decoderbestfitfallback.cs
all-local:
+PROFILE_DIR=$(DESTDIR)$(mono_libdir)/mono/
+
install-local:
- $(MKINSTALLDIRS) $(DESTDIR)$(LIBRARY_INSTALL_DIR)
- $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.0/* $(DESTDIR)$(LIBRARY_INSTALL_DIR)
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/2.0
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/3.5
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.0
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v2.0/* $(PROFILE_DIR)/2.0
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v3.5/* $(PROFILE_DIR)/3.5
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.0/* $(PROFILE_DIR)/4.0
-DISTFILES = $(wildcard ../../../external/binary-reference-assemblies/v4.0/*) Makefile
+DISTFILES = $(wildcard ../../../external/binary-reference-assemblies/v4.0/*) $(wildcard ../../../external/binary-reference-assemblies/v3.5/*) $(wildcard ../../../external/binary-reference-assemblies/v2.0/*) Makefile
dist-local: dist-default
var cand_param = candidate_pd.FixedParameters [j];
var best_param = best_pd.FixedParameters [j];
+ if (cand_param.HasDefaultValue != best_param.HasDefaultValue)
+ return cand_param.HasDefaultValue;
+
if (candidate_pd.Count == best_pd.Count) {
//
// LAMESPEC:
// void Foo (int i = 0) is better than void Foo (params int[]) for Foo ()
// void Foo (string[] s, string value = null) is better than Foo (string s, params string[]) for Foo (null) or Foo ()
//
- if (cand_param.HasDefaultValue != best_param.HasDefaultValue)
- return cand_param.HasDefaultValue;
if (cand_param.HasDefaultValue) {
++j;
// void Foo (string s, int i = 0) <-> Foo (string s, byte i = 0)
// void Foo (string s, params int[]) <-> Foo (string s, params byte[])
//
- if (cand_param.HasDefaultValue && best_param.HasDefaultValue)
- return false;
+ return false;
}
break;
//
public class StackAlloc : Expression {
TypeSpec otype;
- Expression t;
+ Expression texpr;
Expression count;
public StackAlloc (Expression type, Expression count, Location l)
{
- t = type;
+ texpr = type;
this.count = count;
loc = l;
}
public Expression TypeExpression {
get {
- return this.t;
+ return texpr;
}
}
ec.Report.Error (255, loc, "Cannot use stackalloc in finally or catch");
}
- otype = t.ResolveAsType (ec);
+ otype = texpr.ResolveAsType (ec);
if (otype == null)
return null;
{
StackAlloc target = (StackAlloc) t;
target.count = count.Clone (clonectx);
- target.t = t.Clone (clonectx);
+ target.texpr = texpr.Clone (clonectx);
}
public override object Accept (StructuralVisitor visitor)
Constant c = field_type.Kind == MemberKind.MissingType ?
new NullConstant (InternalType.ErrorType, Location.Null) :
CreateConstantFromValue (field_type, fi);
- return new ConstSpec (declaringType, definition, field_type, fi, mod, c);
+ return new ConstSpec (declaringType, definition, field_type, fi, mod | Modifiers.STATIC, c);
}
if ((fa & FieldAttributes.InitOnly) != 0) {
if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi));
if (dc != null)
- return new ConstSpec (declaringType, definition, field_type, fi, mod, dc);
+ return new ConstSpec (declaringType, definition, field_type, fi, mod | Modifiers.STATIC, dc);
}
mod |= Modifiers.READONLY;
}
if (Set == null) {
- if ((ModFlags & Modifiers.SEALED) != 0 && base_prop.HasSet && !base_prop.Set.IsAccessible (this)) {
- // TODO: Should be different error code but csc uses for some reason same
- Report.SymbolRelatedToPreviousError (base_prop);
- Report.Error (546, Location,
- "`{0}': cannot override because `{1}' does not have accessible set accessor",
- GetSignatureForError (), base_prop.GetSignatureForError ());
- ok = false;
- }
+ if (base_prop.HasSet) {
+ if ((ModFlags & Modifiers.SEALED) != 0 && !base_prop.Set.IsAccessible (this)) {
+ // TODO: Should be different error code but csc uses for some reason same
+ Report.SymbolRelatedToPreviousError (base_prop);
+ Report.Error (546, Location,
+ "`{0}': cannot override because `{1}' does not have accessible set accessor",
+ GetSignatureForError (), base_prop.GetSignatureForError ());
+ ok = false;
+ }
- if ((ModFlags & Modifiers.AutoProperty) != 0) {
- Report.Error (8080, Location, "`{0}': Auto-implemented properties must override all accessors of the overridden property",
- GetSignatureForError ());
- ok = false;
+ if ((ModFlags & Modifiers.AutoProperty) != 0) {
+ Report.Error (8080, Location, "`{0}': Auto-implemented properties must override all accessors of the overridden property",
+ GetSignatureForError ());
+ ok = false;
+ }
}
} else {
if (!base_prop.HasSet) {
--- /dev/null
+using System;
+
+class MainClass
+{
+ abstract public class Bar
+ {
+ abstract public bool Condition { get; }
+ }
+
+ class Baz: Bar
+ {
+ public override bool Condition { get; } = true;
+ }
+
+ public static void Main (string[] args)
+ {
+ }
+}
static int Test_6 (params object[] o)
{
- return 0;
+ return 1;
}
static int Test_6 (int i = 1, params object[] a)
{
- return 1;
+ return 0;
}
static int Test_7 (bool b, params object[] o)
{
- return 0;
+ return 1;
}
static int Test_7 (bool b, int i = 1, params object[] a)
+ {
+ return 0;
+ }
+
+ static int Test_8 (Type t, bool b = false, int x = 0)
+ {
+ return 0;
+ }
+
+ static int Test_8 (Type t, params int[] x)
{
return 1;
}
if (Test_7 (false) != 0)
return 7;
+ if (Test_8 (typeof (bool)) != 0)
+ return 8;
+
Console.WriteLine ("ok");
return 0;
}
Test (delegate () {
int i = *v.GetUnsafeValue ();
});
+
+ Test (delegate () {
+ byte* buffer = stackalloc byte[8192];
+ });
}
-
public static void Main ()
{
Exception diffException;
--- /dev/null
+// Compiler options: -t:library
+
+public static class Constants
+{
+ public const long One = 1;
+}
\ No newline at end of file
--- /dev/null
+// Compiler options: -r:test-static-using-09-lib.dll
+
+using static Constants;
+
+static class Program
+{
+ static void Main ()
+ {
+ System.Console.WriteLine (One);
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="gtest-autoproperty-17.cs">
+ <type name="MainClass">
+ <method name="Void Main(System.String[])" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="MainClass+Bar">
+ <method name="Boolean get_Condition()" attrs="3526">
+ <size>0</size>
+ </method>
+ <method name="Void .ctor()" attrs="6276">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="MainClass+Baz">
+ <method name="Boolean get_Condition()" attrs="2246">
+ <size>14</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>14</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-collectioninit-01.cs">
<type name="Test">
<method name="Void TestList(System.Collections.Generic.List`1[System.Int32], Int32)" attrs="145">
<size>10</size>
</method>
<method name="Int32 Main()" attrs="150">
- <size>161</size>
+ <size>192</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
+ <method name="Int32 Test_8(System.Type, Boolean, Int32)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Int32 Test_8(System.Type, Int32[])" attrs="145">
+ <size>10</size>
+ </method>
</type>
</test>
<test name="gtest-optional-10.cs">
</type>
<type name="C">
<method name="Void UnsafeTests()" attrs="145">
- <size>36</size>
+ <size>70</size>
</method>
<method name="Void Main()" attrs="150">
<size>99</size>
</method>
</type>
<type name="C">
- <method name="Void <Main>m__0()" attrs="145">
+ <method name="Void <UnsafeTests>m__0()" attrs="145">
+ <size>12</size>
+ </method>
+ <method name="Void <Main>m__1()" attrs="145">
<size>17</size>
</method>
</type>
</method>
</type>
</test>
+ <test name="test-static-using-09.cs">
+ <type name="Program">
+ <method name="Void Main()" attrs="145">
+ <size>9</size>
+ </method>
+ </type>
+ </test>
<test name="test-var-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">
// even if we (just before saving) will resolve all type references (bug #26752)
void MarkWithResolvedScope (TypeReference type)
{
- // we cannot set the Scope of a TypeSpecification so there's no point in resolving it
- if ((type == null) || (type is TypeSpecification))
+ if (type == null)
+ return;
+
+ // a GenericInstanceType can could contains generic arguments with scope that
+ // needs to be updated out of the PCL facade (bug #28823)
+ var git = (type as GenericInstanceType);
+ if ((git != null) && git.HasGenericArguments) {
+ foreach (var ga in git.GenericArguments)
+ MarkWithResolvedScope (ga);
return;
+ }
+ // we cannot set the Scope of a TypeSpecification but it's element type can be set
+ // e.g. System.String[] -> System.String
+ var ts = (type as TypeSpecification);
+ if (ts != null) {
+ MarkWithResolvedScope (ts.GetElementType ());
+ return;
+ }
+
var td = type.Resolve ();
if (td != null)
type.Scope = td.Scope;
install-frameworks:
$(MKINSTALLDIRS) $(DESTDIR)$(NETFRAMEWORK_DIR)/v$(FRAMEWORK_VERSION)/RedistList
$(INSTALL_DATA) frameworks/net_$(FRAMEWORK_VERSION).xml $(DESTDIR)$(NETFRAMEWORK_DIR)/v$(FRAMEWORK_VERSION)/RedistList/FrameworkList.xml
+ $(MKINSTALLDIRS) $(DESTDIR)$(NETFRAMEWORK_DIR)/v2.0/RedistList
+ $(INSTALL_DATA) frameworks/net_2.0.xml $(DESTDIR)$(NETFRAMEWORK_DIR)/v2.0/RedistList/FrameworkList.xml
$(MKINSTALLDIRS) $(DESTDIR)$(NETFRAMEWORK_DIR)/v3.0/RedistList
$(INSTALL_DATA) frameworks/net_3.0.xml $(DESTDIR)$(NETFRAMEWORK_DIR)/v3.0/RedistList/FrameworkList.xml
+ $(MKINSTALLDIRS) $(DESTDIR)$(NETFRAMEWORK_DIR)/v3.5/RedistList
+ $(INSTALL_DATA) frameworks/net_3.5.xml $(DESTDIR)$(NETFRAMEWORK_DIR)/v3.5/RedistList/FrameworkList.xml
$(MKINSTALLDIRS) $(DESTDIR)$(NETFRAMEWORK_DIR)/v4.0/RedistList
$(INSTALL_DATA) frameworks/net_4.0.xml $(DESTDIR)$(NETFRAMEWORK_DIR)/v4.0/RedistList/FrameworkList.xml
$(MKINSTALLDIRS) $(DESTDIR)$(NETFRAMEWORK_DIR)/v4.0/Profile/Client/RedistList
+++ /dev/null
-%{!?ext_man: %define ext_man .gz}
-%define llvm no
-%define sgen yes
-
-%ifnarch %ix86 x86_64
-%define llvm no
-%endif
-
-%ifnarch %ix86 x86_64 s390x
-%define sgen no
-%endif
-
-Name: mono-core
-License: LGPL v2.1 only
-Group: Development/Languages/Mono
-Summary: A .NET Runtime Environment
-Url: http://www.mono-project.com
-Version: @VERSION@
-Release: 0
-Source0: mono-%{version}.tar.bz2
-BuildRequires: bison
-%if 0%{?suse_version}
-BuildRequires: fdupes
-BuildRequires: xorg-x11-libX11-devel
-%else
-BuildRequires: libX11-devel
-%endif
-BuildRequires: gcc-c++
-BuildRequires: pkgconfig
-BuildRequires: zlib-devel
-%ifnarch ia64
-BuildRequires: valgrind-devel
-%endif
-%if %llvm == yes
-BuildRequires: llvm-mono-devel
-%endif
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
-Obsoletes: mono
-Obsoletes: mono-cairo
-Obsoletes: mono-drawing
-Obsoletes: mono-ikvm
-Obsoletes: mono-posix
-Obsoletes: mono-xml-relaxng
-Obsoletes: mono-ziplib
-Provides: mono = %{version}-%{release}
-Provides: mono-cairo
-Provides: mono-drawing
-Provides: mono-ikvm
-Provides: mono-posix
-Provides: mono-xml-relaxng
-Provides: mono-ziplib
-# This version of mono has issues with the following versions of apps:
-# (not because of regressions, but because bugfixes in mono uncover bugs in the apps)
-Conflicts: banshee < 1.0
-Conflicts: f-spot < 0.4
-Conflicts: helix-banshee < 1.0
-Conflicts: mono-addins < 0.3.1
-%if 0%{?suse_version}
-Recommends: libgdiplus0 >= 2.6
-%endif
-%if %llvm == yes
-Recommends: libmono-llvm0 = %{version}-%{release}
-%endif
-Provides: mono(Commons.Xml.Relaxng) = 1.0.5000.0
-Provides: mono(CustomMarshalers) = 1.0.5000.0
-Provides: mono(I18N) = 1.0.5000.0
-Provides: mono(I18N.West) = 1.0.5000.0
-Provides: mono(ICSharpCode.SharpZipLib) = 0.6.0.0
-Provides: mono(ICSharpCode.SharpZipLib) = 0.84.0.0
-Provides: mono(Mono.Cairo) = 1.0.5000.0
-Provides: mono(Mono.CompilerServices.SymbolWriter) = 1.0.5000.0
-Provides: mono(Mono.Posix) = 1.0.5000.0
-Provides: mono(Mono.Security) = 1.0.5000.0
-Provides: mono(System) = 1.0.5000.0
-Provides: mono(System.Security) = 1.0.5000.0
-Provides: mono(System.Xml) = 1.0.5000.0
-Provides: mono(mscorlib) = 1.0.5000.0
-
-%define _use_internal_dependency_generator 0
-%define __find_provides env sh -c 'filelist=($(cat)) && { printf "%s\\n" "${filelist[@]}" | /usr/lib/rpm/find-provides && printf "%s\\n" "${filelist[@]}" | prefix=%{buildroot}%{_prefix} %{buildroot}%{_bindir}/mono-find-provides ; } | sort | uniq'
-%define __find_requires env sh -c 'filelist=($(cat)) && { printf "%s\\n" "${filelist[@]}" | /usr/lib/rpm/find-requires && printf "%s\\n" "${filelist[@]}" | prefix=%{buildroot}%{_prefix} %{buildroot}%{_bindir}/mono-find-requires ; } | sort | uniq'
-
-%description
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-%prep
-%setup -q -n mono-%{version}
-
-%build
-# These are only needed if there are patches to the runtime
-#rm -f libgc/libtool.m4
-#autoreconf --force --install
-#autoreconf --force --install libgc
-export CFLAGS=" $RPM_OPT_FLAGS -fno-strict-aliasing"
-# distro specific configure options
-%if %llvm == yes
-export PATH=/opt/novell/llvm-mono/bin:$PATH
-%endif
-%configure \
- --target=%{_host} \
- --with-sgen=%{sgen} \
-%if %llvm == yes
- --enable-loadedllvm \
- --disable-system-aot \
-%endif
-%ifnarch %ix86 x86_64
- --disable-system-aot \
-%endif
- --with-ikvm=yes \
- --with-moonlight=no
-#make # We are not -jN safe! %{?jobs:-j%jobs}
-# We are now !
-make get-monolite-latest
-make %{?_smp_mflags}
-
-%install
-make install DESTDIR=%buildroot
-# remove .la files (they are generally bad news)
-rm -f %buildroot%_libdir/*.la
-# remove Windows-only stuff
-rm -rf %buildroot%_prefix/lib/mono/*/Mono.Security.Win32*
-rm -f %buildroot%_libdir/libMonoSupportW.*
-# remove .a files for libraries that are really only for us
-rm -f %buildroot%_libdir/libMonoPosixHelper.a
-rm -f %buildroot%_libdir/libikvm-native.a
-rm -f %buildroot%_libdir/libmono-llvm.a
-# remove libgc cruft
-rm -rf %buildroot%_datadir/libgc-mono
-# remove stuff that we don't package
-rm -f %buildroot%_bindir/cilc
-rm -f %buildroot%_mandir/man1/cilc.1*
-rm -f %buildroot%_prefix/lib/mono/*/browsercaps-updater.exe*
-rm -f %buildroot%_prefix/lib/mono/*/culevel.exe*
-rm -f %buildroot%_prefix/lib/mono/2.0/cilc.exe*
-# brp-compress doesn't search _mandir
-# so we cheat it
-ln -s . %buildroot%_prefix%_prefix
-RPM_BUILD_ROOT=%buildroot%_prefix /usr/lib/rpm/brp-compress
-rm %buildroot%_prefix%_prefix
-%if 0%{?suse_version}
-%fdupes %buildroot%_prefix
-%endif
-%find_lang mcs
-
-%clean
-rm -rf %buildroot
-
-%files -f mcs.lang
-%defattr(-, root, root)
-%doc AUTHORS COPYING.LIB ChangeLog NEWS README.md
-%config %_sysconfdir/mono/2.0/machine.config
-%config %_sysconfdir/mono/2.0/settings.map
-%config %_sysconfdir/mono/4.0/machine.config
-%config %_sysconfdir/mono/4.0/settings.map
-%config %_sysconfdir/mono/4.5/machine.config
-%config %_sysconfdir/mono/4.5/settings.map
-%config %_sysconfdir/mono/config
-%dir %_prefix/lib/mono
-%dir %_prefix/lib/mono/2.0
-%dir %_prefix/lib/mono/3.5
-%dir %_prefix/lib/mono/4.0
-%dir %_prefix/lib/mono/4.5
-%dir %_prefix/lib/mono/compat-2.0
-%dir %_prefix/lib/mono/gac
-%dir %_sysconfdir/mono
-%dir %_sysconfdir/mono/2.0
-%dir %_sysconfdir/mono/4.0
-%dir %_sysconfdir/mono/4.5
-%_bindir/al
-%_bindir/al2
-%_bindir/certmgr
-%_bindir/chktrust
-%_bindir/crlupdate
-%_bindir/csharp
-%_bindir/dmcs
-%_bindir/gacutil
-%_bindir/gacutil2
-%_bindir/ikdasm
-%_bindir/mcs
-%_bindir/mono
-%_bindir/mono-configuration-crypto
-%if %sgen == yes
-%_bindir/mono-sgen
-%endif
-%_bindir/mono-boehm
-%_bindir/mono-test-install
-%_bindir/mozroots
-%_bindir/peverify
-%_bindir/setreg
-%_bindir/sn
-%_libdir/libMonoPosixHelper.so*
-%_libdir/libikvm-native.so
-%_mandir/man1/certmgr.1%ext_man
-%_mandir/man1/chktrust.1%ext_man
-%_mandir/man1/crlupdate.1%ext_man
-%_mandir/man1/csharp.1%ext_man
-%_mandir/man1/gacutil.1%ext_man
-%_mandir/man1/mcs.1%ext_man
-%_mandir/man1/mono-configuration-crypto.1%ext_man
-%_mandir/man1/mono.1%ext_man
-%_mandir/man1/mozroots.1%ext_man
-%_mandir/man1/setreg.1%ext_man
-%_mandir/man1/sn.1%ext_man
-%_mandir/man5/mono-config.5%ext_man
-%_prefix/lib/mono/2.0/Commons.Xml.Relaxng.dll
-%_prefix/lib/mono/2.0/CustomMarshalers.dll
-%_prefix/lib/mono/2.0/I18N.West.dll
-%_prefix/lib/mono/2.0/I18N.dll
-%_prefix/lib/mono/2.0/ICSharpCode.SharpZipLib.dll
-%_prefix/lib/mono/2.0/Microsoft.VisualC.dll
-%_prefix/lib/mono/2.0/Mono.C5.dll
-%_prefix/lib/mono/2.0/Mono.CSharp.dll
-%_prefix/lib/mono/2.0/Mono.Cairo.dll
-%_prefix/lib/mono/2.0/Mono.CompilerServices.SymbolWriter.dll
-%_prefix/lib/mono/2.0/Mono.Management.dll
-%_prefix/lib/mono/2.0/Mono.Posix.dll
-%_prefix/lib/mono/2.0/Mono.Security.dll
-%_prefix/lib/mono/2.0/Mono.Simd.dll
-%_prefix/lib/mono/2.0/Mono.Tasklets.dll
-%_prefix/lib/mono/2.0/System.Configuration.dll
-%_prefix/lib/mono/2.0/System.Core.dll
-%_prefix/lib/mono/2.0/System.Drawing.dll
-%_prefix/lib/mono/2.0/System.Net.dll
-%_prefix/lib/mono/2.0/System.Security.dll
-%_prefix/lib/mono/2.0/System.Xml.Linq.dll
-%_prefix/lib/mono/2.0/System.Xml.dll
-%_prefix/lib/mono/2.0/System.dll
-%_prefix/lib/mono/2.0/System.Json.dll
-%_prefix/lib/mono/2.0/al.exe*
-%_prefix/lib/mono/2.0/cscompmgd.dll
-%_prefix/lib/mono/2.0/gacutil.exe*
-%_prefix/lib/mono/2.0/mscorlib.dll*
-%_prefix/lib/mono/4.0/Commons.Xml.Relaxng.dll
-%_prefix/lib/mono/4.0/CustomMarshalers.dll
-%_prefix/lib/mono/4.0/I18N.West.dll
-%_prefix/lib/mono/4.0/I18N.dll
-%_prefix/lib/mono/4.0/ICSharpCode.SharpZipLib.dll
-%_prefix/lib/mono/4.0/Microsoft.CSharp.dll
-%_prefix/lib/mono/4.0/Microsoft.VisualC.dll
-%_prefix/lib/mono/4.0/Mono.C5.dll
-%_prefix/lib/mono/4.0/Mono.CSharp.dll
-%_prefix/lib/mono/4.0/Mono.Cairo.dll
-%_prefix/lib/mono/4.0/Mono.CompilerServices.SymbolWriter.dll
-%_prefix/lib/mono/4.0/Mono.Management.dll
-%_prefix/lib/mono/4.0/Mono.Parallel.dll
-%_prefix/lib/mono/4.0/Mono.Posix.dll
-%_prefix/lib/mono/4.0/Mono.Security.dll
-%_prefix/lib/mono/4.0/Mono.Simd.dll
-%_prefix/lib/mono/4.0/Mono.Tasklets.dll
-%_prefix/lib/mono/4.0/System.Configuration.dll
-%_prefix/lib/mono/4.0/System.Core.dll
-%_prefix/lib/mono/4.0/System.Drawing.dll
-%_prefix/lib/mono/4.0/System.Dynamic.dll
-%_prefix/lib/mono/4.0/System.Json.dll
-%_prefix/lib/mono/4.0/System.Json.Microsoft.dll
-%_prefix/lib/mono/4.0/System.Net.dll
-%_prefix/lib/mono/4.0/System.Numerics.dll
-%_prefix/lib/mono/4.0/System.Security.dll
-%_prefix/lib/mono/4.0/System.Xml.Linq.dll
-%_prefix/lib/mono/4.0/System.Xml.dll
-%_prefix/lib/mono/4.0/System.dll
-%_prefix/lib/mono/4.5/al.exe*
-%_prefix/lib/mono/4.5/certmgr.exe*
-%_prefix/lib/mono/4.5/chktrust.exe*
-%_prefix/lib/mono/4.5/crlupdate.exe*
-%_prefix/lib/mono/4.0/cscompmgd.dll
-%_prefix/lib/mono/4.5/csharp.exe*
-%_prefix/lib/mono/4.5/gacutil.exe*
-%_prefix/lib/mono/4.5/ikdasm.exe*
-%_prefix/lib/mono/4.5/mcs.exe*
-%_prefix/lib/mono/4.5/mozroots.exe*
-%_prefix/lib/mono/4.0/mscorlib.dll*
-%_prefix/lib/mono/4.5/setreg.exe*
-%_prefix/lib/mono/4.5/sn.exe*
-%_prefix/lib/mono/4.5/Commons.Xml.Relaxng.dll
-%_prefix/lib/mono/4.5/CustomMarshalers.dll
-%_prefix/lib/mono/4.5/I18N.CJK.dll
-%_prefix/lib/mono/4.5/I18N.MidEast.dll
-%_prefix/lib/mono/4.5/I18N.Other.dll
-%_prefix/lib/mono/4.5/I18N.Rare.dll
-%_prefix/lib/mono/4.5/I18N.West.dll
-%_prefix/lib/mono/4.5/I18N.dll
-%_prefix/lib/mono/4.5/IBM.Data.DB2.dll
-%_prefix/lib/mono/4.5/ICSharpCode.SharpZipLib.dll
-%_prefix/lib/mono/4.5/Microsoft.CSharp.dll
-%_prefix/lib/mono/4.5/Microsoft.VisualC.dll
-%_prefix/lib/mono/4.5/Mono.C5.dll
-%_prefix/lib/mono/4.5/Mono.CSharp.dll
-%_prefix/lib/mono/4.5/Mono.Cairo.dll
-%_prefix/lib/mono/4.5/Mono.CompilerServices.SymbolWriter.dll
-%_prefix/lib/mono/4.5/Mono.Management.dll
-%_prefix/lib/mono/4.5/Mono.Parallel.dll
-%_prefix/lib/mono/4.5/Mono.Posix.dll
-%_prefix/lib/mono/4.5/Mono.Security.dll
-%_prefix/lib/mono/4.5/Mono.Simd.dll
-%_prefix/lib/mono/4.5/Mono.Tasklets.dll
-%_prefix/lib/mono/4.5/System.Configuration.dll
-%_prefix/lib/mono/4.5/System.Core.dll
-%_prefix/lib/mono/4.5/System.Drawing.dll
-%_prefix/lib/mono/4.5/System.Dynamic.dll
-%_prefix/lib/mono/4.5/System.IO.Compression.dll
-%_prefix/lib/mono/4.5/System.IO.Compression.FileSystem.dll
-%_prefix/lib/mono/4.5/System.Json.dll
-%_prefix/lib/mono/4.5/System.Json.Microsoft.dll
-%_prefix/lib/mono/4.5/System.Net.dll
-%_prefix/lib/mono/4.5/System.Net.Http.dll
-%_prefix/lib/mono/4.5/System.Net.Http.WebRequest.dll
-%_prefix/lib/mono/4.5/System.Numerics.dll
-%_prefix/lib/mono/4.5/System.Security.dll
-%_prefix/lib/mono/4.5/System.Threading.Tasks.Dataflow.dll
-%_prefix/lib/mono/4.5/System.Xml.Linq.dll
-%_prefix/lib/mono/4.5/System.Xml.dll
-%_prefix/lib/mono/4.5/System.dll
-%_prefix/lib/mono/4.5/cscompmgd.dll
-%_prefix/lib/mono/4.5/mscorlib.dll*
-%_prefix/lib/mono/4.5/System.Windows.dll
-%_prefix/lib/mono/4.5/System.Xml.Serialization.dll
-%_prefix/lib/mono/4.5/Facades/*.dll
-%_prefix/lib/mono/compat-2.0/ICSharpCode.SharpZipLib.dll
-%_prefix/lib/mono/gac/Commons.Xml.Relaxng
-%_prefix/lib/mono/gac/CustomMarshalers
-%_prefix/lib/mono/gac/I18N
-%_prefix/lib/mono/gac/I18N.West
-%_prefix/lib/mono/gac/ICSharpCode.SharpZipLib
-%_prefix/lib/mono/gac/Microsoft.CSharp
-%_prefix/lib/mono/gac/Microsoft.VisualC
-%_prefix/lib/mono/gac/Mono.C5
-%_prefix/lib/mono/gac/Mono.CSharp
-%_prefix/lib/mono/gac/Mono.Cairo
-%_prefix/lib/mono/gac/Mono.Cecil
-%_prefix/lib/mono/gac/Mono.Cecil.Mdb
-%_prefix/lib/mono/gac/Mono.CompilerServices.SymbolWriter
-%_prefix/lib/mono/gac/Mono.Management
-%_prefix/lib/mono/gac/Mono.Parallel
-%_prefix/lib/mono/gac/Mono.Posix
-%_prefix/lib/mono/gac/Mono.Security
-%_prefix/lib/mono/gac/Mono.Simd
-%_prefix/lib/mono/gac/Mono.Tasklets
-%_prefix/lib/mono/gac/System
-%_prefix/lib/mono/gac/System.Configuration
-%_prefix/lib/mono/gac/System.Core
-%_prefix/lib/mono/gac/System.Drawing
-%_prefix/lib/mono/gac/System.Dynamic
-%_prefix/lib/mono/gac/System.IO.Compression
-%_prefix/lib/mono/gac/System.IO.Compression.FileSystem
-%_prefix/lib/mono/gac/System.Net
-%_prefix/lib/mono/gac/System.Net.Http
-%_prefix/lib/mono/gac/System.Net.Http.WebRequest
-%_prefix/lib/mono/gac/System.Numerics
-%_prefix/lib/mono/gac/System.Security
-%_prefix/lib/mono/gac/System.Threading.Tasks.Dataflow
-%_prefix/lib/mono/gac/System.Xml
-%_prefix/lib/mono/gac/System.Xml.Linq
-%_prefix/lib/mono/gac/System.Json
-%_prefix/lib/mono/gac/System.Json.Microsoft
-%_prefix/lib/mono/gac/System.Windows
-%_prefix/lib/mono/gac/System.Xml.Serialization
-%_prefix/lib/mono/gac/cscompmgd
-%_prefix/lib/mono/mono-configuration-crypto
-
-%package -n libmono-2_0-1
-License: LGPL v2.1 only
-Summary: A Library for embedding Mono in your Application
-Group: Development/Libraries/C and C++
-
-%description -n libmono-2_0-1
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-A Library for embedding Mono in your Application.
-
-%files -n libmono-2_0-1
-%defattr(-, root, root)
-%_libdir/libmono-2.0.so.1*
-
-%post -n libmono-2_0-1 -p /sbin/ldconfig
-
-%postun -n libmono-2_0-1 -p /sbin/ldconfig
-
-%package -n libmono-2_0-devel
-License: LGPL v2.1 only
-Summary: Development files for libmono
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-
-%description -n libmono-2_0-devel
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Development files for libmono.
-
-%files -n libmono-2_0-devel
-%defattr(-, root, root)
-%_bindir/mono-gdb.py
-%_includedir/mono-2.0
-%_libdir/libmono-2.0.a
-%_libdir/libmono-2.0.so
-%_libdir/pkgconfig/mono-2.pc
-
-%if %sgen == yes
-%package -n libmonosgen-2_0-1
-License: LGPL v2.1 only
-Summary: A Library for embedding Mono in your Application (sgen version)
-Group: Development/Libraries/C and C++
-
-%description -n libmonosgen-2_0-1
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-A Library for embedding Mono in your Application (sgen version).
-
-%files -n libmonosgen-2_0-1
-%defattr(-, root, root)
-%_libdir/libmonosgen-2.0.so.1*
-
-%post -n libmonosgen-2_0-1 -p /sbin/ldconfig
-
-%postun -n libmonosgen-2_0-1 -p /sbin/ldconfig
-
-%package -n libmonosgen-2_0-devel
-License: LGPL v2.1 only
-Summary: Development files for libmonosgen
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: libmono-2_0-devel
-
-%description -n libmonosgen-2_0-devel
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Development files for libmonosgen.
-
-%files -n libmonosgen-2_0-devel
-%defattr(-, root, root)
-%_bindir/mono-sgen-gdb.py
-%_libdir/libmonosgen-2.0.a
-%_libdir/libmonosgen-2.0.so
-%_libdir/pkgconfig/monosgen-2.pc
-%endif
-
-%package -n libmonoboehm-2_0-1
-License: LGPL v2.1 only
-Summary: A Library for embedding Mono in your Application (boehm version)
-Group: Development/Libraries/C and C++
-
-%description -n libmonoboehm-2_0-1
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-A Library for embedding Mono in your Application (boehm version).
-
-%files -n libmonoboehm-2_0-1
-%defattr(-, root, root)
-%_libdir/libmonoboehm-2.0.so.1*
-
-%post -n libmonoboehm-2_0-1 -p /sbin/ldconfig
-
-%postun -n libmonoboehm-2_0-1 -p /sbin/ldconfig
-
-%package -n libmonoboehm-2_0-devel
-License: LGPL v2.1 only
-Summary: Development files for libmonosgen
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: libmono-2_0-devel
-
-%description -n libmonoboehm-2_0-devel
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Development files for libmonoboehm.
-
-%files -n libmonoboehm-2_0-devel
-%defattr(-, root, root)
-%_libdir/libmonoboehm-2.0.a
-%_libdir/libmonoboehm-2.0.so
-
-%if %llvm == yes
-%package -n libmono-llvm0
-License: LGPL v2.1 only
-Summary: Loadable LLVM libary for mono
-Group: Development/Libraries/C and C++
-
-%description -n libmono-llvm0
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Loadable LLVM libary for mono.
-
-%files -n libmono-llvm0
-%defattr(-, root, root)
-%_libdir/libmono-llvm.so*
-
-%post -n libmono-llvm0 -p /sbin/ldconfig
-
-%postun -n libmono-llvm0 -p /sbin/ldconfig
-%endif
-
-%package -n mono-locale-extras
-License: LGPL v2.1 only
-Summary: Extra locale information
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Provides: mono(I18N.CJK) = 1.0.5000.0
-Provides: mono(I18N.MidEast) = 1.0.5000.0
-Provides: mono(I18N.Other) = 1.0.5000.0
-Provides: mono(I18N.Rare) = 1.0.5000.0
-
-%description -n mono-locale-extras
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Extra locale information.
-
-%files -n mono-locale-extras
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/I18N.CJK.dll
-%_prefix/lib/mono/2.0/I18N.MidEast.dll
-%_prefix/lib/mono/2.0/I18N.Other.dll
-%_prefix/lib/mono/2.0/I18N.Rare.dll
-%_prefix/lib/mono/4.0/I18N.CJK.dll
-%_prefix/lib/mono/4.0/I18N.MidEast.dll
-%_prefix/lib/mono/4.0/I18N.Other.dll
-%_prefix/lib/mono/4.0/I18N.Rare.dll
-%_prefix/lib/mono/4.5/I18N.CJK.dll
-%_prefix/lib/mono/4.5/I18N.MidEast.dll
-%_prefix/lib/mono/4.5/I18N.Other.dll
-%_prefix/lib/mono/4.5/I18N.Rare.dll
-%_prefix/lib/mono/gac/I18N.CJK
-%_prefix/lib/mono/gac/I18N.MidEast
-%_prefix/lib/mono/gac/I18N.Other
-%_prefix/lib/mono/gac/I18N.Rare
-
-%package -n mono-data
-License: LGPL v2.1 only
-Summary: Database connectivity for Mono
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Obsoletes: mono-directory
-Obsoletes: mono-ms-enterprise
-Obsoletes: mono-novell-directory
-Provides: mono-directory
-Provides: mono-ms-enterprise
-Provides: mono-novell-directory
-Provides: mono(Mono.Data.Tds) = 1.0.5000.0
-Provides: mono(Novell.Directory.Ldap) = 1.0.5000.0
-Provides: mono(System.Data) = 1.0.5000.0
-Provides: mono(System.DirectoryServices) = 1.0.5000.0
-Provides: mono(System.DirectoryServices.Protocols) = 1.0.5000.0
-Provides: mono(System.EnterpriseServices) = 1.0.5000.0
-
-%description -n mono-data
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Database connectivity for Mono.
-
-%files -n mono-data
-%defattr(-, root, root)
-%_bindir/sqlmetal
-%_bindir/sqlsharp
-%_mandir/man1/sqlsharp.1%ext_man
-%_prefix/lib/mono/2.0/Mono.Data.Tds.dll
-%_prefix/lib/mono/2.0/Novell.Directory.Ldap.dll
-%_prefix/lib/mono/2.0/System.Data.DataSetExtensions.dll
-%_prefix/lib/mono/2.0/System.Data.Linq.dll
-%_prefix/lib/mono/2.0/System.Data.dll
-%_prefix/lib/mono/2.0/System.DirectoryServices.dll
-%_prefix/lib/mono/2.0/System.DirectoryServices.Protocols.dll
-%_prefix/lib/mono/2.0/System.EnterpriseServices.dll
-%_prefix/lib/mono/2.0/System.Runtime.Serialization.dll
-%_prefix/lib/mono/2.0/System.Transactions.dll
-%_prefix/lib/mono/4.0/Mono.Data.Tds.dll
-%_prefix/lib/mono/4.0/Novell.Directory.Ldap.dll
-%_prefix/lib/mono/4.0/System.Data.DataSetExtensions.dll
-%_prefix/lib/mono/4.0/System.Data.Linq.dll
-%_prefix/lib/mono/4.0/System.Data.dll
-%_prefix/lib/mono/4.0/System.DirectoryServices.dll
-%_prefix/lib/mono/4.0/System.DirectoryServices.Protocols.dll
-%_prefix/lib/mono/4.0/System.EnterpriseServices.dll
-%_prefix/lib/mono/4.0/System.Runtime.Serialization.dll
-%_prefix/lib/mono/4.0/System.Transactions.dll
-%_prefix/lib/mono/4.0/WebMatrix.Data.dll
-%_prefix/lib/mono/4.5/Mono.Data.Tds.dll
-%_prefix/lib/mono/4.5/Novell.Directory.Ldap.dll
-%_prefix/lib/mono/4.5/System.Data.DataSetExtensions.dll
-%_prefix/lib/mono/4.5/System.Data.Linq.dll
-%_prefix/lib/mono/4.5/System.Data.dll
-%_prefix/lib/mono/4.5/System.DirectoryServices.dll
-%_prefix/lib/mono/4.5/System.DirectoryServices.Protocols.dll
-%_prefix/lib/mono/4.5/System.EnterpriseServices.dll
-%_prefix/lib/mono/4.5/System.Runtime.Serialization.dll
-%_prefix/lib/mono/4.5/System.Transactions.dll
-%_prefix/lib/mono/4.5/WebMatrix.Data.dll
-%_prefix/lib/mono/4.5/EntityFramework.dll
-%_prefix/lib/mono/4.5/EntityFramework.SqlServer.dll
-%_prefix/lib/mono/4.5/sqlmetal.exe*
-%_prefix/lib/mono/4.5/sqlsharp.exe*
-%_prefix/lib/mono/gac/Mono.Data.Tds
-%_prefix/lib/mono/gac/Novell.Directory.Ldap
-%_prefix/lib/mono/gac/System.Data
-%_prefix/lib/mono/gac/System.Data.DataSetExtensions
-%_prefix/lib/mono/gac/System.Data.Linq
-%_prefix/lib/mono/gac/System.DirectoryServices
-%_prefix/lib/mono/gac/System.DirectoryServices.Protocols
-%_prefix/lib/mono/gac/System.EnterpriseServices
-%_prefix/lib/mono/gac/System.Runtime.Serialization
-%_prefix/lib/mono/gac/System.Transactions
-%_prefix/lib/mono/gac/WebMatrix.Data
-%_prefix/lib/mono/gac/EntityFramework
-%_prefix/lib/mono/gac/EntityFramework.SqlServer
-
-%package -n mono-winforms
-License: LGPL v2.1 only
-Summary: Mono's Windows Forms implementation
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Provides: mono-window-forms
-Obsoletes: mono-window-forms
-Provides: mono(Accessibility) = 1.0.5000.0
-Provides: mono(System.Design) = 1.0.5000.0
-Provides: mono(System.Drawing) = 1.0.5000.0
-Provides: mono(System.Drawing.Design) = 1.0.5000.0
-Provides: mono(System.Windows.Forms) = 1.0.5000.0
-
-%description -n mono-winforms
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Mono's Windows Forms implementation.
-
-%files -n mono-winforms
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/Accessibility.dll
-%_prefix/lib/mono/2.0/Mono.WebBrowser.dll
-%_prefix/lib/mono/2.0/System.Design.dll
-%_prefix/lib/mono/2.0/System.Drawing.Design.dll
-%_prefix/lib/mono/2.0/System.Windows.Forms.dll
-%_prefix/lib/mono/4.0/Accessibility.dll
-%_prefix/lib/mono/4.0/Mono.WebBrowser.dll
-%_prefix/lib/mono/4.0/System.Design.dll
-%_prefix/lib/mono/4.0/System.Drawing.Design.dll
-%_prefix/lib/mono/4.0/System.Windows.Forms.DataVisualization.dll
-%_prefix/lib/mono/4.0/System.Windows.Forms.dll
-%_prefix/lib/mono/4.5/Accessibility.dll
-%_prefix/lib/mono/4.5/Mono.WebBrowser.dll
-%_prefix/lib/mono/4.5/System.Design.dll
-%_prefix/lib/mono/4.5/System.Drawing.Design.dll
-%_prefix/lib/mono/4.5/System.Windows.Forms.DataVisualization.dll
-%_prefix/lib/mono/4.5/System.Windows.Forms.dll
-%_prefix/lib/mono/gac/Accessibility
-%_prefix/lib/mono/gac/Mono.WebBrowser
-%_prefix/lib/mono/gac/System.Design
-%_prefix/lib/mono/gac/System.Drawing.Design
-%_prefix/lib/mono/gac/System.Windows.Forms
-%_prefix/lib/mono/gac/System.Windows.Forms.DataVisualization
-
-%package -n ibm-data-db2
-License: LGPL v2.1 only
-Summary: Database connectivity for DB2
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-
-%description -n ibm-data-db2
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Database connectivity for DB2.
-
-%files -n ibm-data-db2
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/IBM.Data.DB2.dll
-%_prefix/lib/mono/4.0/IBM.Data.DB2.dll
-%_prefix/lib/mono/4.5/IBM.Data.DB2.dll
-%_prefix/lib/mono/gac/IBM.Data.DB2
-
-%package -n mono-extras
-License: LGPL v2.1 only
-Summary: Extra packages
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Obsoletes: mono-ms-extras
-Provides: mono-ms-extras
-Provides: mono(Mono.Messaging) = 1.0.5000.0
-Provides: mono(Mono.Messaging.RabbitMQ) = 1.0.5000.0
-Provides: mono(RabbitMQ.Client) = 1.0.5000.0
-Provides: mono(System.Configuration.Install) = 1.0.5000.0
-Provides: mono(System.Management) = 1.0.5000.0
-Provides: mono(System.Messaging) = 1.0.5000.0
-Provides: mono(System.ServiceProcess) = 1.0.5000.0
-Provides: mono(mono-service) = 1.0.5000.0
-
-%description -n mono-extras
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Extra packages.
-
-%files -n mono-extras
-%defattr(-, root, root)
-%_bindir/mono-service
-%_bindir/mono-service2
-%_mandir/man1/mono-service.1%ext_man
-%_prefix/lib/mono/2.0/Mono.Messaging.RabbitMQ.dll
-%_prefix/lib/mono/2.0/Mono.Messaging.dll
-%_prefix/lib/mono/2.0/RabbitMQ.Client.Apigen.exe*
-%_prefix/lib/mono/2.0/RabbitMQ.Client.dll
-%_prefix/lib/mono/2.0/System.Configuration.Install.dll
-%_prefix/lib/mono/2.0/System.Management.dll
-%_prefix/lib/mono/2.0/System.Messaging.dll
-%_prefix/lib/mono/2.0/System.ServiceProcess.dll
-%_prefix/lib/mono/2.0/mono-service.exe*
-%_prefix/lib/mono/4.0/Mono.Messaging.RabbitMQ.dll
-%_prefix/lib/mono/4.0/Mono.Messaging.dll
-%_prefix/lib/mono/4.0/RabbitMQ.Client.Apigen.exe*
-%_prefix/lib/mono/4.0/RabbitMQ.Client.dll
-%_prefix/lib/mono/4.0/System.Configuration.Install.dll
-%_prefix/lib/mono/4.0/System.Management.dll
-%_prefix/lib/mono/4.0/System.Messaging.dll
-%_prefix/lib/mono/4.0/System.Runtime.Caching.dll
-%_prefix/lib/mono/4.0/System.ServiceProcess.dll
-%_prefix/lib/mono/4.0/System.Xaml.dll
-%_prefix/lib/mono/4.5/installutil.exe*
-%_prefix/lib/mono/4.5/mono-service.exe*
-%_prefix/lib/mono/4.5/Mono.Messaging.RabbitMQ.dll
-%_prefix/lib/mono/4.5/Mono.Messaging.dll
-%_prefix/lib/mono/4.5/RabbitMQ.Client.Apigen.exe*
-%_prefix/lib/mono/4.5/RabbitMQ.Client.dll
-%_prefix/lib/mono/4.5/System.Configuration.Install.dll
-%_prefix/lib/mono/4.5/System.Management.dll
-%_prefix/lib/mono/4.5/System.Messaging.dll
-%_prefix/lib/mono/4.5/System.Runtime.Caching.dll
-%_prefix/lib/mono/4.5/System.ServiceProcess.dll
-%_prefix/lib/mono/4.5/System.Xaml.dll
-%_prefix/lib/mono/gac/Mono.Messaging
-%_prefix/lib/mono/gac/Mono.Messaging.RabbitMQ
-%_prefix/lib/mono/gac/RabbitMQ.Client
-%_prefix/lib/mono/gac/System.Configuration.Install
-%_prefix/lib/mono/gac/System.Management
-%_prefix/lib/mono/gac/System.Messaging
-%_prefix/lib/mono/gac/System.Runtime.Caching
-%_prefix/lib/mono/gac/System.ServiceProcess
-%_prefix/lib/mono/gac/System.Xaml
-%_prefix/lib/mono/gac/mono-service
-
-%package -n mono-data-sqlite
-License: LGPL v2.1 only
-Summary: Database connectivity for Mono
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: mono-data == %version-%release
-Provides: mono(Mono.Data.Sqlite) = 1.0.5000.0
-
-%description -n mono-data-sqlite
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Database connectivity for Mono.
-
-%files -n mono-data-sqlite
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/Mono.Data.Sqlite.dll
-%_prefix/lib/mono/4.0/Mono.Data.Sqlite.dll
-%_prefix/lib/mono/4.5/Mono.Data.Sqlite.dll
-%_prefix/lib/mono/gac/Mono.Data.Sqlite
-
-%package -n mono-wcf
-License: MIT License (or similar) ; Ms-Pl
-Summary: Mono implementation of WCF, Windows Communication Foundation
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-
-%description -n mono-wcf
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Mono implementation of WCF, Windows Communication Foundation
-
-%files -n mono-wcf
-%defattr(-, root, root)
-%_bindir/svcutil
-%_libdir/pkgconfig/wcf.pc
-%_prefix/lib/mono/2.0/System.Data.Services.dll
-%_prefix/lib/mono/2.0/System.IdentityModel.Selectors.dll
-%_prefix/lib/mono/2.0/System.IdentityModel.dll
-%_prefix/lib/mono/2.0/System.ServiceModel.Web.dll
-%_prefix/lib/mono/2.0/System.ServiceModel.dll
-%_prefix/lib/mono/4.0/System.Data.Services.dll
-%_prefix/lib/mono/4.0/System.IdentityModel.Selectors.dll
-%_prefix/lib/mono/4.0/System.IdentityModel.dll
-%_prefix/lib/mono/4.0/System.Runtime.DurableInstancing.dll
-%_prefix/lib/mono/4.0/System.ServiceModel.Activation.dll
-%_prefix/lib/mono/4.0/System.ServiceModel.Discovery.dll
-%_prefix/lib/mono/4.0/System.ServiceModel.Routing.dll
-%_prefix/lib/mono/4.0/System.ServiceModel.Web.dll
-%_prefix/lib/mono/4.0/System.ServiceModel.dll
-%_prefix/lib/mono/4.5/System.Data.Services.dll
-%_prefix/lib/mono/4.5/System.IdentityModel.Selectors.dll
-%_prefix/lib/mono/4.5/System.IdentityModel.dll
-%_prefix/lib/mono/4.5/System.Runtime.DurableInstancing.dll
-%_prefix/lib/mono/4.5/System.ServiceModel.Activation.dll
-%_prefix/lib/mono/4.5/System.ServiceModel.Discovery.dll
-%_prefix/lib/mono/4.5/System.ServiceModel.Routing.dll
-%_prefix/lib/mono/4.5/System.ServiceModel.Web.dll
-%_prefix/lib/mono/4.5/System.ServiceModel.dll
-%_prefix/lib/mono/4.5/svcutil.exe*
-%_prefix/lib/mono/gac/System.Data.Services
-%_prefix/lib/mono/gac/System.IdentityModel
-%_prefix/lib/mono/gac/System.IdentityModel.Selectors
-%_prefix/lib/mono/gac/System.Runtime.DurableInstancing
-%_prefix/lib/mono/gac/System.ServiceModel
-%_prefix/lib/mono/gac/System.ServiceModel.Activation
-%_prefix/lib/mono/gac/System.ServiceModel.Discovery
-%_prefix/lib/mono/gac/System.ServiceModel.Routing
-%_prefix/lib/mono/gac/System.ServiceModel.Web
-
-%package -n mono-winfxcore
-License: MIT License (or similar) ; Ms-Pl
-Summary: Mono implementation of core WinFX APIs
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-
-%description -n mono-winfxcore
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Mono implementation of core WinFX APIs
-
-%files -n mono-winfxcore
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/System.Data.Services.Client.dll*
-%_prefix/lib/mono/2.0/WindowsBase.dll*
-%_prefix/lib/mono/4.0/System.Data.Services.Client.dll*
-%_prefix/lib/mono/4.0/WindowsBase.dll*
-%_prefix/lib/mono/4.5/System.Data.Services.Client.dll*
-%_prefix/lib/mono/4.5/WindowsBase.dll*
-%_prefix/lib/mono/gac/System.Data.Services.Client
-%_prefix/lib/mono/gac/WindowsBase
-
-%package -n mono-web
-License: MIT License (or similar) ; Ms-Pl
-Summary: Mono implementation of ASP.NET, Remoting and Web Services
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Obsoletes: mono-remoting
-Obsoletes: mono-web-forms
-Obsoletes: mono-web-services
-Provides: mono-remoting
-Provides: mono-web-forms
-Provides: mono-web-services
-Provides: mono(Mono.Http) = 1.0.5000.0
-Provides: mono(System.Runtime.Remoting) = 1.0.5000.0
-Provides: mono(System.Runtime.Serialization.Formatters.Soap) = 1.0.5000.0
-Provides: mono(System.Web) = 1.0.5000.0
-Provides: mono(System.Web.Services) = 1.0.5000.0
-
-%description -n mono-web
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Mono implementation of ASP.NET, Remoting and Web Services.
-
-%files -n mono-web
-%defattr(-, root, root)
-%config %_sysconfdir/mono/2.0/Browsers
-%config %_sysconfdir/mono/2.0/DefaultWsdlHelpGenerator.aspx
-%config %_sysconfdir/mono/2.0/web.config
-%config %_sysconfdir/mono/4.0/Browsers
-%config %_sysconfdir/mono/4.0/DefaultWsdlHelpGenerator.aspx
-%config %_sysconfdir/mono/4.0/web.config
-%config %_sysconfdir/mono/4.5/Browsers
-%config %_sysconfdir/mono/4.5/DefaultWsdlHelpGenerator.aspx
-%config %_sysconfdir/mono/4.5/web.config
-%config %_sysconfdir/mono/browscap.ini
-%config %_sysconfdir/mono/mconfig/config.xml
-%dir %_sysconfdir/mono/mconfig
-%_bindir/disco
-%_bindir/mconfig
-%_bindir/soapsuds
-%_bindir/wsdl
-%_bindir/wsdl2
-%_bindir/xsd
-%_libdir/pkgconfig/aspnetwebstack.pc
-%_mandir/man1/disco.1%ext_man
-%_mandir/man1/mconfig.1%ext_man
-%_mandir/man1/soapsuds.1%ext_man
-%_mandir/man1/wsdl.1%ext_man
-%_mandir/man1/xsd.1%ext_man
-%_prefix/lib/mono/2.0/Mono.Http.dll
-%_prefix/lib/mono/2.0/System.ComponentModel.DataAnnotations.dll
-%_prefix/lib/mono/2.0/System.Runtime.Remoting.dll
-%_prefix/lib/mono/2.0/System.Runtime.Serialization.Formatters.Soap.dll
-%_prefix/lib/mono/2.0/System.Web.Abstractions.dll
-%_prefix/lib/mono/2.0/System.Web.Routing.dll
-%_prefix/lib/mono/2.0/System.Web.Services.dll
-%_prefix/lib/mono/2.0/System.Web.dll
-%_prefix/lib/mono/2.0/wsdl.exe*
-%_prefix/lib/mono/2.0/xsd.exe*
-%_prefix/lib/mono/4.0/Microsoft.Web.Infrastructure.dll
-%_prefix/lib/mono/4.0/Mono.Http.dll
-%_prefix/lib/mono/4.0/System.ComponentModel.Composition.dll
-%_prefix/lib/mono/4.0/System.ComponentModel.DataAnnotations.dll
-%_prefix/lib/mono/4.0/System.Runtime.Remoting.dll
-%_prefix/lib/mono/4.0/System.Runtime.Serialization.Formatters.Soap.dll
-%_prefix/lib/mono/4.0/System.Web.Abstractions.dll
-%_prefix/lib/mono/4.0/System.Web.ApplicationServices.dll
-%_prefix/lib/mono/4.0/System.Web.Routing.dll
-%_prefix/lib/mono/4.0/System.Web.Services.dll
-%_prefix/lib/mono/4.0/System.Web.dll
-%_prefix/lib/mono/4.5/Mono.Http.dll
-%_prefix/lib/mono/4.5/System.ComponentModel.Composition.dll
-%_prefix/lib/mono/4.5/System.ComponentModel.DataAnnotations.dll
-%_prefix/lib/mono/4.5/System.Net.Http.Formatting.dll
-%_prefix/lib/mono/4.5/System.Runtime.Remoting.dll
-%_prefix/lib/mono/4.5/System.Runtime.Serialization.Formatters.Soap.dll
-%_prefix/lib/mono/4.5/System.Web.Abstractions.dll
-%_prefix/lib/mono/4.5/System.Web.ApplicationServices.dll
-%_prefix/lib/mono/4.5/System.Web.Http.dll
-%_prefix/lib/mono/4.5/System.Web.Http.SelfHost.dll
-%_prefix/lib/mono/4.5/System.Web.Http.WebHost.dll
-%_prefix/lib/mono/4.5/System.Web.Routing.dll
-%_prefix/lib/mono/4.5/System.Web.Razor.dll
-%_prefix/lib/mono/4.5/System.Web.Services.dll
-%_prefix/lib/mono/4.5/System.Web.WebPages.Deployment.dll
-%_prefix/lib/mono/4.5/System.Web.WebPages.Razor.dll
-%_prefix/lib/mono/4.5/System.Web.WebPages.dll
-%_prefix/lib/mono/4.5/System.Web.dll
-%_prefix/lib/mono/4.5/disco.exe*
-%_prefix/lib/mono/4.5/mconfig.exe*
-%_prefix/lib/mono/4.5/soapsuds.exe*
-%_prefix/lib/mono/4.5/wsdl.exe*
-%_prefix/lib/mono/4.5/xsd.exe*
-%_prefix/lib/mono/4.5/Microsoft.Web.Infrastructure.dll
-%_prefix/lib/mono/gac/Microsoft.Web.Infrastructure
-%_prefix/lib/mono/gac/Mono.Http
-%_prefix/lib/mono/gac/System.ComponentModel.Composition
-%_prefix/lib/mono/gac/System.ComponentModel.DataAnnotations
-%_prefix/lib/mono/gac/System.Net.Http.Formatting
-%_prefix/lib/mono/gac/System.Runtime.Remoting
-%_prefix/lib/mono/gac/System.Runtime.Serialization.Formatters.Soap
-%_prefix/lib/mono/gac/System.Web
-%_prefix/lib/mono/gac/System.Web.Abstractions
-%_prefix/lib/mono/gac/System.Web.ApplicationServices
-%_prefix/lib/mono/gac/System.Web.Http
-%_prefix/lib/mono/gac/System.Web.Http.SelfHost
-%_prefix/lib/mono/gac/System.Web.Http.WebHost
-%_prefix/lib/mono/gac/System.Web.Routing
-%_prefix/lib/mono/gac/System.Web.Razor
-%_prefix/lib/mono/gac/System.Web.Services
-%_prefix/lib/mono/gac/System.Web.WebPages.Deployment
-%_prefix/lib/mono/gac/System.Web.WebPages.Razor
-%_prefix/lib/mono/gac/System.Web.WebPages
-
-%package -n mono-mvc
-License: MIT License (or similar) ; Ms-Pl
-Summary: Mono implementation of ASP.NET MVC
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-
-%description -n mono-mvc
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Mono implementation of ASP.NET MVC.
-
-%files -n mono-mvc
-%defattr(-, root, root)
-%_libdir/pkgconfig/system.web.extensions.design_1.0.pc
-%_libdir/pkgconfig/system.web.extensions_1.0.pc
-%_libdir/pkgconfig/system.web.mvc.pc
-%_libdir/pkgconfig/system.web.mvc2.pc
-%_libdir/pkgconfig/system.web.mvc3.pc
-%_prefix/lib/mono/2.0/System.Web.DynamicData.dll
-%_prefix/lib/mono/2.0/System.Web.Extensions.Design.dll
-%_prefix/lib/mono/2.0/System.Web.Extensions.dll
-%_prefix/lib/mono/2.0/System.Web.Mvc.dll
-%_prefix/lib/mono/4.0/System.Web.DynamicData.dll
-%_prefix/lib/mono/4.0/System.Web.Extensions.Design.dll
-%_prefix/lib/mono/4.0/System.Web.Extensions.dll
-%_prefix/lib/mono/4.5/System.Web.DynamicData.dll
-%_prefix/lib/mono/4.5/System.Web.Extensions.Design.dll
-%_prefix/lib/mono/4.5/System.Web.Extensions.dll
-%_prefix/lib/mono/4.5/System.Web.Mvc.dll
-%_prefix/lib/mono/compat-2.0/System.Web.Extensions.Design.dll
-%_prefix/lib/mono/compat-2.0/System.Web.Extensions.dll
-%_prefix/lib/mono/compat-2.0/System.Web.Mvc.dll
-%_prefix/lib/mono/gac/System.Web.DynamicData
-%_prefix/lib/mono/gac/System.Web.Extensions
-%_prefix/lib/mono/gac/System.Web.Extensions.Design
-%_prefix/lib/mono/gac/System.Web.Mvc
-
-%package -n mono-data-oracle
-License: LGPL v2.1 only
-Summary: Database connectivity for Mono
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: mono-data == %version-%release
-Provides: mono(System.Data.OracleClient) = 1.0.5000.0
-
-%description -n mono-data-oracle
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Database connectivity for Mono.
-
-%files -n mono-data-oracle
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/System.Data.OracleClient.dll
-%_prefix/lib/mono/4.0/System.Data.OracleClient.dll
-%_prefix/lib/mono/4.5/System.Data.OracleClient.dll
-%_prefix/lib/mono/gac/System.Data.OracleClient
-
-%package -n mono-data-postgresql
-License: LGPL v2.1 only
-Summary: Database connectivity for Mono
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: mono-data == %version-%release
-Provides: mono(Npgsql) = 1.0.5000.0
-
-%description -n mono-data-postgresql
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Database connectivity for Mono.
-
-%files -n mono-data-postgresql
-%defattr(-, root, root)
-%_prefix/lib/mono/2.0/Npgsql.dll
-%_prefix/lib/mono/4.0/Npgsql.dll
-%_prefix/lib/mono/4.5/Npgsql.dll
-%_prefix/lib/mono/gac/Npgsql
-
-%package -n mono-rx-core
-License: MIT License (or similar) ; Apache License 2.0
-Summary: Reactive Extensions for Mono core libraries
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Provides: mono(System.Reactive.Interfaces) = 1.0.5000.0
-
-%description -n mono-rx-core
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Reactive Extensions for Mono, core packages, which don't depend on
-desktop-specific features.
-
-%files -n mono-rx-core
-%defattr(-, root, root)
-%_libdir/pkgconfig/reactive.pc
-%_prefix/lib/mono/4.5/System.Reactive.Core.dll
-%_prefix/lib/mono/4.5/System.Reactive.Debugger.dll
-%_prefix/lib/mono/4.5/System.Reactive.Experimental.dll
-%_prefix/lib/mono/4.5/System.Reactive.Interfaces.dll
-%_prefix/lib/mono/4.5/System.Reactive.Linq.dll
-%_prefix/lib/mono/4.5/System.Reactive.Observable.Aliases.dll
-%_prefix/lib/mono/4.5/System.Reactive.PlatformServices.dll
-%_prefix/lib/mono/4.5/System.Reactive.Providers.dll
-%_prefix/lib/mono/4.5/System.Reactive.Runtime.Remoting.dll
-%_prefix/lib/mono/gac/System.Reactive.Core
-%_prefix/lib/mono/gac/System.Reactive.Debugger
-%_prefix/lib/mono/gac/System.Reactive.Experimental
-%_prefix/lib/mono/gac/System.Reactive.Interfaces
-%_prefix/lib/mono/gac/System.Reactive.Linq
-%_prefix/lib/mono/gac/System.Reactive.Observable.Aliases
-%_prefix/lib/mono/gac/System.Reactive.PlatformServices
-%_prefix/lib/mono/gac/System.Reactive.Providers
-%_prefix/lib/mono/gac/System.Reactive.Runtime.Remoting
-
-%package -n mono-rx-desktop
-License: MIT License (or similar) ; Apache License 2.0
-Summary: Reactive Extensions for Mono desktop-specific libraries
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: mono-rx-core == %version-%release
-Provides: mono(System.Reactive.Interfaces) = 1.0.5000.0
-
-%description -n mono-rx-desktop
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Reactive Extensions for Mono, desktop-specific packages (winforms,
-windows threading).
-
-%files -n mono-rx-desktop
-%defattr(-, root, root)
-%_prefix/lib/mono/4.5/System.Reactive.Windows.Forms.dll
-%_prefix/lib/mono/4.5/System.Reactive.Windows.Threading.dll
-%_prefix/lib/mono/gac/System.Reactive.Windows.Forms
-%_prefix/lib/mono/gac/System.Reactive.Windows.Threading
-
-%package -n mono-nunit
-License: LGPL v2.1 only
-Summary: NUnit Testing Framework
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-
-%description -n mono-nunit
-NUnit is a unit-testing framework for all .Net languages. Initially
-ported from JUnit, the current release, version 2.2, is the fourth
-major release of this Unit based unit testing tool for Microsoft .NET.
-It is written entirely in C# and has been completely redesigned to
-take advantage of many .NET language features, for example
-custom attributes and other reflection related capabilities. NUnit
-brings xUnit to all .NET languages.
-
-%files -n mono-nunit
-%defattr(-, root, root)
-%_libdir/pkgconfig/mono-nunit.pc
-%_prefix/bin/nunit-console
-%_prefix/bin/nunit-console2
-%_prefix/bin/nunit-console4
-%_prefix/lib/mono/2.0/nunit-console-runner.dll
-%_prefix/lib/mono/2.0/nunit-console.exe*
-%_prefix/lib/mono/2.0/nunit.core.dll
-%_prefix/lib/mono/2.0/nunit.core.extensions.dll
-%_prefix/lib/mono/2.0/nunit.core.interfaces.dll
-%_prefix/lib/mono/2.0/nunit.framework.dll
-%_prefix/lib/mono/2.0/nunit.framework.extensions.dll
-%_prefix/lib/mono/2.0/nunit.mocks.dll
-%_prefix/lib/mono/2.0/nunit.util.dll
-%_prefix/lib/mono/4.5/nunit-console-runner.dll
-%_prefix/lib/mono/4.5/nunit-console.exe*
-%_prefix/lib/mono/4.5/nunit.core.dll
-%_prefix/lib/mono/4.5/nunit.core.extensions.dll
-%_prefix/lib/mono/4.5/nunit.core.interfaces.dll
-%_prefix/lib/mono/4.5/nunit.framework.dll
-%_prefix/lib/mono/4.5/nunit.framework.extensions.dll
-%_prefix/lib/mono/4.5/nunit.mocks.dll
-%_prefix/lib/mono/4.5/nunit.util.dll
-%_prefix/lib/mono/gac/nunit-console-runner
-%_prefix/lib/mono/gac/nunit.core
-%_prefix/lib/mono/gac/nunit.core.extensions
-%_prefix/lib/mono/gac/nunit.core.interfaces
-%_prefix/lib/mono/gac/nunit.framework
-%_prefix/lib/mono/gac/nunit.framework.extensions
-%_prefix/lib/mono/gac/nunit.mocks
-%_prefix/lib/mono/gac/nunit.util
-
-%package -n mono-devel
-License: LGPL v2.1 only
-Summary: Mono development tools
-Group: Development/Languages/Mono
-Requires: mono-core == %version-%release
-Requires: libgdiplus0
-Requires: pkgconfig
-Provides: mono-xbuild
-# Required because they are referenced by .pc files
-Requires: mono-data == %version-%release
-Requires: mono-data-oracle == %version-%release
-Requires: mono-extras == %version-%release
-Requires: mono-web == %version-%release
-Requires: mono-winforms == %version-%release
-# We build natively on ppc64 now
-%ifarch ppc64
-Provides: mono-biarchcompat
-Obsoletes: mono-biarchcompat
-%endif
-Provides: mono(PEAPI) = 1.0.5000.0
-Provides: mono(resgen) = 1.0.5000.0
-
-%description -n mono-devel
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. This package contains compilers and
-other tools needed to develop .NET applications.
-
-Mono development tools.
-
-%post -n mono-devel -p /sbin/ldconfig
-
-%postun -n mono-devel -p /sbin/ldconfig
-
-%files -n mono-devel
-%defattr(-, root, root)
-%_bindir/caspol
-%_bindir/ccrewrite
-%_bindir/cccheck
-%_bindir/cert2spc
-%_bindir/dtd2rng
-%_bindir/dtd2xsd
-%_bindir/genxs
-%_bindir/httpcfg
-%_bindir/ilasm
-%_bindir/installvst
-%_bindir/lc
-%_bindir/macpack
-%_bindir/makecert
-%_bindir/mkbundle
-%_bindir/mono-api-info
-%_bindir/mono-cil-strip
-%_bindir/mono-find-provides
-%_bindir/mono-find-requires
-%_bindir/mono-heapviz
-%_bindir/mono-shlib-cop
-%_bindir/mono-xmltool
-%_bindir/monodis
-%_bindir/monograph
-%_bindir/monolinker
-%_bindir/monop
-%_bindir/monop2
-%_bindir/mprof-report
-%_bindir/pdb2mdb
-%_bindir/pedump
-%_bindir/permview
-%_bindir/prj2make
-%_bindir/resgen
-%_bindir/resgen2
-%_bindir/secutil
-%_bindir/sgen
-%_bindir/signcode
-%_bindir/xbuild
-%_bindir/mdbrebase
-%dir %_datadir/mono-2.0
-%dir %_datadir/mono-2.0/mono
-%dir %_datadir/mono-2.0/mono/cil
-%_datadir/mono-2.0/mono/cil/cil-opcodes.xml
-%_libdir/libmono-profiler-*.*
-%_libdir/pkgconfig/cecil.pc
-%_libdir/pkgconfig/dotnet.pc
-%_libdir/pkgconfig/dotnet35.pc
-%_libdir/pkgconfig/mono-cairo.pc
-%_libdir/pkgconfig/mono-lineeditor.pc
-%_libdir/pkgconfig/mono-options.pc
-%_libdir/pkgconfig/mono.pc
-%_libdir/pkgconfig/xbuild12.pc
-%_mandir/man1/al.1%ext_man
-%_mandir/man1/ccrewrite.1%ext_man
-%_mandir/man1/cccheck.1%ext_man
-%_mandir/man1/cert2spc.1%ext_man
-%_mandir/man1/dtd2xsd.1%ext_man
-%_mandir/man1/genxs.1%ext_man
-%_mandir/man1/httpcfg.1%ext_man
-%_mandir/man1/ilasm.1%ext_man
-%_mandir/man1/lc.1%ext_man
-%_mandir/man1/macpack.1%ext_man
-%_mandir/man1/makecert.1%ext_man
-%_mandir/man1/mkbundle.1%ext_man
-%_mandir/man1/mono-api-info.1%ext_man
-%_mandir/man1/mono-cil-strip.1%ext_man
-%_mandir/man1/mono-shlib-cop.1%ext_man
-%_mandir/man1/mono-xmltool.1%ext_man
-%_mandir/man1/monodis.1%ext_man
-%_mandir/man1/monolinker.1%ext_man
-%_mandir/man1/monop.1%ext_man
-%_mandir/man1/mprof-report.1%ext_man
-%_mandir/man1/pdb2mdb.1%ext_man
-%_mandir/man1/permview.1%ext_man
-%_mandir/man1/prj2make.1%ext_man
-%_mandir/man1/resgen.1%ext_man
-%_mandir/man1/secutil.1%ext_man
-%_mandir/man1/sgen.1%ext_man
-%_mandir/man1/signcode.1%ext_man
-%_mandir/man1/xbuild.1%ext_man
-%_prefix/lib/mono-source-libs
-%_prefix/lib/mono/2.0/MSBuild
-%_prefix/lib/mono/2.0/Microsoft.Build.Engine.dll
-%_prefix/lib/mono/2.0/Microsoft.Build.Framework.dll
-%_prefix/lib/mono/2.0/Microsoft.Build.Tasks.dll
-%_prefix/lib/mono/2.0/Microsoft.Build.Utilities.dll
-%_prefix/lib/mono/2.0/Microsoft.Build.xsd
-%_prefix/lib/mono/2.0/Microsoft.CSharp.targets
-%_prefix/lib/mono/2.0/Microsoft.Common.targets
-%_prefix/lib/mono/2.0/Microsoft.Common.tasks
-%_prefix/lib/mono/2.0/Microsoft.VisualBasic.targets
-%_prefix/lib/mono/2.0/Mono.Debugger.Soft.dll
-%_prefix/lib/mono/2.0/Mono.XBuild.Tasks.dll
-%_prefix/lib/mono/2.0/PEAPI.dll
-%_prefix/lib/mono/2.0/genxs.exe*
-%_prefix/lib/mono/2.0/ilasm.exe*
-%_prefix/lib/mono/2.0/mkbundle.exe*
-%_prefix/lib/mono/2.0/monolinker.*
-%_prefix/lib/mono/2.0/monop.exe*
-%_prefix/lib/mono/2.0/resgen.exe*
-%_prefix/lib/mono/2.0/xbuild.exe*
-%_prefix/lib/mono/2.0/xbuild.rsp
-%_prefix/lib/mono/3.5/MSBuild
-%_prefix/lib/mono/3.5/Microsoft.Build.Engine.dll
-%_prefix/lib/mono/3.5/Microsoft.Build.Framework.dll
-%_prefix/lib/mono/3.5/Microsoft.Build.Tasks.v3.5.dll
-%_prefix/lib/mono/3.5/Microsoft.Build.Utilities.v3.5.dll
-%_prefix/lib/mono/3.5/Microsoft.Build.xsd
-%_prefix/lib/mono/3.5/Microsoft.CSharp.targets
-%_prefix/lib/mono/3.5/Microsoft.Common.targets
-%_prefix/lib/mono/3.5/Microsoft.Common.tasks
-%_prefix/lib/mono/3.5/Microsoft.VisualBasic.targets
-%_prefix/lib/mono/3.5/Mono.XBuild.Tasks.dll
-%_prefix/lib/mono/3.5/xbuild.exe*
-%_prefix/lib/mono/3.5/xbuild.rsp
-%_prefix/lib/mono/4.0/Microsoft.Build.dll
-%_prefix/lib/mono/4.0/Microsoft.Build.Engine.dll
-%_prefix/lib/mono/4.0/Microsoft.Build.Framework.dll
-%_prefix/lib/mono/4.0/Microsoft.Build.Tasks.v4.0.dll
-%_prefix/lib/mono/4.0/Microsoft.Build.Utilities.v4.0.dll
-%_prefix/lib/mono/4.0/Mono.Debugger.Soft.dll
-%_prefix/lib/mono/4.0/Mono.XBuild.Tasks.dll
-%_prefix/lib/mono/4.0/PEAPI.dll
-%_prefix/lib/mono/4.5/MSBuild
-%_prefix/lib/mono/4.5/Microsoft.Build.dll
-%_prefix/lib/mono/4.5/Microsoft.Build.Engine.dll
-%_prefix/lib/mono/4.5/Microsoft.Build.Framework.dll
-%_prefix/lib/mono/4.5/Microsoft.Build.Tasks.v4.0.dll
-%_prefix/lib/mono/4.5/Microsoft.Build.Utilities.v4.0.dll
-%_prefix/lib/mono/4.5/Microsoft.Build.xsd
-%_prefix/lib/mono/4.5/Microsoft.CSharp.targets
-%_prefix/lib/mono/4.5/Microsoft.Common.targets
-%_prefix/lib/mono/4.5/Microsoft.Common.tasks
-%_prefix/lib/mono/4.5/Microsoft.VisualBasic.targets
-%_prefix/lib/mono/4.5/Mono.Debugger.Soft.dll
-%_prefix/lib/mono/4.5/Mono.CodeContracts.dll
-%_prefix/lib/mono/4.5/Mono.XBuild.Tasks.dll
-%_prefix/lib/mono/4.5/PEAPI.dll
-%_prefix/lib/mono/4.5/caspol.exe*
-%_prefix/lib/mono/4.5/cccheck.exe*
-%_prefix/lib/mono/4.5/ccrewrite.exe*
-%_prefix/lib/mono/4.5/cert2spc.exe*
-%_prefix/lib/mono/4.5/dtd2rng.exe*
-%_prefix/lib/mono/4.5/dtd2xsd.exe*
-%_prefix/lib/mono/4.5/genxs.exe*
-%_prefix/lib/mono/4.5/httpcfg.exe*
-%_prefix/lib/mono/4.5/ictool.exe*
-%_prefix/lib/mono/4.5/ilasm.exe*
-%_prefix/lib/mono/4.5/installvst.exe*
-%_prefix/lib/mono/4.5/lc.exe*
-%_prefix/lib/mono/4.5/macpack.exe*
-%_prefix/lib/mono/4.5/makecert.exe*
-%_prefix/lib/mono/4.5/mkbundle.exe*
-%_prefix/lib/mono/4.5/mono-api-info.exe*
-%_prefix/lib/mono/4.5/mono-cil-strip.exe*
-%_prefix/lib/mono/4.5/mono-shlib-cop.exe*
-%_prefix/lib/mono/4.5/mono-xmltool.exe*
-%_prefix/lib/mono/4.5/monolinker.*
-%_prefix/lib/mono/4.5/monop.exe*
-%_prefix/lib/mono/4.5/pdb2mdb.exe*
-%_prefix/lib/mono/4.5/permview.exe*
-%_prefix/lib/mono/4.5/resgen.exe*
-%_prefix/lib/mono/4.5/secutil.exe*
-%_prefix/lib/mono/4.5/sgen.exe*
-%_prefix/lib/mono/4.5/signcode.exe*
-%_prefix/lib/mono/4.5/xbuild.exe*
-%_prefix/lib/mono/4.5/xbuild.rsp
-%_prefix/lib/mono/4.5/mdbrebase.exe*
-%_prefix/lib/mono/gac/Microsoft.Build
-%_prefix/lib/mono/gac/Microsoft.Build.Engine
-%_prefix/lib/mono/gac/Microsoft.Build.Framework
-%_prefix/lib/mono/gac/Microsoft.Build.Tasks
-%_prefix/lib/mono/gac/Microsoft.Build.Tasks.v3.5
-%_prefix/lib/mono/gac/Microsoft.Build.Tasks.v4.0
-%_prefix/lib/mono/gac/Microsoft.Build.Tasks.v12.0
-%_prefix/lib/mono/gac/Microsoft.Build.Utilities
-%_prefix/lib/mono/gac/Microsoft.Build.Utilities.v3.5
-%_prefix/lib/mono/gac/Microsoft.Build.Utilities.v4.0
-%_prefix/lib/mono/gac/Microsoft.Build.Utilities.v12.0
-%_prefix/lib/mono/gac/Mono.CodeContracts
-%_prefix/lib/mono/gac/Mono.Debugger.Soft
-%_prefix/lib/mono/gac/Mono.XBuild.Tasks
-%_prefix/lib/mono/gac/PEAPI
-%_prefix/lib/mono/xbuild
-%_prefix/lib/mono/xbuild-frameworks
-
-%package -n monodoc-core
-License: LGPL v2.1 only
-Summary: Monodoc - Documentation tools for C# code
-Group: Development/Tools/Other
-Requires: mono-core == %version-%release
-Obsoletes: monodoc
-Provides: monodoc
-# Added to uncompress and compare documentation used by build-compare
-Requires: unzip
-
-%description -n monodoc-core
-Monodoc-core contains documentation tools for C#.
-
-%files -n monodoc-core
-%defattr(-, root, root)
-%_bindir/mdassembler
-%_bindir/mdoc
-%_bindir/mdoc-assemble
-%_bindir/mdoc-export-html
-%_bindir/mdoc-export-msxdoc
-%_bindir/mdoc-update
-%_bindir/mdoc-validate
-%_bindir/mdvalidater
-%_bindir/mod
-%_bindir/monodocer
-%_bindir/monodocs2html
-%_bindir/monodocs2slashdoc
-%_libdir/pkgconfig/monodoc.pc
-%_mandir/man1/mdassembler.1%ext_man
-%_mandir/man1/mdoc-assemble.1%ext_man
-%_mandir/man1/mdoc-export-html.1%ext_man
-%_mandir/man1/mdoc-export-msxdoc.1%ext_man
-%_mandir/man1/mdoc-update.1%ext_man
-%_mandir/man1/mdoc-validate.1%ext_man
-%_mandir/man1/mdoc.1%ext_man
-%_mandir/man1/mdvalidater.1%ext_man
-%_mandir/man1/monodocer.1%ext_man
-%_mandir/man1/monodocs2html.1%ext_man
-%_mandir/man5/mdoc.5%ext_man
-%_prefix/lib/mono/4.5/mdoc.exe*
-%_prefix/lib/mono/4.5/mod.exe*
-%_prefix/lib/mono/4.0/monodoc.dll*
-%_prefix/lib/mono/gac/monodoc
-%_prefix/lib/mono/monodoc
-%_prefix/lib/monodoc
-
-%package -n mono-complete
-License: LGPL v2.1 only
-Summary: Install everything built from the mono source tree
-Group: Development/Languages/Mono
-Requires: mono-core = %version-%release
-Requires: ibm-data-db2 = %version-%release
-Requires: libmono-2_0-1 = %version-%release
-Requires: libmono-2_0-devel = %version-%release
-%if %llvm == yes
-Requires: libmono-llvm0 = %version-%release
-%endif
-%if %sgen == yes
-Requires: libmonosgen-2_0-1 = %version-%release
-Requires: libmonosgen-2_0-devel = %version-%release
-%endif
-Requires: mono-data = %version-%release
-Requires: mono-data-oracle = %version-%release
-Requires: mono-data-postgresql = %version-%release
-Requires: mono-data-sqlite = %version-%release
-Requires: mono-devel = %version-%release
-Requires: mono-extras = %version-%release
-Requires: mono-locale-extras = %version-%release
-Requires: mono-nunit = %version-%release
-Requires: mono-wcf = %version-%release
-Requires: mono-web = %version-%release
-Requires: mono-winforms = %version-%release
-Requires: mono-winfxcore = %version-%release
-Requires: monodoc-core = %version-%release
-
-%description -n mono-complete
-The Mono Project is an open development initiative that is working to
-develop an open source, Unix version of the .NET development platform.
-Its objective is to enable Unix developers to build and deploy
-cross-platform .NET applications. The project will implement various
-technologies that have been submitted to the ECMA for standardization.
-
-Install everything built from the mono source tree. Note that this does
-not install anything from outside the mono source (XSP, mono-basic, etc.).
-
-%files -n mono-complete
-%defattr(-, root, root)
-%dir %_prefix/lib/mono/compat-2.0
-
-%changelog
+++ /dev/null
-* Write test cases
-
- Write test cases to stress test TypeSpec. This is done by
- creating arrays of various dimensions, sizes, and lower
- bounds.
semaphores.h \
sockets.h \
status.h \
- system.h \
threads.h \
timefuncs.h \
types.h \
socket-private.h \
socket-wrappers.h \
status.h \
- system.c \
- system.h \
threads.h \
thread-private.h \
timefuncs.c \
#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-mutex.h>
#include <mono/utils/mono-signal-handler.h>
+#include <mono/utils/mono-proclib.h>
/* The process' environment strings */
#if defined(__APPLE__) && !defined (__arm__) && !defined (__aarch64__)
/* Not sure if w32 allows NULLs here or not */
return FALSE;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
- /* This is a pseudo handle, so just fail for now
- */
- return FALSE;
-
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ gpointer pid = GINT_TO_POINTER (WAPI_HANDLE_TO_PID(process));
+ gint64 start_ticks, user_ticks, kernel_ticks;
+
+ mono_process_get_times (pid, &start_ticks, &user_ticks, &kernel_ticks);
+
+ _wapi_guint64_to_filetime (start_ticks, create_time);
+ _wapi_guint64_to_filetime (user_ticks, kernel_time);
+ _wapi_guint64_to_filetime (kernel_ticks, user_time);
+
+ return TRUE;
+ }
+
process_handle = lookup_process_handle (process);
if (!process_handle) {
DEBUG ("%s: Can't find process %p", __func__, process);
+++ /dev/null
-/*
- * system.c: System information
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <sys/time.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "mono/io-layer/wapi.h"
-
-void GetSystemInfo(WapiSystemInfo *info)
-{
- info->dwPageSize=getpagesize();
-
- /* Fill in the rest of this junk. Maybe with libgtop */
-#ifdef _SC_NPROCESSORS_ONLN
- info->dwNumberOfProcessors = sysconf (_SC_NPROCESSORS_ONLN);
- if (info->dwNumberOfProcessors <= 0)
- info->dwNumberOfProcessors = 1;
-#else
- info->dwNumberOfProcessors = 1;
-#endif
-}
-
-
+++ /dev/null
-/*
- * system.h: System information
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_SYSTEM_H_
-#define _WAPI_SYSTEM_H_
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef struct _WapiSystemInfo WapiSystemInfo;
-
-struct _WapiSystemInfo
-{
- union _anon_union
- {
- guint32 dwOemId;
- struct _anon_struct
- {
- guint16 wProcessorArchitecture;
- guint16 wReserved;
- } _anon_struct;
- } _anon_union;
-
- guint32 dwPageSize;
- gpointer lpMinimumApplicationAddress;
- gpointer lpMaximumApplicationAddress;
- guint32 /*_PTR?*/ dwActiveProcessorMask;
- guint32 dwNumberOfProcessors;
- guint32 dwProcessorType;
- guint32 dwAllocationGranularity;
- guint16 wProcessorLevel;
- guint16 wProcessorRevision;
-};
-
-extern void GetSystemInfo(WapiSystemInfo *info);
-
-G_END_DECLS
-#endif /* _WAPI_SYSTEM_H_ */
extern void Sleep(guint32 ms);
extern guint32 SleepEx(guint32 ms, gboolean alertable);
-void wapi_interrupt_thread (gpointer handle);
void wapi_clear_interruption (void);
gboolean wapi_thread_set_wait_handle (gpointer handle);
void wapi_thread_clear_wait_handle (gpointer handle);
typedef WapiLargeInteger *PLARGE_INTEGER;
typedef WapiULargeInteger ULARGE_INTEGER;
typedef WapiULargeInteger *PULARGE_INTEGER;
-typedef WapiSystemInfo SYSTEM_INFO;
-typedef WapiSystemInfo *LPSYSTEM_INFO;
typedef WapiFloatingSaveArea FLOATING_SAVE_AREA;
typedef WapiFloatingSaveArea *PFLOATING_SAVE_AREA;
typedef WapiContext CONTEXT;
#include <mono/io-layer/semaphores.h>
#include <mono/io-layer/sockets.h>
#include <mono/io-layer/status.h>
-#include <mono/io-layer/system.h>
#include <mono/io-layer/threads.h>
#include <mono/io-layer/timefuncs.h>
#include <mono/io-layer/versioninfo.h>
* call the wait function again. This essentially means that the target thread will
* busy wait until it is ready to process the interruption.
*/
-void
-wapi_interrupt_thread (gpointer thread_handle)
-{
- gpointer wait_handle;
-
- wait_handle = wapi_prepare_interrupt_thread (thread_handle);
- wapi_finish_interrupt_thread (wait_handle);
-}
-
gpointer
wapi_prepare_interrupt_thread (gpointer thread_handle)
{
sgen-layout-stats.h \
sgen-qsort.c \
sgen-qsort.h \
+ sgen-thread-pool.c \
+ sgen-thread-pool.h \
sgen-tagged-pointer.h
libmonoruntime_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(null_gc_sources) $(boehm_sources)
endif
endif
-EXTRA_DIST = make-bundle.pl sample-bundle $(win32_sources) $(unix_sources) $(null_sources) runtime.h \
+EXTRA_DIST = $(win32_sources) $(unix_sources) $(null_sources) runtime.h \
tpool-poll.c tpool-epoll.c tpool-kqueue.c
+++ /dev/null
-
-* Uniform names
-
- We have a mess of names in the icall.c file, we need to sort that out.
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 125
+#define MONO_CORLIB_VERSION 127
typedef struct
{
typedef struct {
MonoImage *corlib;
- MonoImage *system;
MonoClass *object_class;
MonoClass *byte_class;
MonoClass *void_class;
MonoClass *methodhandle_class;
MonoClass *systemtype_class;
MonoClass *monotype_class;
+ MonoClass *runtimetype_class;
MonoClass *exception_class;
MonoClass *threadabortexception_class;
MonoClass *thread_class;
#define DECIMAL_LO32(dec) ((dec).v.v.Lo32)
#define DECIMAL_MID32(dec) ((dec).v.v.Mid32)
#define DECIMAL_HI32(dec) ((dec).Hi32)
-#define DECIMAL_LO64_GET(dec) ((dec).v.Lo64)
-#define DECIMAL_LO64_SET(dec,value) {(dec).v.Lo64 = value; }
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+# define DECIMAL_LO64_GET(dec) (((uint64_t)((dec).v.v.Mid32) << 32) | (dec).v.v.Lo32)
+# define DECIMAL_LO64_SET(dec,value) {(dec).v.v.Lo32 = (value); (dec).v.v.Mid32 = ((value) >> 32); }
+#else
+# define DECIMAL_LO64_GET(dec) ((dec).v.Lo64)
+# define DECIMAL_LO64_SET(dec,value) {(dec).v.Lo64 = value; }
+#endif
#define DECIMAL_SETZERO(dec) {DECIMAL_LO32(dec) = 0; DECIMAL_MID32(dec) = 0; DECIMAL_HI32(dec) = 0; DECIMAL_SIGNSCALE(dec) = 0;}
#define COPYDEC(dest, src) {DECIMAL_SIGNSCALE(dest) = DECIMAL_SIGNSCALE(src); DECIMAL_HI32(dest) = DECIMAL_HI32(src); \
uint32_t right_sign;
MonoDecimal result;
+ result.Hi32 = 0; // Just to shut up the compiler
+
// First check signs and whether either are zero. If both are
// non-zero and of the same sign, just use subtraction to compare.
//
}
mono_defaults.corlib = mono_assembly_get_image (ass);
- /* might be NULL if System.dll is not yet loaded */
- mono_defaults.system = mono_image_loaded ("System");
-
mono_defaults.object_class = mono_class_from_name (
mono_defaults.corlib, "System", "Object");
g_assert (mono_defaults.object_class != 0);
mono_defaults.corlib, "System", "MonoType");
g_assert (mono_defaults.monotype_class != 0);
+ mono_defaults.runtimetype_class = mono_class_from_name (
+ mono_defaults.corlib, "System", "RuntimeType");
+ g_assert (mono_defaults.runtimetype_class != 0);
+
mono_defaults.exception_class = mono_class_from_name (
mono_defaults.corlib, "System", "Exception");
g_assert (mono_defaults.exception_class != 0);
#include <config.h>
-#ifndef TARGET_WIN32
+#ifndef HOST_WIN32
#include <glib.h>
#include <string.h>
#include <config.h>
-#ifdef TARGET_WIN32
+#ifdef HOST_WIN32
#include <glib.h>
#include <string.h>
ICALL(ARRAY_13, "SetValueImpl", ves_icall_System_Array_SetValueImpl)
ICALL_TYPE(BUFFER, "System.Buffer", BUFFER_1)
-ICALL(BUFFER_1, "BlockCopyInternal", ves_icall_System_Buffer_BlockCopyInternal)
-ICALL(BUFFER_2, "ByteLengthInternal", ves_icall_System_Buffer_ByteLengthInternal)
-ICALL(BUFFER_3, "GetByteInternal", ves_icall_System_Buffer_GetByteInternal)
-ICALL(BUFFER_4, "SetByteInternal", ves_icall_System_Buffer_SetByteInternal)
+ICALL(BUFFER_1, "InternalBlockCopy", ves_icall_System_Buffer_BlockCopyInternal)
+ICALL(BUFFER_2, "_ByteLength", ves_icall_System_Buffer_ByteLengthInternal)
+ICALL(BUFFER_3, "_GetByte", ves_icall_System_Buffer_GetByteInternal)
+ICALL(BUFFER_4, "_SetByte", ves_icall_System_Buffer_SetByteInternal)
ICALL_TYPE (COMPO_W, "System.ComponentModel.Win32Exception", COMPO_W_1)
ICALL (COMPO_W_1, "W32ErrorMessage", ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage)
ICALL (SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal)
ICALL(SOCK_7, "GetSocketOption_arr_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,byte[]&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal)
ICALL(SOCK_8, "GetSocketOption_obj_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal)
+ICALL(SOCK_21, "IOControl_internal(intptr,int,byte[],byte[],int&)", ves_icall_System_Net_Sockets_Socket_IOControl_internal)
ICALL(SOCK_9, "Listen_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_Listen_internal)
ICALL(SOCK_10, "LocalEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal)
ICALL(SOCK_11, "Poll_internal", ves_icall_System_Net_Sockets_Socket_Poll_internal)
+ICALL(SOCK_13, "ReceiveFrom_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&)", ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal)
ICALL(SOCK_11a, "Receive_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&)", ves_icall_System_Net_Sockets_Socket_Receive_array_internal)
ICALL(SOCK_12, "Receive_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&)", ves_icall_System_Net_Sockets_Socket_Receive_internal)
-ICALL(SOCK_13, "RecvFrom_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&)", ves_icall_System_Net_Sockets_Socket_RecvFrom_internal)
ICALL(SOCK_14, "RemoteEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal)
ICALL(SOCK_15, "Select_internal(System.Net.Sockets.Socket[]&,int,int&)", ves_icall_System_Net_Sockets_Socket_Select_internal)
-ICALL(SOCK_15a, "SendFile(intptr,string,byte[],byte[],System.Net.Sockets.TransmitFileOptions)", ves_icall_System_Net_Sockets_Socket_SendFile)
+ICALL(SOCK_15a, "SendFile_internal(intptr,string,byte[],byte[],System.Net.Sockets.TransmitFileOptions)", ves_icall_System_Net_Sockets_Socket_SendFile_internal)
ICALL(SOCK_16, "SendTo_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,int&)", ves_icall_System_Net_Sockets_Socket_SendTo_internal)
ICALL(SOCK_16a, "Send_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&)", ves_icall_System_Net_Sockets_Socket_Send_array_internal)
ICALL(SOCK_17, "Send_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&)", ves_icall_System_Net_Sockets_Socket_Send_internal)
ICALL(SOCK_18, "SetSocketOption_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object,byte[],int,int&)", ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal)
ICALL(SOCK_19, "Shutdown_internal(intptr,System.Net.Sockets.SocketShutdown,int&)", ves_icall_System_Net_Sockets_Socket_Shutdown_internal)
ICALL(SOCK_20, "Socket_internal(System.Net.Sockets.AddressFamily,System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,int&)", ves_icall_System_Net_Sockets_Socket_Socket_internal)
-ICALL(SOCK_21, "WSAIoctl(intptr,int,byte[],byte[],int&)", ves_icall_System_Net_Sockets_Socket_WSAIoctl)
ICALL(SOCK_21a, "cancel_blocking_socket_operation", icall_cancel_blocking_socket_operation)
ICALL(SOCK_22, "socket_pool_queue", icall_append_io_job)
ICALL(RT_2, "GetConstructors_internal", ves_icall_Type_GetConstructors_internal)
ICALL(RT_3, "GetEvents_internal", ves_icall_Type_GetEvents_internal)
ICALL(RT_5, "GetFields_internal", ves_icall_Type_GetFields_internal)
-ICALL(RT_6, "GetGenericArguments", ves_icall_MonoType_GetGenericArguments)
+ICALL(RT_6, "GetGenericArgumentsInternal", ves_icall_MonoType_GetGenericArguments)
ICALL(RT_7, "GetGenericParameterAttributes", ves_icall_Type_GetGenericParameterAttributes)
ICALL(RT_8, "GetGenericParameterConstraints_impl", ves_icall_Type_GetGenericParameterConstraints)
ICALL(RT_9, "GetGenericParameterPosition", ves_icall_Type_GetGenericParameterPosition)
return class->rank;
}
+static MonoArray*
+create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
+{
+ MonoArray *res;
+ res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
+ return res;
+}
+
ICALL_EXPORT MonoArray*
-ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
+ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
{
MonoArray *res;
MonoClass *klass, *pklass;
MonoDomain *domain = mono_object_domain (type);
- MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
int i;
klass = mono_class_from_mono_type (type->type);
if (klass->generic_container) {
MonoGenericContainer *container = klass->generic_container;
- res = mono_array_new_specific (array_vtable, container->type_argc);
+ res = create_type_array (domain, runtimeTypeArray, container->type_argc);
for (i = 0; i < container->type_argc; ++i) {
pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
}
} else if (klass->generic_class) {
MonoGenericInst *inst = klass->generic_class->context.class_inst;
- res = mono_array_new_specific (array_vtable, inst->type_argc);
+ res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
for (i = 0; i < inst->type_argc; ++i)
mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
} else {
- res = mono_array_new_specific (array_vtable, 0);
+ res = NULL;
}
return res;
}
MonoTypedRef res;
MonoReflectionField *f;
MonoClass *klass;
- MonoType *ftype;
- guint8 *p;
+ MonoType *ftype = NULL;
+ guint8 *p = NULL;
int i;
memset (&res, 0, sizeof (res));
free_hash (image->var_cache_slow);
free_hash (image->mvar_cache_slow);
free_hash (image->wrapper_param_names);
- free_hash (image->native_wrapper_aot_cache);
free_hash (image->pinvoke_scopes);
free_hash (image->pinvoke_scope_filenames);
for (i = 0; i < image->gshared_types_len; ++i)
+++ /dev/null
-#!/usr/bin/perl -w
-# Copyright (C) 2003 Ximian, Inc.
-# Paolo Molaro (lupus@ximian.com)
-#
-# Create an header file to be included in the mono libraries to
-# bundle assemblies inside the runtime.
-# The template file contains a list of assemblies, one per line,
-# with the name followed by a ':' and the filename.
-# Lines starting with '#' and empty lines are ignored.
-# See sample-bundle for an example.
-# We need to use an assembly file because gcc can't handle large arrays:-(
-
-if ($#ARGV != 2) {
- die "Usage: make-bundle.pl template headerfile.h asm-file\n";
-}
-
-my $template = $ARGV [0];
-my $header = $ARGV [1];
-my $output = $ARGV [2];
-my %assemblies = ();
-
-my $line = 0;
-open (T, $template) || die "Cannot open bundle template: $!\n";
-while (<T>) {
- ++$line;
- next if (/^\s*#/);
- next if (/^\s*$/);
- if (/^([a-zA-Z0-9-.]+):\s*(.+?)\s*$/) {
- my ($name, $filename) = ($1, $2);
- if (exists $assemblies {$name}) {
- die "Assembly $name defined multiple times.\n";
- } else {
- $assemblies {$name} = $filename;
- }
- } else {
- die "Unknown format at line $line: $_";
- }
-}
-close (T);
-
-open (O, ">$output.tmp") || die "Cannot open $output: $!\n";
-open (H, ">$header.tmp") || die "Cannot open $output: $!\n";
-print H <<"EOF";
-/* File generated by make-bundle: do not edit! */
-
-#ifndef __MONO_BUNDLE_H__
-#define __MONO_BUNDLE_H__
-
-typedef struct {
- const char *name;
- const unsigned char *data;
- const unsigned int size;
-} MonoBundledAssembly;
-
-EOF
-
-my $bundle_entries = "";
-
-foreach my $name (sort keys %assemblies) {
- my $file = $assemblies {$name};
- my ($nread, $buf, $i, $cname, $need_eol, $size);
- $cname = $name;
- $cname =~ s/[-.]/_/g;
- open (F, $file) || die "Cannot open $file: $!\n";
- $size = -s F;
-# print O "/* assembly $name from $file */\n";
-# print O "static const unsigned char assembly_data_$cname [] = {\n";
- print O ".globl assembly_data_$cname\n";
- print O "\t.section .rodata\n";
- print O "\t.align 32\n";
- print O "\t.type assembly_data_$cname, \@object\n";
- print O "\t.size assembly_data_$cname, $size\n";
- print O "assembly_data_$cname:\n";
- print H "extern const unsigned char assembly_data_$cname [];\n";
- print H "static const MonoBundledAssembly assembly_bundle_$cname = {\"$name\", assembly_data_$cname, $size};\n";
- $bundle_entries .= "\t&assembly_bundle_$cname,\n";
- $need_eol = 0;
- print "Adding assembly '$name' from $file...\n";
- while (($n = sysread (F, $buf, 32))) {
- for ($i = 0; $i < $n; ++$i) {
- print O "\t.byte ", ord (substr ($buf, $i, 1)), "\n";
- }
-# print O ",\n" if ($need_eol);
-# $need_eol = 1;
-# print O "\t";
-# for ($i = 0; $i < $n; ++$i) {
-# print O ", " if $i > 0;
-# print O ord (substr ($buf, $i, 1));
-# }
- }
-# print O "\n};\n\n";
- close (F);
-}
-
-print H "\nstatic const MonoBundledAssembly* bundled_assemblies [] = {\n";
-print H $bundle_entries;
-print H "\tNULL\n";
-print H "};\n\n";
-print H "#endif /* __MONO_BUNDLE_H__ */\n";
-close (O);
-close (H);
-rename ("$header.tmp", $header);
-rename ("$output.tmp", $output);
-
unsigned char cval [8];
} mono_rdouble;
-#if NO_UNALIGNED_ACCESS
+#if defined(__s390x__)
+
+#define read16(x) s390x_read16(*(guint16 *)(x))
+#define read32(x) s390x_read32(*(guint32 *)(x))
+#define read64(x) s390x_read64(*(guint64 *)(x))
+
+static __inline__ guint16
+s390x_read16(guint16 x)
+{
+ guint16 ret;
+
+ __asm__ (" lrvr %0,%1\n"
+ " sra %0,16\n"
+ : "=r" (ret) : "r" (x));
+
+ return(ret);
+}
+
+static __inline__ guint32
+s390x_read32(guint32 x)
+{
+ guint32 ret;
+
+ __asm__ (" lrvr %0,%1\n"
+ : "=r" (ret) : "r" (x));
+
+ return(ret);
+}
+
+static __inline__ guint64
+s390x_read64(guint64 x)
+{
+ guint64 ret;
+
+ __asm__ (" lrvgr %0,%1\n"
+ : "=r" (ret) : "r" (x));
+
+ return(ret);
+}
+
+#else
+
+# if NO_UNALIGNED_ACCESS
guint16 mono_read16 (const unsigned char *x);
guint32 mono_read32 (const unsigned char *x);
#define read32(x) (mono_read32 ((const unsigned char *)(x)))
#define read64(x) (mono_read64 ((const unsigned char *)(x)))
-#else
+# else
#define read16(x) GUINT16_FROM_LE (*((const guint16 *) (x)))
#define read32(x) GUINT32_FROM_LE (*((const guint32 *) (x)))
#define read64(x) GUINT64_FROM_LE (*((const guint64 *) (x)))
+# endif
+
#endif
#define readr4(x,dest) \
+++ /dev/null
-/*
- * monosn.c: Mono String Name Utility
- *
- * Author:
- * Paolo Molaro (lupus@ximian.com)
- *
- * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- *
- */
-#include <mono/metadata/class.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/assembly.h>
-#include "mono/utils/mono-digest.h"
-/* trim headers */
-
-#include <string.h>
-#include <ctype.h>
-
-#define RSA1_MAGIC 0x32415351
-#define RSA2_MAGIC 0x32415352
-#define PRIVKEY_MAGIC 0x00000207
-#define PUBKEY_MAGIC 0x00008004
-
-typedef struct {
- guchar type, version;
- guint16 reserved1;
- guint32 algid;
-} MonoKeyHeader;
-
-typedef struct {
- MonoKeyHeader header;
- guint32 bitlen;
- guint32 exponent;
- guchar modulus [MONO_ZERO_LEN_ARRAY];
-} MonoRSAPubHeader;
-
-static void
-print_data (const char *data, int len)
-{
- int i;
- for (i = 0; i < len; ++i) {
- if (i && !(i % 32))
- printf ("\n");
- printf ("%02x", data [i] & 0xff);
- }
- printf ("\n");
-}
-
-static int
-show_token (const char *file, int is_assembly, int show_pubkey) {
- char token [20];
- if (!is_assembly) {
- char *pubkey;
- gsize len;
- if (!g_file_get_contents (file, &pubkey, &len, NULL)) {
- printf ("Cannot load file: %s\n", file);
- return 2;
- }
- mono_digest_get_public_token (token, pubkey, len);
- if (show_pubkey) {
- printf ("Public key is\n");
- print_data (pubkey, len);
- }
- g_free (pubkey);
- } else {
- MonoImage *image;
- const char *pubkey;
- guint32 len;
-
- mono_metadata_init ();
- mono_images_init ();
- mono_assemblies_init ();
- mono_loader_init ();
-
- image = mono_image_open (file, NULL);
- if (!image) {
- printf ("Cannot open image file: %s\n", file);
- return 2;
- }
- pubkey = mono_image_get_public_key (image, &len);
- if (!pubkey) {
- printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image));
- mono_image_close (image);
- return 2;
- }
- if (show_pubkey) {
- printf ("Public key is\n");
- print_data (pubkey, len);
- }
- mono_digest_get_public_token (token, pubkey, len);
- mono_image_close (image);
- }
- printf ("Public key token is ");
- print_data (token, 8);
- return 0;
-}
-
-static int
-extract_data_to_file (int pubk, const char *assembly, const char *outfile) {
- MonoImage *image;
- FILE *file;
- const char *pubkey;
- guint32 len;
-
- image = mono_image_open (assembly, NULL);
- if (!image) {
- printf ("Cannot open image file: %s\n", assembly);
- return 2;
- }
- if (pubk)
- pubkey = mono_image_get_public_key (image, &len);
- else
- pubkey = mono_image_get_strong_name (image, &len);
- if (!pubkey) {
- printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image));
- mono_image_close (image);
- return 2;
- }
- if (!(file = fopen (outfile, "wb"))) {
- printf ("Cannot open output file: %s\n", outfile);
- return 2;
- }
- fwrite (pubkey, len, 1, file);
- fclose (file);
- mono_image_close (image);
- return 0;
-}
-
-const static guint8 asciitable [128] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
- 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
- 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
- 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
- 0xff, 0xff
-};
-
-/* data is changed in place */
-static char*
-pem_decode (guchar *data, int len, int *rlen) {
- guchar *p, *s;
- int b64len, i, rem = 0, full;
- int b0, b1, b2, b3, offset, dlen;
-
- p = strstr (data, "-----BEGIN");
- s = strstr (data, "\n-----END");
- if (!p || !s)
- return NULL;
- while (*p != '\n') p++;
- *s = 0;
- s = data = p;
- while (*p) {
- if (isalnum (*p) || *p == '+' || *p == '=' || *p == '/') {
- *s++ = *p++;
- } else {
- p++;
- }
- }
- *s = 0;
- b64len = s - data;
-
- full = b64len >> 2;
- if (data [b64len - 1] == '=') {
- full--;
- rem++;
- }
- if (data [b64len - 2] == '=')
- rem++;
- offset = 0;
- p = data;
- for (i = 0; i < full; ++i) {
- b0 = asciitable [data [offset++]];
- b1 = asciitable [data [offset++]];
- b2 = asciitable [data [offset++]];
- b3 = asciitable [data [offset++]];
-
- *p++ = (b0 << 2) | (b1 >> 4);
- *p++ = (b1 << 4) | (b2 >> 2);
- *p++ = (b2 << 6) | b3;
- }
- dlen = full * 3;
- switch (rem) {
- case 1:
- b0 = asciitable [data [offset++]];
- b1 = asciitable [data [offset++]];
- b2 = asciitable [data [offset++]];
-
- *p++ = (b0 << 2) | (b1 >> 4);
- *p++ = (b1 << 4) | (b2 >> 2);
- dlen += 2;
- break;
- case 2:
- b0 = asciitable [data [offset++]];
- b1 = asciitable [data [offset++]];
-
- *p++ = (b0 << 2) | (b1 >> 4);
- dlen++;
- break;
- }
- *rlen = dlen;
- return data;
-}
-
-enum {
- DER_INTEGER = 2,
- DER_BITSTRING = 3,
- DER_NULL = 5,
- DER_OBJID = 6,
- DER_SEQUENCE = 16,
- DER_INVALID = -1,
- DER_END = -2
-};
-
-static int
-der_get_next (guchar *data, int dlen, int offset, int *len, guchar **rdata)
-{
- int i, l, type, val;
-
- if (offset + 1 >= dlen)
- return DER_END;
-
- type = data [offset++] & 0x1f;
- if (data [offset] == 0x80) /* not supported */
- return DER_INVALID;
- l = 0;
- if (data [offset] & 0x80) {
- val = data [offset++] & 0x7f;
- for (i = 0; i < val; ++i) {
- l = (l << 8) | data [offset++];
- }
- } else {
- l = data [offset++];
- }
- *len = l;
- *rdata = data + offset;
- return type;
-}
-
-static void
-dump_asn1 (guchar *key, int len) {
- int type, offset, elen;
- guchar *edata;
-
- offset = 0;
- while ((type = der_get_next (key, len, offset, &elen, &edata)) >= 0) {
- switch (type) {
- case DER_SEQUENCE:
- g_print ("seq (%d) at %d\n", elen, offset);
- dump_asn1 (edata, elen);
- offset = elen + edata - key;
- break;
- case DER_BITSTRING:
- g_print ("bits (%d) at %p + %d\n", elen, edata, offset);
- dump_asn1 (edata + 1, elen);
- offset = 1 + elen + edata - key;
- break;
- case DER_INTEGER:
- g_print ("int (%d) at %d\n", elen, offset);
- offset = elen + edata - key;
- break;
- case DER_NULL:
- g_print ("null (%d) at %d\n", elen, offset);
- offset = elen + edata - key;
- break;
- case DER_OBJID:
- g_print ("objid (%d) at %d\n", elen, offset);
- offset = elen + edata - key;
- break;
- default:
- return;
- }
- }
-}
-
-static guint32
-get_der_int (guchar *data, int len)
-{
- guint32 val = 0;
- int i;
- for (i = 0; i < len; ++i)
- val = (val << 8) | data [i];
- return val;
-}
-
-static void
-mem_reverse (guchar *p, int len) {
- int i, t;
-
- for (i = 0; i < len/2; ++i) {
- t = p [i];
- p [i] = p [len - i - 1];
- p [len - i - 1] = t;
- }
-}
-
-static int
-convert_der_key (guchar *key, int len, guchar **ret, int *retlen)
-{
- int type, offset, val, elen;
- guchar *r, *edata;
-
- offset = 0;
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_SEQUENCE)
- return 1;
- key = edata;
- len = elen;
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type == DER_INTEGER) {
- int i;
- guchar *ints [6];
- int lengths [6];
- guchar *p;
- /* a private RSA key */
- val = get_der_int (edata, elen);
- if (val != 0)
- return 2;
- offset = elen + edata - key;
- /* the modulus */
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_INTEGER)
- return 2;
- offset = elen + edata - key;
- if ((elen & 1) && *edata == 0) {
- edata ++;
- elen--;
- }
- r = g_new0 (guchar, elen*4 + elen/2 + 20);
- r [0] = 0x7; r [1] = 0x2; r [5] = 0x24;
- r [8] = 0x52; r [9] = 0x53; r [10] = 0x41; r [11] = 0x32;
- *(guint32*)(r + 12) = elen * 8;
- memcpy (r + 20, edata, elen);
- mem_reverse (r + 20, elen);
- p = r + 20 + elen;
- /* the exponent */
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_INTEGER)
- return 2;
- offset = elen + edata - key;
- val = get_der_int (edata, elen);
- *(guint32*)(r + 16) = val;
- for (i = 0; i < 6; i++) {
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_INTEGER)
- return 2;
- offset = elen + edata - key;
- if ((elen & 1) && *edata == 0) {
- edata++;
- elen--;
- }
- ints [i] = edata;
- lengths [i] = elen;
- g_print ("len: %d\n", elen);
- }
- /* prime1 */
- g_print ("prime1 at %d (%d)\n", p-r, lengths [1]);
- memcpy (p, ints [1], lengths [1]);
- mem_reverse (p, lengths [1]);
- p += lengths [1];
- /* prime2 */
- g_print ("prime2 at %d (%d)\n", p-r, lengths [2]);
- memcpy (p, ints [2], lengths [2]);
- mem_reverse (p, lengths [2]);
- p += lengths [2];
- /* exponent1 */
- g_print ("exp1 at %d (%d)\n", p-r, lengths [3]);
- memcpy (p, ints [3], lengths [3]);
- mem_reverse (p, lengths [3]);
- p += lengths [3];
- /* exponent2 */
- g_print ("exp2 at %d (%d)\n", p-r, lengths [4]);
- memcpy (p, ints [4], lengths [4]);
- mem_reverse (p, lengths [4]);
- p += lengths [4];
- /* coeff */
- g_print ("coeff at %d (%d)\n", p-r, lengths [5]);
- memcpy (p, ints [5], lengths [5]);
- mem_reverse (p, lengths [5]);
- p += lengths [5];
- /* private exponent */
- g_print ("prive at %d (%d)\n", p-r, lengths [0]);
- memcpy (p, ints [0], lengths [0]);
- mem_reverse (p, lengths [0]);
- p += lengths [0];
- *ret = r;
- *retlen = p-r;
- return 0;
- }
- return 1;
-}
-
-static int
-convert_format (const char *from, const char *outfile) {
- guchar *key, *bindata, *keyout;
- gsize len;
- int binlen, ret, lenout;
- FILE *file;
-
- if (!g_file_get_contents (from, (gchar**) &key, &len, NULL)) {
- printf ("Cannot load file: %s\n", from);
- return 2;
- }
-
- if (*key == 0 || *key == 0x24) {
- g_free (key);
- printf ("Cannot convert to pem format yet\n");
- return 2;
- }
- bindata = pem_decode (key, len, &binlen);
- if (!(file = fopen (outfile, "wb"))) {
- g_free (key);
- printf ("Cannot open output file: %s\n", outfile);
- return 2;
- }
- dump_asn1 (bindata, binlen);
- ret = convert_der_key (bindata, binlen, &keyout, &lenout);
- if (!ret) {
- fwrite (keyout, lenout, 1, file);
- g_free (keyout);
- } else {
- printf ("Cannot convert key\n");
- }
- fclose (file);
- g_free (key);
- return ret;
-}
-
-static int
-get_digest (const char *from, const char *outfile)
-{
- guchar *ass;
- guchar digest [20];
- gsize len;
- guint32 snpos, snsize;
- FILE *file;
- MonoImage *image;
- MonoSHA1Context sha1;
-
- image = mono_image_open (from, NULL);
- if (!image) {
- printf ("Cannot open image file: %s\n", from);
- return 2;
- }
- snpos = mono_image_strong_name_position (image, &snsize);
- if (!snpos) {
- /*printf ("%s does not represent a strongly named assembly\n", from);
- mono_image_close (image);
- return 2;*/
- snsize = 0;
- }
-
- if (!g_file_get_contents (from, (gchar**) &ass, &len, NULL)) {
- printf ("Cannot load file: %s\n", from);
- mono_image_close (image);
- return 2;
- }
- /*
- * FIXME: we may need to set the STRONGNAMESIGNED flag in the cli header
- * before taking the sha1 digest of the image.
- */
- mono_sha1_init (&sha1);
- mono_sha1_update (&sha1, ass, snpos);
- mono_sha1_update (&sha1, ass + snpos + snsize, len - snsize - snpos);
- mono_sha1_final (&sha1, digest);
-
- mono_image_close (image);
- g_free (ass);
- if (!(file = fopen (outfile, "wb"))) {
- printf ("Cannot open output file: %s\n", outfile);
- return 2;
- }
- fwrite (digest, 20, 1, file);
- fclose (file);
- return 0;
-}
-
-static void
-help (int err) {
- printf ("monosn: Mono Strong Name Utility\nUsage: monosn option [arguments]\n");
- printf ("Available options:\n");
- printf ("\t-C keyin keyout Convert key file format from PEM to cryptoAPI (or the reverse).\n");
- printf ("\t-e assembly file Extract the public key from assembly to file.\n");
- printf ("\t-E assembly file Extract the strong name from assembly to file.\n");
- printf ("\t-r assembly file Extract the sha1 digest from assembly to file.\n");
- printf ("\t-t[p] file Display the public key token from file.\n");
- printf ("\t-T[p] assembly Display the public key token from assembly.\n");
- exit (err);
-}
-
-int
-main (int argc, char *argv[]) {
- int opt;
-
- if (argc < 2 || argv [1] [0] != '-')
- help (1);
-
- opt = argv [1] [1];
- switch (opt) {
- case 'C':
- if (argc != 4)
- help (1);
- return convert_format (argv [2], argv [3]);
- case 'e':
- if (argc != 4)
- help (1);
- return extract_data_to_file (1, argv [2], argv [3]);
- case 'E':
- if (argc != 4)
- help (1);
- return extract_data_to_file (0, argv [2], argv [3]);
- case 'h':
- case '?':
- help (0);
- return 0;
- case 'r':
- if (argc != 4)
- help (1);
- return get_digest (argv [2], argv [3]);
- case 't':
- if (argc != 3)
- help (1);
- return show_token (argv [2], 0, argv [1] [2] == 'p');
- case 'T':
- if (argc != 3)
- help (1);
- return show_token (argv [2], 1, argv [1] [2] == 'p');
- default:
- help (1);
- }
- return 0;
-}
-
MonoString *param_name;
} MonoArgumentException;
-typedef struct {
- MonoSystemException base;
- MonoString *msg;
- MonoString *type_name;
-} MonoTypeLoadException;
-
typedef struct {
MonoObject object;
MonoObject *async_state;
DECL_OFFSET(MonoContext, r8)
DECL_OFFSET(MonoContext, r9)
DECL_OFFSET(MonoContext, r10)
+DECL_OFFSET(MonoContext, r11)
DECL_OFFSET(MonoContext, r12)
DECL_OFFSET(MonoContext, r13)
DECL_OFFSET(MonoContext, r14)
DECL_OFFSET(MonoLMF, rbp)
DECL_OFFSET(MonoLMF, rip)
+DECL_OFFSET(SeqPointInfo, ss_tramp_addr)
DECL_OFFSET(SeqPointInfo, bp_addrs)
+
DECL_OFFSET(DynCallArgs, res)
-DECL_OFFSET(SeqPointInfo, ss_trigger_page)
DECL_OFFSET(MonoLMFTramp, regs)
DECL_OFFSET(MonoLMFTramp, lmf_addr)
+++ /dev/null
-# sample bundle template for use with the configure option --with-bundle=...
-
-console: ../tests/console.exe
-mscorlib: /usr/local/lib/corlib.dll
-
printf ("VTable is invalid (points inside nursery).\n");
goto bridge;
}
- printf ("Class: %s\n", vtable->klass->name);
+ printf ("Class: %s.%s\n", vtable->klass->name_space, vtable->klass->name);
desc = ((GCVTable*)vtable)->desc;
printf ("Descriptor: %lx\n", (long)desc);
if (need_setup)
setup_valid_nursery_objects ();
- for (i = 0; i < valid_nursery_object_count; ++i) {
- if (valid_nursery_objects [i] >= ptr)
+ for (i = 0; i < valid_nursery_object_count - 1; ++i) {
+ if (valid_nursery_objects [i + 1] > ptr)
break;
}
if (i >= valid_nursery_object_count || valid_nursery_objects [i] + safe_object_get_size ((MonoObject *)valid_nursery_objects [i]) < ptr) {
- SGEN_LOG (0, "nursery-ptr (unalloc'd-memory)\n");
+ SGEN_LOG (0, "nursery-ptr (unalloc'd-memory)");
return NULL;
} else {
char *obj = valid_nursery_objects [i];
if (obj == ptr)
- SGEN_LOG (0, "nursery-ptr\n");
+ SGEN_LOG (0, "nursery-ptr %p", obj);
else
- SGEN_LOG (0, "nursery-ptr (interior-ptr offset %td)\n", ptr - obj);
+ SGEN_LOG (0, "nursery-ptr %p (interior-ptr offset %td)", obj, ptr - obj);
return obj;
}
}
static guint64 time_minor_pinning = 0;
static guint64 time_minor_scan_remsets = 0;
static guint64 time_minor_scan_pinned = 0;
-static guint64 time_minor_scan_registered_roots = 0;
-static guint64 time_minor_scan_thread_data = 0;
+static guint64 time_minor_scan_roots = 0;
static guint64 time_minor_finish_gray_stack = 0;
static guint64 time_minor_fragment_creation = 0;
static guint64 time_major_pre_collection_fragment_clear = 0;
static guint64 time_major_pinning = 0;
static guint64 time_major_scan_pinned = 0;
-static guint64 time_major_scan_registered_roots = 0;
-static guint64 time_major_scan_thread_data = 0;
-static guint64 time_major_scan_alloc_pinned = 0;
-static guint64 time_major_scan_finalized = 0;
-static guint64 time_major_scan_big_objects = 0;
+static guint64 time_major_scan_roots = 0;
+static guint64 time_major_scan_mod_union = 0;
static guint64 time_major_finish_gray_stack = 0;
static guint64 time_major_free_bigobjs = 0;
static guint64 time_major_los_sweep = 0;
if (wake) {
g_assert (concurrent_collection_in_progress);
- if (sgen_workers_have_started ()) {
- sgen_workers_ensure_awake ();
- } else {
- if (concurrent_collection_in_progress)
- g_assert (current_collection_generation == -1);
- }
+ sgen_workers_ensure_awake ();
}
}
sgen_perform_collection (0, GENERATION_OLD, "clear domain", TRUE);
g_assert (!concurrent_collection_in_progress);
+ major_collector.finish_sweeping ();
+
sgen_process_fin_stage_entries ();
sgen_process_dislink_stage_entries ();
mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_pinning);
mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_remsets);
mono_counters_register ("Minor scan pinned", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_pinned);
- mono_counters_register ("Minor scan registered roots", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_registered_roots);
- mono_counters_register ("Minor scan thread data", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_thread_data);
- mono_counters_register ("Minor finish gray stack", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_finish_gray_stack);
+ mono_counters_register ("Minor scan roots", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_roots);
mono_counters_register ("Minor fragment creation", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_fragment_creation);
mono_counters_register ("Major fragment clear", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_pre_collection_fragment_clear);
mono_counters_register ("Major pinning", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_pinning);
mono_counters_register ("Major scan pinned", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_pinned);
- mono_counters_register ("Major scan registered roots", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_registered_roots);
- mono_counters_register ("Major scan thread data", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_thread_data);
- mono_counters_register ("Major scan alloc_pinned", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_alloc_pinned);
- mono_counters_register ("Major scan finalized", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_finalized);
- mono_counters_register ("Major scan big objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_big_objects);
+ mono_counters_register ("Major scan roots", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_roots);
+ mono_counters_register ("Major scan mod union", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_scan_mod_union);
mono_counters_register ("Major finish gray stack", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_finish_gray_stack);
mono_counters_register ("Major free big objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_free_bigobjs);
mono_counters_register ("Major LOS sweep", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_major_los_sweep);
}
static void
-job_remembered_set_scan (WorkerData *worker_data, void *dummy)
+job_remembered_set_scan (void *worker_data_untyped, SgenThreadPoolJob *job)
{
+ WorkerData *worker_data = worker_data_untyped;
remset.scan_remsets (sgen_workers_get_job_gray_queue (worker_data));
}
-typedef struct
-{
+typedef struct {
+ SgenThreadPoolJob job;
CopyOrMarkObjectFunc copy_or_mark_func;
ScanObjectFunc scan_func;
char *heap_start;
char *heap_end;
int root_type;
-} ScanFromRegisteredRootsJobData;
+} ScanFromRegisteredRootsJob;
static void
-job_scan_from_registered_roots (WorkerData *worker_data, void *job_data_untyped)
+job_scan_from_registered_roots (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- ScanFromRegisteredRootsJobData *job_data = job_data_untyped;
+ WorkerData *worker_data = worker_data_untyped;
+ ScanFromRegisteredRootsJob *job_data = (ScanFromRegisteredRootsJob*)job;
ScanCopyContext ctx = { job_data->scan_func, job_data->copy_or_mark_func,
sgen_workers_get_job_gray_queue (worker_data) };
scan_from_registered_roots (job_data->heap_start, job_data->heap_end, job_data->root_type, ctx);
- sgen_free_internal_dynamic (job_data, sizeof (ScanFromRegisteredRootsJobData), INTERNAL_MEM_WORKER_JOB_DATA);
}
-typedef struct
-{
+typedef struct {
+ SgenThreadPoolJob job;
char *heap_start;
char *heap_end;
-} ScanThreadDataJobData;
+} ScanThreadDataJob;
static void
-job_scan_thread_data (WorkerData *worker_data, void *job_data_untyped)
+job_scan_thread_data (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- ScanThreadDataJobData *job_data = job_data_untyped;
+ WorkerData *worker_data = worker_data_untyped;
+ ScanThreadDataJob *job_data = (ScanThreadDataJob*)job;
scan_thread_data (job_data->heap_start, job_data->heap_end, TRUE,
sgen_workers_get_job_gray_queue (worker_data));
- sgen_free_internal_dynamic (job_data, sizeof (ScanThreadDataJobData), INTERNAL_MEM_WORKER_JOB_DATA);
}
+typedef struct {
+ SgenThreadPoolJob job;
+ FinalizeReadyEntry *list;
+} ScanFinalizerEntriesJob;
+
static void
-job_scan_finalizer_entries (WorkerData *worker_data, void *job_data_untyped)
+job_scan_finalizer_entries (void *worker_data_untyped, SgenThreadPoolJob *job)
{
- FinalizeReadyEntry *list = job_data_untyped;
+ WorkerData *worker_data = worker_data_untyped;
+ ScanFinalizerEntriesJob *job_data = (ScanFinalizerEntriesJob*)job;
ScanCopyContext ctx = { NULL, current_object_ops.copy_or_mark_object, sgen_workers_get_job_gray_queue (worker_data) };
- scan_finalizer_entries (list, ctx);
+ scan_finalizer_entries (job_data->list, ctx);
}
static void
-job_scan_major_mod_union_cardtable (WorkerData *worker_data, void *job_data_untyped)
+job_scan_major_mod_union_cardtable (void *worker_data_untyped, SgenThreadPoolJob *job)
{
+ WorkerData *worker_data = worker_data_untyped;
g_assert (concurrent_collection_in_progress);
major_collector.scan_card_table (TRUE, sgen_workers_get_job_gray_queue (worker_data));
}
static void
-job_scan_los_mod_union_cardtable (WorkerData *worker_data, void *job_data_untyped)
+job_scan_los_mod_union_cardtable (void *worker_data_untyped, SgenThreadPoolJob *job)
{
+ WorkerData *worker_data = worker_data_untyped;
g_assert (concurrent_collection_in_progress);
sgen_los_scan_card_table (TRUE, sgen_workers_get_job_gray_queue (worker_data));
}
sgen_gray_object_queue_init (&gray_queue, NULL);
}
+static void
+enqueue_scan_from_roots_jobs (char *heap_start, char *heap_end)
+{
+ ScanFromRegisteredRootsJob *scrrj;
+ ScanThreadDataJob *stdj;
+ ScanFinalizerEntriesJob *sfej;
+
+ /* registered roots, this includes static fields */
+
+ scrrj = (ScanFromRegisteredRootsJob*)sgen_thread_pool_job_alloc ("scan from registered roots normal", job_scan_from_registered_roots, sizeof (ScanFromRegisteredRootsJob));
+ scrrj->copy_or_mark_func = current_object_ops.copy_or_mark_object;
+ scrrj->scan_func = current_object_ops.scan_object;
+ scrrj->heap_start = heap_start;
+ scrrj->heap_end = heap_end;
+ scrrj->root_type = ROOT_TYPE_NORMAL;
+ sgen_workers_enqueue_job (&scrrj->job);
+
+ scrrj = (ScanFromRegisteredRootsJob*)sgen_thread_pool_job_alloc ("scan from registered roots wbarrier", job_scan_from_registered_roots, sizeof (ScanFromRegisteredRootsJob));
+ scrrj->copy_or_mark_func = current_object_ops.copy_or_mark_object;
+ scrrj->scan_func = current_object_ops.scan_object;
+ scrrj->heap_start = heap_start;
+ scrrj->heap_end = heap_end;
+ scrrj->root_type = ROOT_TYPE_WBARRIER;
+ sgen_workers_enqueue_job (&scrrj->job);
+
+ /* Threads */
+
+ stdj = (ScanThreadDataJob*)sgen_thread_pool_job_alloc ("scan thread data", job_scan_thread_data, sizeof (ScanThreadDataJob));
+ stdj->heap_start = heap_start;
+ stdj->heap_end = heap_end;
+ sgen_workers_enqueue_job (&stdj->job);
+
+ /* Scan the list of objects ready for finalization. */
+
+ sfej = (ScanFinalizerEntriesJob*)sgen_thread_pool_job_alloc ("scan finalizer entries", job_scan_finalizer_entries, sizeof (ScanFinalizerEntriesJob));
+ sfej->list = fin_ready_list;
+ sgen_workers_enqueue_job (&sfej->job);
+
+ sfej = (ScanFinalizerEntriesJob*)sgen_thread_pool_job_alloc ("scan critical finalizer entries", job_scan_finalizer_entries, sizeof (ScanFinalizerEntriesJob));
+ sfej->list = critical_fin_list;
+ sgen_workers_enqueue_job (&sfej->job);
+}
+
/*
* Perform a nursery collection.
*
gboolean needs_major;
size_t max_garbage_amount;
char *nursery_next;
- ScanFromRegisteredRootsJobData *scrrjd_normal, *scrrjd_wbarrier;
- ScanThreadDataJobData *stdjd;
mword fragment_total;
ScanCopyContext ctx;
TV_DECLARE (atv);
current_collection_generation = GENERATION_NURSERY;
current_object_ops = sgen_minor_collector.serial_ops;
+ SGEN_ASSERT (0, !sgen_collection_is_concurrent (), "Why is the nursery collection concurrent?");
+
reset_pinned_from_failed_allocation ();
check_scan_starts ();
* as part of which we scan the card table. Then, later, we scan the mod union
* cardtable. We should only have to do one.
*/
- sgen_workers_enqueue_job ("scan remset", job_remembered_set_scan, NULL);
+ sgen_workers_enqueue_job (sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (SgenThreadPoolJob)));
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (btv);
MONO_GC_CHECKPOINT_5 (GENERATION_NURSERY);
- /* registered roots, this includes static fields */
- scrrjd_normal = sgen_alloc_internal_dynamic (sizeof (ScanFromRegisteredRootsJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE);
- scrrjd_normal->copy_or_mark_func = current_object_ops.copy_or_mark_object;
- scrrjd_normal->scan_func = current_object_ops.scan_object;
- scrrjd_normal->heap_start = sgen_get_nursery_start ();
- scrrjd_normal->heap_end = nursery_next;
- scrrjd_normal->root_type = ROOT_TYPE_NORMAL;
- sgen_workers_enqueue_job ("scan from registered roots normal", job_scan_from_registered_roots, scrrjd_normal);
-
- scrrjd_wbarrier = sgen_alloc_internal_dynamic (sizeof (ScanFromRegisteredRootsJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE);
- scrrjd_wbarrier->copy_or_mark_func = current_object_ops.copy_or_mark_object;
- scrrjd_wbarrier->scan_func = current_object_ops.scan_object;
- scrrjd_wbarrier->heap_start = sgen_get_nursery_start ();
- scrrjd_wbarrier->heap_end = nursery_next;
- scrrjd_wbarrier->root_type = ROOT_TYPE_WBARRIER;
- sgen_workers_enqueue_job ("scan from registered roots wbarrier", job_scan_from_registered_roots, scrrjd_wbarrier);
+ enqueue_scan_from_roots_jobs (sgen_get_nursery_start (), nursery_next);
TV_GETTIME (btv);
- time_minor_scan_registered_roots += TV_ELAPSED (atv, btv);
+ time_minor_scan_roots += TV_ELAPSED (atv, btv);
MONO_GC_CHECKPOINT_6 (GENERATION_NURSERY);
-
- /* thread data */
- stdjd = sgen_alloc_internal_dynamic (sizeof (ScanThreadDataJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE);
- stdjd->heap_start = sgen_get_nursery_start ();
- stdjd->heap_end = nursery_next;
- sgen_workers_enqueue_job ("scan thread data", job_scan_thread_data, stdjd);
-
- TV_GETTIME (atv);
- time_minor_scan_thread_data += TV_ELAPSED (btv, atv);
- btv = atv;
-
MONO_GC_CHECKPOINT_7 (GENERATION_NURSERY);
-
- g_assert (!sgen_collection_is_concurrent ());
-
- /* Scan the list of objects ready for finalization. If */
- sgen_workers_enqueue_job ("scan finalizer entries", job_scan_finalizer_entries, fin_ready_list);
- sgen_workers_enqueue_job ("scan criticial finalizer entries", job_scan_finalizer_entries, critical_fin_list);
-
MONO_GC_CHECKPOINT_8 (GENERATION_NURSERY);
finish_gray_stack (GENERATION_NURSERY, &gray_queue);
MONO_GC_CHECKPOINT_9 (GENERATION_NURSERY);
- /*
- * The (single-threaded) finalization code might have done
- * some copying/marking so we can only reset the GC thread's
- * worker data here instead of earlier when we joined the
- * workers.
- */
- sgen_workers_reset_data ();
-
if (objects_pinned) {
sgen_optimize_pin_queue ();
sgen_pinning_setup_section (nursery_section);
char *heap_end = (char*)-1;
gboolean profile_roots = mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS;
GCRootReport root_report = { 0 };
- ScanFromRegisteredRootsJobData *scrrjd_normal, *scrrjd_wbarrier;
- ScanThreadDataJobData *stdjd;
ScanCopyContext ctx;
if (concurrent_collection_in_progress) {
TV_GETTIME (atv);
time_major_scan_pinned += TV_ELAPSED (btv, atv);
- /* registered roots, this includes static fields */
- scrrjd_normal = sgen_alloc_internal_dynamic (sizeof (ScanFromRegisteredRootsJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE);
- scrrjd_normal->copy_or_mark_func = current_object_ops.copy_or_mark_object;
- scrrjd_normal->scan_func = current_object_ops.scan_object;
- scrrjd_normal->heap_start = heap_start;
- scrrjd_normal->heap_end = heap_end;
- scrrjd_normal->root_type = ROOT_TYPE_NORMAL;
- sgen_workers_enqueue_job ("scan from registered roots normal", job_scan_from_registered_roots, scrrjd_normal);
-
- scrrjd_wbarrier = sgen_alloc_internal_dynamic (sizeof (ScanFromRegisteredRootsJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE);
- scrrjd_wbarrier->copy_or_mark_func = current_object_ops.copy_or_mark_object;
- scrrjd_wbarrier->scan_func = current_object_ops.scan_object;
- scrrjd_wbarrier->heap_start = heap_start;
- scrrjd_wbarrier->heap_end = heap_end;
- scrrjd_wbarrier->root_type = ROOT_TYPE_WBARRIER;
- sgen_workers_enqueue_job ("scan from registered roots wbarrier", job_scan_from_registered_roots, scrrjd_wbarrier);
-
- TV_GETTIME (btv);
- time_major_scan_registered_roots += TV_ELAPSED (atv, btv);
-
- /* Threads */
- stdjd = sgen_alloc_internal_dynamic (sizeof (ScanThreadDataJobData), INTERNAL_MEM_WORKER_JOB_DATA, TRUE);
- stdjd->heap_start = heap_start;
- stdjd->heap_end = heap_end;
- sgen_workers_enqueue_job ("scan thread data", job_scan_thread_data, stdjd);
-
- TV_GETTIME (atv);
- time_major_scan_thread_data += TV_ELAPSED (btv, atv);
-
- TV_GETTIME (btv);
- time_major_scan_alloc_pinned += TV_ELAPSED (atv, btv);
-
if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
report_finalizer_roots ();
- /* scan the list of objects ready for finalization */
- sgen_workers_enqueue_job ("scan finalizer entries", job_scan_finalizer_entries, fin_ready_list);
- sgen_workers_enqueue_job ("scan critical finalizer entries", job_scan_finalizer_entries, critical_fin_list);
+ enqueue_scan_from_roots_jobs (heap_start, heap_end);
+
+ TV_GETTIME (btv);
+ time_major_scan_roots += TV_ELAPSED (atv, btv);
if (scan_mod_union) {
g_assert (finish_up_concurrent_mark);
/* Mod union card table */
- sgen_workers_enqueue_job ("scan mod union cardtable", job_scan_major_mod_union_cardtable, NULL);
- sgen_workers_enqueue_job ("scan LOS mod union cardtable", job_scan_los_mod_union_cardtable, NULL);
- }
-
- TV_GETTIME (atv);
- time_major_scan_finalized += TV_ELAPSED (btv, atv);
- SGEN_LOG (2, "Root scan: %d usecs", TV_ELAPSED (btv, atv));
+ sgen_workers_enqueue_job (sgen_thread_pool_job_alloc ("scan mod union cardtable", job_scan_major_mod_union_cardtable, sizeof (SgenThreadPoolJob)));
+ sgen_workers_enqueue_job (sgen_thread_pool_job_alloc ("scan LOS mod union cardtable", job_scan_los_mod_union_cardtable, sizeof (SgenThreadPoolJob)));
- TV_GETTIME (btv);
- time_major_scan_big_objects += TV_ELAPSED (atv, btv);
+ TV_GETTIME (atv);
+ time_major_scan_mod_union += TV_ELAPSED (btv, atv);
+ }
}
static void
}
static void
-wait_for_workers_to_finish (void)
-{
- while (!sgen_workers_all_done ())
- g_usleep (200);
-}
-
-static void
-major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean scan_whole_nursery)
+major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean forced, gboolean scan_whole_nursery)
{
ScannedObjectCounts counts;
LOSObject *bigobj, *prevbo;
SGEN_ASSERT (0, sgen_workers_all_done (), "Can't have workers working after joining");
- /*
- * The (single-threaded) finalization code might have done
- * some copying/marking so we can only reset the GC thread's
- * worker data here instead of earlier when we joined the
- * workers.
- */
- sgen_workers_reset_data ();
-
if (objects_pinned) {
g_assert (!concurrent_collection_in_progress);
g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
- sgen_memgov_major_collection_end ();
+ sgen_memgov_major_collection_end (forced);
current_collection_generation = -1;
memset (&counts, 0, sizeof (ScannedObjectCounts));
}
static gboolean
-major_do_collection (const char *reason)
+major_do_collection (const char *reason, gboolean forced)
{
TV_DECLARE (time_start);
TV_DECLARE (time_end);
TV_GETTIME (time_start);
major_start_collection (FALSE, &old_next_pin_slot);
- major_finish_collection (reason, old_next_pin_slot, FALSE);
+ major_finish_collection (reason, old_next_pin_slot, forced, FALSE);
TV_GETTIME (time_end);
gc_stats.major_gc_time += TV_ELAPSED (time_start, time_end);
}
static void
-major_finish_concurrent_collection (void)
+major_finish_concurrent_collection (gboolean forced)
{
TV_DECLARE (total_start);
TV_DECLARE (total_end);
* marking before the nursery collection is allowed to run, otherwise we might miss
* some remsets.
*/
- wait_for_workers_to_finish ();
+ sgen_workers_wait ();
SGEN_TV_GETTIME (time_major_conc_collection_end);
gc_stats.major_gc_time_concurrent += SGEN_TV_ELAPSED (time_major_conc_collection_start, time_major_conc_collection_end);
sgen_check_mod_union_consistency ();
current_collection_generation = GENERATION_OLD;
- major_finish_collection ("finishing", -1, late_pinned);
+ major_finish_collection ("finishing", -1, forced, late_pinned);
if (whole_heap_check_before_collection)
sgen_check_whole_heap (FALSE);
int generation_to_collect = -1;
const char *reason = NULL;
-
if (size > SGEN_MAX_SMALL_OBJ_SIZE) {
if (sgen_need_major_collection (size)) {
reason = "LOS overflow";
gboolean finish = major_should_finish_concurrent_collection () || (wait_to_finish && generation_to_collect == GENERATION_OLD);
if (finish) {
- major_finish_concurrent_collection ();
+ major_finish_concurrent_collection (wait_to_finish);
oldest_generation_collected = GENERATION_OLD;
} else {
sgen_workers_signal_start_nursery_collection_and_wait ();
goto done;
}
- if (major_do_collection (reason)) {
+ if (major_do_collection (reason, wait_to_finish)) {
overflow_generation_to_collect = GENERATION_NURSERY;
overflow_reason = "Excessive pinning";
}
if (overflow_generation_to_collect == GENERATION_NURSERY)
collect_nursery (NULL, FALSE);
else
- major_do_collection (overflow_reason);
+ major_do_collection (overflow_reason, wait_to_finish);
TV_GETTIME (gc_end);
infos [1].total_time = SGEN_TV_ELAPSED (infos [1].total_time, gc_end);
g_strfreev (opts);
}
- if (major_collector.is_concurrent)
- sgen_workers_init (1);
-
if (major_collector_opt)
g_free (major_collector_opt);
if (major_collector.post_param_init)
major_collector.post_param_init (&major_collector);
+ if (major_collector.needs_thread_pool)
+ sgen_workers_init (1);
+
sgen_memgov_init (max_heap, soft_limit, debug_print_allowance, allowance_ratio, save_target);
memset (&remset, 0, sizeof (remset));
#define UNLOCK_INTERRUPTION mono_mutex_unlock (&sgen_interruption_mutex)
/* FIXME: Use InterlockedAdd & InterlockedAdd64 to reduce the CAS cost. */
+#define SGEN_CAS InterlockedCompareExchange
#define SGEN_CAS_PTR InterlockedCompareExchangePointer
#define SGEN_ATOMIC_ADD(x,i) do { \
int __old_x; \
void sgen_wait_for_suspend_ack (int count);
void sgen_os_init (void);
-gboolean sgen_is_worker_thread (MonoNativeThreadId thread);
-
void sgen_update_heap_boundaries (mword low, mword high);
void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags);
INTERNAL_MEM_MS_BLOCK_INFO_SORT,
INTERNAL_MEM_EPHEMERON_LINK,
INTERNAL_MEM_WORKER_DATA,
- INTERNAL_MEM_WORKER_JOB_DATA,
+ INTERNAL_MEM_THREAD_POOL_JOB,
INTERNAL_MEM_BRIDGE_DATA,
INTERNAL_MEM_OLD_BRIDGE_HASH_TABLE,
INTERNAL_MEM_OLD_BRIDGE_HASH_TABLE_ENTRY,
INTERNAL_MEM_TARJAN_BRIDGE_HASH_TABLE_ENTRY,
INTERNAL_MEM_TARJAN_OBJ_BUCKET,
INTERNAL_MEM_BRIDGE_DEBUG,
- INTERNAL_MEM_JOB_QUEUE_ENTRY,
INTERNAL_MEM_TOGGLEREF_DATA,
INTERNAL_MEM_CARDTABLE_MOD_UNION,
INTERNAL_MEM_BINARY_PROTOCOL,
/* Updating references */
#ifdef SGEN_CHECK_UPDATE_REFERENCE
+gboolean sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread) MONO_INTERNAL;
static inline void
sgen_update_reference (void **p, void *o, gboolean allow_null)
{
if (!allow_null)
SGEN_ASSERT (0, o, "Cannot update a reference with a NULL pointer");
- SGEN_ASSERT (0, !sgen_is_worker_thread (mono_native_thread_id_get ()), "Can't update a reference in the worker thread");
+ SGEN_ASSERT (0, !sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Can't update a reference in the worker thread");
*p = o;
}
struct _SgenMajorCollector {
size_t section_size;
gboolean is_concurrent;
+ gboolean needs_thread_pool;
gboolean supports_cardtable;
gboolean sweeps_lazily;
void* (*alloc_object) (MonoVTable *vtable, size_t size, gboolean has_references);
void (*free_pinned_object) (char *obj, size_t size);
+
+ /*
+ * This is used for domain unloading, heap walking from the logging profiler, and
+ * debugging. Can assume the world is stopped.
+ */
void (*iterate_objects) (IterateObjectsFlags flags, IterateObjectCallbackFunc callback, void *data);
+
void (*free_non_pinned_object) (char *obj, size_t size);
void (*pin_objects) (SgenGrayQueue *queue);
void (*pin_major_object) (char *obj, SgenGrayQueue *queue);
void (*update_cardtable_mod_union) (void);
void (*init_to_space) (void);
void (*sweep) (void);
- gboolean (*have_finished_sweeping) (void);
- void (*free_swept_blocks) (void);
+ gboolean (*have_swept) (void);
+ void (*finish_sweeping) (void);
+ void (*free_swept_blocks) (size_t allowance);
void (*check_scan_starts) (void);
void (*dump_heap) (FILE *heap_dump_file);
gint64 (*get_used_size) (void);
gboolean (*obj_is_from_pinned_alloc) (char *obj);
void (*report_pinned_memory_usage) (void);
size_t (*get_num_major_sections) (void);
+ size_t (*get_bytes_survived_last_sweep) (void);
gboolean (*handle_gc_param) (const char *opt);
void (*print_gc_param_usage) (void);
- gboolean (*is_worker_thread) (MonoNativeThreadId thread);
void (*post_param_init) (SgenMajorCollector *collector);
- void* (*alloc_worker_data) (void);
- void (*init_worker_thread) (void *data);
- void (*reset_worker_data) (void *data);
gboolean (*is_valid_object) (char *object);
MonoVTable* (*describe_pointer) (char *pointer);
guint8* (*get_cardtable_mod_union_for_object) (char *object);
int sgen_stop_world (int generation);
int sgen_restart_world (int generation, GGTimingInfo *timing);
+gboolean sgen_is_world_stopped (void);
void sgen_init_stw (void);
/* LOS */
case INTERNAL_MEM_MS_BLOCK_INFO_SORT: return "marksweep-block-info-sort";
case INTERNAL_MEM_EPHEMERON_LINK: return "ephemeron-link";
case INTERNAL_MEM_WORKER_DATA: return "worker-data";
- case INTERNAL_MEM_WORKER_JOB_DATA: return "worker-job-data";
+ case INTERNAL_MEM_THREAD_POOL_JOB: return "thread-pool-job";
case INTERNAL_MEM_BRIDGE_DATA: return "bridge-data";
case INTERNAL_MEM_OLD_BRIDGE_HASH_TABLE: return "old-bridge-hash-table";
case INTERNAL_MEM_OLD_BRIDGE_HASH_TABLE_ENTRY: return "old-bridge-hash-table-entry";
case INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE: return "bridge-alive-hash-table";
case INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE_ENTRY: return "bridge-alive-hash-table-entry";
case INTERNAL_MEM_BRIDGE_DEBUG: return "bridge-debug";
- case INTERNAL_MEM_JOB_QUEUE_ENTRY: return "job-queue-entry";
case INTERNAL_MEM_TOGGLEREF_DATA: return "toggleref-data";
case INTERNAL_MEM_CARDTABLE_MOD_UNION: return "cardtable-mod-union";
case INTERNAL_MEM_BINARY_PROTOCOL: return "binary-protocol";
#include "metadata/sgen-pointer-queue.h"
#include "metadata/sgen-pinning.h"
#include "metadata/sgen-workers.h"
+#include "metadata/sgen-thread-pool.h"
#if defined(ARCH_MIN_MS_BLOCK_SIZE) && defined(ARCH_MIN_MS_BLOCK_SIZE_SHIFT)
#define MS_BLOCK_SIZE ARCH_MIN_MS_BLOCK_SIZE
#define MS_NUM_MARK_WORDS ((MS_BLOCK_SIZE / SGEN_ALLOC_ALIGN + sizeof (mword) * 8 - 1) / (sizeof (mword) * 8))
+/*
+ * Blocks progress from one state to the next:
+ *
+ * SWEPT The block is fully swept. It might or might not be in
+ * a free list.
+ *
+ * MARKING The block might or might not contain live objects. If
+ * we're in between an initial collection pause and the
+ * finishing pause, the block might or might not be in a
+ * free list.
+ *
+ * CHECKING The sweep thread is investigating the block to determine
+ * whether or not it contains live objects. The block is
+ * not in a free list.
+ *
+ * NEED_SWEEPING The block contains live objects but has not yet been
+ * swept. It also contains free slots. It is in a block
+ * free list.
+ *
+ * SWEEPING The block is being swept. It might be in a free list.
+ */
+
+enum {
+ BLOCK_STATE_SWEPT,
+ BLOCK_STATE_MARKING,
+ BLOCK_STATE_CHECKING,
+ BLOCK_STATE_NEED_SWEEPING,
+ BLOCK_STATE_SWEEPING
+};
+
typedef struct _MSBlockInfo MSBlockInfo;
struct _MSBlockInfo {
guint16 obj_size;
* recalculating to save the space.
*/
guint16 obj_size_index;
+ /* FIXME: Reduce this - it only needs a byte. */
+ volatile gint32 state;
unsigned int pinned : 1;
unsigned int has_references : 1;
unsigned int has_pinned : 1; /* means cannot evacuate */
unsigned int is_to_space : 1;
- unsigned int swept : 1;
void ** volatile free_list;
MSBlockInfo * volatile next_free;
guint8 *cardtable_mod_union;
static float concurrent_evacuation_threshold = 0.666f;
static gboolean want_evacuation = FALSE;
-static gboolean lazy_sweep = TRUE;
-static gboolean have_swept = TRUE;
+static gboolean lazy_sweep = FALSE;
+
+enum {
+ SWEEP_STATE_SWEPT,
+ SWEEP_STATE_NEED_SWEEPING,
+ SWEEP_STATE_SWEEPING,
+ SWEEP_STATE_SWEEPING_AND_ITERATING,
+ SWEEP_STATE_COMPACTING
+};
+
+static volatile int sweep_state = SWEEP_STATE_SWEPT;
static gboolean concurrent_mark;
+static gboolean concurrent_sweep = TRUE;
#define BLOCK_IS_TAGGED_HAS_REFERENCES(bl) SGEN_POINTER_IS_TAGGED_1 ((bl))
#define BLOCK_TAG_HAS_REFERENCES(bl) SGEN_POINTER_TAG_1 ((bl))
-#define BLOCK_UNTAG_HAS_REFERENCES(bl) SGEN_POINTER_UNTAG_1 ((bl))
-#define BLOCK_TAG(bl) ((bl)->has_references ? BLOCK_TAG_HAS_REFERENCES ((bl)) : (bl))
+#define BLOCK_IS_TAGGED_CHECKING(bl) SGEN_POINTER_IS_TAGGED_2 ((bl))
+#define BLOCK_TAG_CHECKING(bl) SGEN_POINTER_TAG_2 ((bl))
+
+#define BLOCK_UNTAG(bl) SGEN_POINTER_UNTAG_12 ((bl))
+
+#define BLOCK_TAG(bl) ((bl)->has_references ? BLOCK_TAG_HAS_REFERENCES ((bl)) : (bl))
/* all allocated blocks in the system */
static SgenPointerQueue allocated_blocks;
static void *empty_blocks = NULL;
static size_t num_empty_blocks = 0;
-#define FOREACH_BLOCK(bl) { size_t __index; for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { (bl) = BLOCK_UNTAG_HAS_REFERENCES (allocated_blocks.data [__index]);
-#define FOREACH_BLOCK_HAS_REFERENCES(bl,hr) { size_t __index; for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { (bl) = allocated_blocks.data [__index]; (hr) = BLOCK_IS_TAGGED_HAS_REFERENCES ((bl)); (bl) = BLOCK_UNTAG_HAS_REFERENCES ((bl));
-#define END_FOREACH_BLOCK } }
-#define DELETE_BLOCK_IN_FOREACH() (allocated_blocks.data [__index] = NULL)
-
-static size_t num_major_sections = 0;
-/* one free block list for each block object size */
-static MSBlockInfo **free_block_lists [MS_BLOCK_TYPE_MAX];
+#define FOREACH_BLOCK_NO_LOCK_CONDITION(cond,bl) { \
+ size_t __index; \
+ SGEN_ASSERT (0, (cond) && !sweep_in_progress (), "Can't iterate blocks while the world is running or sweep is in progress."); \
+ for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { \
+ (bl) = BLOCK_UNTAG (allocated_blocks.data [__index]);
+#define FOREACH_BLOCK_NO_LOCK(bl) \
+ FOREACH_BLOCK_NO_LOCK_CONDITION(sgen_is_world_stopped (), bl)
+#define FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK(bl,hr) { \
+ size_t __index; \
+ SGEN_ASSERT (0, sgen_is_world_stopped () && !sweep_in_progress (), "Can't iterate blocks while the world is running or sweep is in progress."); \
+ for (__index = 0; __index < allocated_blocks.next_slot; ++__index) { \
+ (bl) = allocated_blocks.data [__index]; \
+ (hr) = BLOCK_IS_TAGGED_HAS_REFERENCES ((bl)); \
+ (bl) = BLOCK_UNTAG ((bl));
+#define END_FOREACH_BLOCK_NO_LOCK } }
+
+static volatile size_t num_major_sections = 0;
+/*
+ * One free block list for each block object size. We add and remove blocks from these
+ * lists lock-free via CAS.
+ *
+ * Blocks accessed/removed from `free_block_lists`:
+ * from the mutator (with GC lock held)
+ * in nursery collections
+ * in non-concurrent major collections
+ * in the finishing pause of concurrent major collections (whole list is cleared)
+ *
+ * Blocks added to `free_block_lists`:
+ * in the sweeping thread
+ * during nursery collections
+ * from domain clearing (with the world stopped and no sweeping happening)
+ *
+ * The only item of those that doesn't require the GC lock is the sweep thread. The sweep
+ * thread only ever adds blocks to the free list, so the ABA problem can't occur.
+ */
+static MSBlockInfo * volatile *free_block_lists [MS_BLOCK_TYPE_MAX];
static guint64 stat_major_blocks_alloced = 0;
static guint64 stat_major_blocks_freed = 0;
}
#endif
-static void
-sweep_block (MSBlockInfo *block, gboolean during_major_collection);
+static gboolean sweep_block (MSBlockInfo *block);
static int
ms_find_block_obj_size_index (size_t size)
sgen_update_heap_boundaries ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), (mword)MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE);
}
+/*
+ * Thread safe
+ */
static void*
ms_get_empty_block (void)
{
} while (SGEN_CAS_PTR (&empty_blocks, block, empty) != empty);
SGEN_ATOMIC_ADD_P (num_empty_blocks, 1);
+
+ binary_protocol_block_free (block, MS_BLOCK_SIZE);
+}
+
+static gboolean
+sweep_in_progress (void)
+{
+ int state = sweep_state;
+ return state == SWEEP_STATE_SWEEPING ||
+ state == SWEEP_STATE_SWEEPING_AND_ITERATING ||
+ state == SWEEP_STATE_COMPACTING;
+}
+
+static inline gboolean
+block_is_swept_or_marking (MSBlockInfo *block)
+{
+ gint32 state = block->state;
+ return state == BLOCK_STATE_SWEPT || state == BLOCK_STATE_MARKING;
}
//#define MARKSWEEP_CONSISTENCY_CHECK
static void
check_block_free_list (MSBlockInfo *block, int size, gboolean pinned)
{
- MSBlockInfo *b;
-
+ SGEN_ASSERT (0, !sweep_in_progress (), "Can't examine allocated blocks during sweep");
for (; block; block = block->next_free) {
+ SGEN_ASSERT (0, block->state != BLOCK_STATE_CHECKING, "Can't have a block we're checking in a free list.");
g_assert (block->obj_size == size);
g_assert ((pinned && block->pinned) || (!pinned && !block->pinned));
/* blocks in the free lists must have at least
one free slot */
- if (block->swept)
- g_assert (block->free_list);
+ g_assert (block->free_list);
/* the block must be in the allocated_blocks array */
g_assert (sgen_pointer_queue_find (&allocated_blocks, BLOCK_TAG (block)) != (size_t)-1);
int i;
/* check all blocks */
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
int count = MS_BLOCK_FREE / block->obj_size;
int num_free = 0;
void **free;
- /* check block header */
- g_assert (((MSBlockHeader*)block->block)->info == block);
-
/* count number of free slots */
for (i = 0; i < count; ++i) {
void **obj = (void**) MS_BLOCK_OBJ (block, i);
g_assert (num_free == 0);
/* check all mark words are zero */
- if (block->swept) {
+ if (!sgen_concurrent_collection_in_progress () && block_is_swept_or_marking (block)) {
for (i = 0; i < MS_NUM_MARK_WORDS; ++i)
g_assert (block->mark_words [i] == 0);
}
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
/* check free blocks */
for (i = 0; i < num_block_obj_sizes; ++i) {
}
#endif
+static void
+add_free_block (MSBlockInfo * volatile *free_blocks, int size_index, MSBlockInfo *block)
+{
+ MSBlockInfo *old;
+ do {
+ block->next_free = old = free_blocks [size_index];
+ } while (SGEN_CAS_PTR ((gpointer)&free_blocks [size_index], block, old) != old);
+}
+
+static void major_finish_sweep_checking (void);
+
static gboolean
ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
{
int size = block_obj_sizes [size_index];
int count = MS_BLOCK_FREE / size;
MSBlockInfo *info;
- MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
+ MSBlockInfo * volatile * free_blocks = FREE_BLOCKS (pinned, has_references);
char *obj_start;
int i;
* want further evacuation.
*/
info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD);
- info->swept = 1;
+ info->state = (info->is_to_space || sgen_concurrent_collection_in_progress ()) ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT;
+ SGEN_ASSERT (6, !sweep_in_progress () || info->state == BLOCK_STATE_SWEPT, "How do we add a new block to be swept while sweeping?");
info->cardtable_mod_union = NULL;
update_heap_boundaries_for_block (info);
+ binary_protocol_block_alloc (info, MS_BLOCK_SIZE);
+
/* build free list */
obj_start = MS_BLOCK_FOR_BLOCK_INFO (info) + MS_BLOCK_SKIP;
info->free_list = (void**)obj_start;
/* the last one */
*(void**)obj_start = NULL;
- info->next_free = free_blocks [size_index];
- free_blocks [size_index] = info;
+ add_free_block (free_blocks, size_index, info);
+
+ /*
+ * This is the only place where the `allocated_blocks` array can potentially grow.
+ * We need to make sure concurrent sweep isn't running when that happens, so in that
+ * specific case we just wait for sweep to finish.
+ */
+ if (sgen_pointer_queue_will_grow (&allocated_blocks))
+ major_finish_sweep_checking ();
sgen_pointer_queue_add (&allocated_blocks, BLOCK_TAG (info));
- ++num_major_sections;
+ SGEN_ATOMIC_ADD_P (num_major_sections, 1);
return TRUE;
}
{
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE)
return block->pinned;
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
return FALSE;
}
+static void
+ensure_can_access_block_free_list (MSBlockInfo *block)
+{
+ retry:
+ for (;;) {
+ switch (block->state) {
+ case BLOCK_STATE_SWEPT:
+ case BLOCK_STATE_MARKING:
+ return;
+ case BLOCK_STATE_CHECKING:
+ SGEN_ASSERT (0, FALSE, "How did we get a block that's being checked from a free list?");
+ break;
+ case BLOCK_STATE_NEED_SWEEPING:
+ if (sweep_block (block))
+ ++stat_major_blocks_lazy_swept;
+ break;
+ case BLOCK_STATE_SWEEPING:
+ /* FIXME: do this more elegantly */
+ g_usleep (100);
+ goto retry;
+ default:
+ SGEN_ASSERT (0, FALSE, "Illegal block state");
+ break;
+ }
+ }
+}
+
static void*
-unlink_slot_from_free_list_uncontested (MSBlockInfo **free_blocks, int size_index)
+unlink_slot_from_free_list_uncontested (MSBlockInfo * volatile *free_blocks, int size_index)
{
- MSBlockInfo *block;
- void *obj;
+ MSBlockInfo *block, *next_free_block;
+ void *obj, *next_free_slot;
+ retry:
block = free_blocks [size_index];
SGEN_ASSERT (9, block, "no free block to unlink from free_blocks %p size_index %d", free_blocks, size_index);
- if (G_UNLIKELY (!block->swept)) {
- stat_major_blocks_lazy_swept ++;
- sweep_block (block, FALSE);
- }
+ ensure_can_access_block_free_list (block);
obj = block->free_list;
- SGEN_ASSERT (9, obj, "block %p in free list had no available object to alloc from", block);
+ SGEN_ASSERT (6, obj, "block %p in free list had no available object to alloc from", block);
- block->free_list = *(void**)obj;
- if (!block->free_list) {
- free_blocks [size_index] = block->next_free;
- block->next_free = NULL;
+ next_free_slot = *(void**)obj;
+ if (next_free_slot) {
+ block->free_list = next_free_slot;
+ return obj;
}
+ next_free_block = block->next_free;
+ if (SGEN_CAS_PTR ((gpointer)&free_blocks [size_index], next_free_block, block) != block)
+ goto retry;
+
+ block->free_list = NULL;
+ block->next_free = NULL;
+
return obj;
}
alloc_obj (MonoVTable *vtable, size_t size, gboolean pinned, gboolean has_references)
{
int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size);
- MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
+ MSBlockInfo * volatile * free_blocks = FREE_BLOCKS (pinned, has_references);
void *obj;
if (!free_blocks [size_index]) {
{
MSBlockInfo *block = MS_BLOCK_FOR_OBJ (obj);
int word, bit;
+ gboolean in_free_list;
+
+ SGEN_ASSERT (9, sweep_state == SWEEP_STATE_SWEPT, "Should have waited for sweep to free objects.");
- if (!block->swept)
- sweep_block (block, FALSE);
+ ensure_can_access_block_free_list (block);
SGEN_ASSERT (9, (pinned && block->pinned) || (!pinned && !block->pinned), "free-object pinning mixup object %p pinned %d block %p pinned %d", obj, pinned, block, block->pinned);
SGEN_ASSERT (9, MS_OBJ_ALLOCED (obj, block), "object %p is already free", obj);
MS_CALC_MARK_BIT (word, bit, obj);
SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p has mark bit set");
- if (!block->free_list) {
- MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, block->has_references);
- int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size);
- SGEN_ASSERT (9, !block->next_free, "block %p doesn't have a free-list of object but belongs to a free-list of blocks");
- block->next_free = free_blocks [size_index];
- free_blocks [size_index] = block;
- }
+
memset (obj, 0, size);
+
+ in_free_list = !!block->free_list;
*(void**)obj = block->free_list;
block->free_list = (void**)obj;
+
+ if (!in_free_list) {
+ MSBlockInfo * volatile *free_blocks = FREE_BLOCKS (pinned, block->has_references);
+ int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size);
+ SGEN_ASSERT (9, !block->next_free, "block %p doesn't have a free-list of object but belongs to a free-list of blocks");
+ add_free_block (free_blocks, size_index, block);
+ }
}
static void
static void*
major_alloc_degraded (MonoVTable *vtable, size_t size)
{
- void *obj;
- size_t old_num_sections;
-
- old_num_sections = num_major_sections;
-
- obj = alloc_obj (vtable, size, FALSE, SGEN_VTABLE_HAS_REFERENCES (vtable));
+ void *obj = alloc_obj (vtable, size, FALSE, SGEN_VTABLE_HAS_REFERENCES (vtable));
if (G_LIKELY (obj)) {
HEAVY_STAT (++stat_objects_alloced_degraded);
HEAVY_STAT (stat_bytes_alloced_degraded += size);
- g_assert (num_major_sections >= old_num_sections);
- sgen_register_major_sections_alloced (num_major_sections - old_num_sections);
}
return obj;
}
{
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) {
int count = MS_BLOCK_FREE / block->obj_size;
int i;
}
return !block->pinned;
}
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
return FALSE;
}
+static gboolean
+try_set_sweep_state (int new, int expected)
+{
+ int old = SGEN_CAS (&sweep_state, new, expected);
+ return old == expected;
+}
+
+static void
+set_sweep_state (int new, int expected)
+{
+ gboolean success = try_set_sweep_state (new, expected);
+ SGEN_ASSERT (0, success, "Could not set sweep state.");
+}
+
+static gboolean ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *have_checked);
+
+static SgenThreadPoolJob * volatile sweep_job;
+
+static void
+major_finish_sweep_checking (void)
+{
+ int block_index;
+ SgenThreadPoolJob *job;
+
+ retry:
+ switch (sweep_state) {
+ case SWEEP_STATE_SWEPT:
+ case SWEEP_STATE_NEED_SWEEPING:
+ return;
+ case SWEEP_STATE_SWEEPING:
+ if (try_set_sweep_state (SWEEP_STATE_SWEEPING_AND_ITERATING, SWEEP_STATE_SWEEPING))
+ break;
+ goto retry;
+ case SWEEP_STATE_SWEEPING_AND_ITERATING:
+ SGEN_ASSERT (0, FALSE, "Is there another minor collection running?");
+ goto retry;
+ case SWEEP_STATE_COMPACTING:
+ goto wait;
+ default:
+ SGEN_ASSERT (0, FALSE, "Invalid sweep state.");
+ break;
+ }
+
+ /*
+ * We're running with the world stopped and the only other thread doing work is the
+ * sweep thread, which doesn't add blocks to the array, so we can safely access
+ * `next_slot`.
+ */
+ for (block_index = 0; block_index < allocated_blocks.next_slot; ++block_index)
+ ensure_block_is_checked_for_sweeping (block_index, FALSE, NULL);
+
+ set_sweep_state (SWEEP_STATE_SWEEPING, SWEEP_STATE_SWEEPING_AND_ITERATING);
+
+ wait:
+ job = sweep_job;
+ if (job)
+ sgen_thread_pool_job_wait (job);
+ SGEN_ASSERT (0, !sweep_job, "Why did the sweep job not null itself?");
+ SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "How is the sweep job done but we're not swept?");
+}
+
static void
major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc callback, void *data)
{
gboolean pinned = flags & ITERATE_OBJECTS_PINNED;
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ major_finish_sweep_checking ();
+ FOREACH_BLOCK_NO_LOCK (block) {
int count = MS_BLOCK_FREE / block->obj_size;
int i;
if (!block->pinned && !non_pinned)
continue;
if (sweep && lazy_sweep) {
- sweep_block (block, FALSE);
- SGEN_ASSERT (0, block->swept, "Block must be swept after sweeping");
+ sweep_block (block);
+ SGEN_ASSERT (6, block->state == BLOCK_STATE_SWEPT, "Block must be swept after sweeping");
}
for (i = 0; i < count; ++i) {
void **obj = (void**) MS_BLOCK_OBJ (block, i);
- if (!block->swept) {
+ /*
+ * We've finished sweep checking, but if we're sweeping lazily and
+ * the flags don't require us to sweep, the block might still need
+ * sweeping. In that case, we need to consult the mark bits to tell
+ * us whether an object slot is live.
+ */
+ if (!block_is_swept_or_marking (block)) {
int word, bit;
+ SGEN_ASSERT (6, !sweep && block->state == BLOCK_STATE_NEED_SWEEPING, "Has sweeping not finished?");
MS_CALC_MARK_BIT (word, bit, obj);
if (!MS_MARK_BIT (block, word, bit))
continue;
if (MS_OBJ_ALLOCED (obj, block))
callback ((char*)obj, block->obj_size, data);
}
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
}
static gboolean
{
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
int idx;
char *obj;
if (obj != object)
return FALSE;
return MS_OBJ_ALLOCED (obj, block);
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
return FALSE;
}
{
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
int idx;
char *obj;
gboolean live;
SGEN_LOG (0, " marked %d)\n", marked ? 1 : 0);
return vtable;
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
return NULL;
}
for (i = 0; i < num_block_obj_sizes; ++i)
slots_available [i] = slots_used [i] = 0;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
int index = ms_find_block_obj_size_index (block->obj_size);
int count = MS_BLOCK_FREE / block->obj_size;
if (MS_OBJ_ALLOCED (MS_BLOCK_OBJ (block, i), block))
++slots_used [index];
}
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
fprintf (heap_dump_file, "<occupancies>\n");
for (i = 0; i < num_block_obj_sizes; ++i) {
}
fprintf (heap_dump_file, "</occupancies>\n");
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
int count = MS_BLOCK_FREE / block->obj_size;
int i;
int start = -1;
}
fprintf (heap_dump_file, "</section>\n");
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
}
#define LOAD_VTABLE SGEN_LOAD_VTABLE
major_copy_or_mark_object_with_evacuation_concurrent (void **ptr, void *obj, SgenGrayQueue *queue)
{
SGEN_ASSERT (9, sgen_concurrent_collection_in_progress (), "Why are we scanning concurrently when there's no concurrent collection on?");
- SGEN_ASSERT (9, !sgen_workers_are_working () || sgen_is_worker_thread (mono_native_thread_id_get ()), "We must not scan from two threads at the same time!");
+ SGEN_ASSERT (9, !sgen_workers_are_working () || sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "We must not scan from two threads at the same time!");
g_assert (!SGEN_OBJECT_IS_FORWARDED (obj));
}
}
+static inline gboolean
+try_set_block_state (MSBlockInfo *block, gint32 new_state, gint32 expected_state)
+{
+ gint32 old_state = SGEN_CAS (&block->state, new_state, expected_state);
+ gboolean success = old_state == expected_state;
+ if (success)
+ binary_protocol_block_set_state (block, MS_BLOCK_SIZE, old_state, new_state);
+ return success;
+}
+
+static inline void
+set_block_state (MSBlockInfo *block, gint32 new_state, gint32 expected_state)
+{
+ SGEN_ASSERT (6, block->state == expected_state, "Block state incorrect before set");
+ block->state = new_state;
+}
+
/*
- * sweep_block:
+ * If `block` needs sweeping, sweep it and return TRUE. Otherwise return FALSE.
*
- * Traverse BLOCK, freeing and zeroing unused objects.
+ * Sweeping means iterating through the block's slots and building the free-list from the
+ * unmarked ones. They will also be zeroed. The mark bits will be reset.
*/
-static void
-sweep_block (MSBlockInfo *block, gboolean during_major_collection)
+static gboolean
+sweep_block (MSBlockInfo *block)
{
int count;
void *reversed = NULL;
- if (!during_major_collection)
- g_assert (!sgen_concurrent_collection_in_progress ());
+ retry:
+ switch (block->state) {
+ case BLOCK_STATE_SWEPT:
+ return FALSE;
+ case BLOCK_STATE_MARKING:
+ case BLOCK_STATE_CHECKING:
+ SGEN_ASSERT (0, FALSE, "How did we get to sweep a block that's being marked or being checked?");
+ goto retry;
+ case BLOCK_STATE_SWEEPING:
+ /* FIXME: Do this more elegantly */
+ g_usleep (100);
+ goto retry;
+ case BLOCK_STATE_NEED_SWEEPING:
+ if (!try_set_block_state (block, BLOCK_STATE_SWEEPING, BLOCK_STATE_NEED_SWEEPING))
+ goto retry;
+ break;
+ default:
+ SGEN_ASSERT (0, FALSE, "Illegal block state");
+ }
- if (block->swept)
- return;
+ SGEN_ASSERT (6, block->state == BLOCK_STATE_SWEEPING, "How did we get here without setting state to sweeping?");
count = MS_BLOCK_FREE / block->obj_size;
}
block->free_list = reversed;
- block->swept = 1;
+ mono_memory_write_barrier ();
+
+ set_block_state (block, BLOCK_STATE_SWEPT, BLOCK_STATE_SWEEPING);
+
+ return TRUE;
}
static inline int
return count;
}
+/* statistics for evacuation */
+static size_t *sweep_slots_available;
+static size_t *sweep_slots_used;
+static size_t *sweep_num_blocks;
+
+static volatile size_t num_major_sections_before_sweep;
+static volatile size_t num_major_sections_freed_in_sweep;
+
static void
-major_sweep (void)
+sweep_start (void)
{
int i;
- MSBlockInfo *block;
-
- /* statistics for evacuation */
- int *slots_available = alloca (sizeof (int) * num_block_obj_sizes);
- int *slots_used = alloca (sizeof (int) * num_block_obj_sizes);
- int *num_blocks = alloca (sizeof (int) * num_block_obj_sizes);
-
- mword total_evacuate_heap = 0;
- mword total_evacuate_saved = 0;
for (i = 0; i < num_block_obj_sizes; ++i)
- slots_available [i] = slots_used [i] = num_blocks [i] = 0;
+ sweep_slots_available [i] = sweep_slots_used [i] = sweep_num_blocks [i] = 0;
/* clear all the free lists */
for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i) {
- MSBlockInfo **free_blocks = free_block_lists [i];
+ MSBlockInfo * volatile *free_blocks = free_block_lists [i];
int j;
for (j = 0; j < num_block_obj_sizes; ++j)
free_blocks [j] = NULL;
}
+}
- /* traverse all blocks, free and zero unmarked objects */
- FOREACH_BLOCK (block) {
- int count;
- gboolean have_live = FALSE;
- gboolean has_pinned;
- gboolean have_free = FALSE;
- int obj_size_index;
- int nused = 0;
+static void sweep_finish (void);
- obj_size_index = block->obj_size_index;
+/*
+ * If `wait` is TRUE and the block is currently being checked, this function will wait until
+ * the checking has finished.
+ *
+ * Returns whether the block is still there. If `wait` is FALSE, the return value will not
+ * be correct, i.e. must not be used.
+ */
+static gboolean
+ensure_block_is_checked_for_sweeping (int block_index, gboolean wait, gboolean *have_checked)
+{
+ int count;
+ gboolean have_live = FALSE;
+ gboolean have_free = FALSE;
+ int nused = 0;
+ int block_state;
+ int i;
+ void *tagged_block;
+ MSBlockInfo *block;
+
+ SGEN_ASSERT (6, sweep_in_progress (), "Why do we call this function if there's no sweep in progress?");
+
+ if (have_checked)
+ *have_checked = FALSE;
- has_pinned = block->has_pinned;
- block->has_pinned = block->pinned;
+ retry:
+ tagged_block = *(void * volatile *)&allocated_blocks.data [block_index];
+ if (!tagged_block)
+ return FALSE;
- block->is_to_space = FALSE;
- block->swept = 0;
+ if (BLOCK_IS_TAGGED_CHECKING (tagged_block)) {
+ if (!wait)
+ return FALSE;
+ /* FIXME: do this more elegantly */
+ g_usleep (100);
+ goto retry;
+ }
- count = MS_BLOCK_FREE / block->obj_size;
+ if (SGEN_CAS_PTR (&allocated_blocks.data [block_index], BLOCK_TAG_CHECKING (tagged_block), tagged_block) != tagged_block)
+ goto retry;
- if (block->cardtable_mod_union) {
- sgen_free_internal_dynamic (block->cardtable_mod_union, CARDS_PER_BLOCK, INTERNAL_MEM_CARDTABLE_MOD_UNION);
- block->cardtable_mod_union = NULL;
- }
+ block = BLOCK_UNTAG (tagged_block);
+ block_state = block->state;
- /* Count marked objects in the block */
- for (i = 0; i < MS_NUM_MARK_WORDS; ++i) {
- nused += bitcount (block->mark_words [i]);
+ if (!sweep_in_progress ()) {
+ SGEN_ASSERT (6, block_state != BLOCK_STATE_SWEEPING && block_state != BLOCK_STATE_CHECKING, "Invalid block state.");
+ if (!lazy_sweep)
+ SGEN_ASSERT (6, block_state != BLOCK_STATE_NEED_SWEEPING, "Invalid block state.");
+ }
+
+ switch (block_state) {
+ case BLOCK_STATE_SWEPT:
+ case BLOCK_STATE_NEED_SWEEPING:
+ case BLOCK_STATE_SWEEPING:
+ goto done;
+ case BLOCK_STATE_MARKING:
+ break;
+ case BLOCK_STATE_CHECKING:
+ SGEN_ASSERT (0, FALSE, "We set the CHECKING bit - how can the stage be CHECKING?");
+ goto done;
+ default:
+ SGEN_ASSERT (0, FALSE, "Illegal block state");
+ break;
+ }
+
+ SGEN_ASSERT (6, block->state == BLOCK_STATE_MARKING, "When we sweep all blocks must start out marking.");
+ set_block_state (block, BLOCK_STATE_CHECKING, BLOCK_STATE_MARKING);
+
+ if (have_checked)
+ *have_checked = TRUE;
+
+ block->has_pinned = block->pinned;
+
+ block->is_to_space = FALSE;
+
+ count = MS_BLOCK_FREE / block->obj_size;
+
+ if (block->cardtable_mod_union) {
+ sgen_free_internal_dynamic (block->cardtable_mod_union, CARDS_PER_BLOCK, INTERNAL_MEM_CARDTABLE_MOD_UNION);
+ block->cardtable_mod_union = NULL;
+ }
+
+ /* Count marked objects in the block */
+ for (i = 0; i < MS_NUM_MARK_WORDS; ++i)
+ nused += bitcount (block->mark_words [i]);
+
+ if (nused)
+ have_live = TRUE;
+ if (nused < count)
+ have_free = TRUE;
+
+ if (have_live) {
+ int obj_size_index = block->obj_size_index;
+ gboolean has_pinned = block->has_pinned;
+
+ set_block_state (block, BLOCK_STATE_NEED_SWEEPING, BLOCK_STATE_CHECKING);
+
+ /*
+ * FIXME: Go straight to SWEPT if there are no free slots. We need
+ * to set the free slot list to NULL, though, and maybe update some
+ * statistics.
+ */
+ if (!lazy_sweep)
+ sweep_block (block);
+
+ if (!has_pinned) {
+ ++sweep_num_blocks [obj_size_index];
+ sweep_slots_used [obj_size_index] += nused;
+ sweep_slots_available [obj_size_index] += count;
}
- if (nused) {
- have_live = TRUE;
+
+ /*
+ * If there are free slots in the block, add
+ * the block to the corresponding free list.
+ */
+ if (have_free) {
+ MSBlockInfo * volatile *free_blocks = FREE_BLOCKS (block->pinned, block->has_references);
+
+ if (!lazy_sweep)
+ SGEN_ASSERT (6, block->free_list, "How do we not have a free list when there are free slots?");
+
+ add_free_block (free_blocks, obj_size_index, block);
}
- if (nused < count)
- have_free = TRUE;
- if (!lazy_sweep)
- sweep_block (block, TRUE);
+ /* FIXME: Do we need the heap boundaries while we do nursery collections? */
+ update_heap_boundaries_for_block (block);
+ } else {
+ /*
+ * Blocks without live objects are removed from the
+ * block list and freed.
+ */
+ SGEN_ASSERT (6, block_index < allocated_blocks.next_slot, "How did the number of blocks shrink?");
+ SGEN_ASSERT (6, allocated_blocks.data [block_index] == BLOCK_TAG_CHECKING (tagged_block), "How did the block move?");
- if (have_live) {
- if (!has_pinned) {
- ++num_blocks [obj_size_index];
- slots_used [obj_size_index] += nused;
- slots_available [obj_size_index] += count;
- }
+ binary_protocol_empty (MS_BLOCK_OBJ (block, 0), (char*)MS_BLOCK_OBJ (block, count) - (char*)MS_BLOCK_OBJ (block, 0));
+ ms_free_block (block);
- /*
- * If there are free slots in the block, add
- * the block to the corresponding free list.
- */
- if (have_free) {
- MSBlockInfo **free_blocks = FREE_BLOCKS (block->pinned, block->has_references);
- int index = MS_BLOCK_OBJ_SIZE_INDEX (block->obj_size);
- block->next_free = free_blocks [index];
- free_blocks [index] = block;
- }
+ SGEN_ATOMIC_ADD_P (num_major_sections, -1);
- update_heap_boundaries_for_block (block);
- } else {
- /*
- * Blocks without live objects are removed from the
- * block list and freed.
- */
- DELETE_BLOCK_IN_FOREACH ();
+ tagged_block = NULL;
+ }
- binary_protocol_empty (MS_BLOCK_OBJ (block, 0), (char*)MS_BLOCK_OBJ (block, count) - (char*)MS_BLOCK_OBJ (block, 0));
- ms_free_block (block);
+ done:
+ allocated_blocks.data [block_index] = tagged_block;
+ return !!tagged_block;
+}
- --num_major_sections;
+static void
+sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job)
+{
+ int block_index;
+ int num_blocks = num_major_sections_before_sweep;
+
+ SGEN_ASSERT (0, sweep_in_progress (), "Sweep thread called with wrong state");
+ SGEN_ASSERT (0, num_blocks <= allocated_blocks.next_slot, "How did we lose blocks?");
+
+ /*
+ * We traverse the block array from high to low. Nursery collections will have to
+ * cooperate with the sweep thread to finish sweeping, and they will traverse from
+ * low to high, to avoid constantly colliding on the same blocks.
+ */
+ for (block_index = num_blocks - 1; block_index >= 0; --block_index) {
+ gboolean have_checked;
+
+ /*
+ * The block might have been freed by another thread doing some checking
+ * work.
+ */
+ if (!ensure_block_is_checked_for_sweeping (block_index, TRUE, &have_checked))
+ ++num_major_sections_freed_in_sweep;
+ }
+
+ while (!try_set_sweep_state (SWEEP_STATE_COMPACTING, SWEEP_STATE_SWEEPING)) {
+ /*
+ * The main GC thread is currently iterating over the block array to help us
+ * finish the sweep. We have already finished, but we don't want to mess up
+ * that iteration, so we just wait for it.
+ */
+ g_usleep (100);
+ }
+
+ if (SGEN_MAX_ASSERT_LEVEL >= 6) {
+ for (block_index = num_blocks; block_index < allocated_blocks.next_slot; ++block_index) {
+ MSBlockInfo *block = BLOCK_UNTAG (allocated_blocks.data [block_index]);
+ SGEN_ASSERT (6, block && block->state == BLOCK_STATE_SWEPT, "How did a new block to be swept get added while swept?");
}
- } END_FOREACH_BLOCK;
+ }
+
sgen_pointer_queue_remove_nulls (&allocated_blocks);
+ sweep_finish ();
+
+ sweep_job = NULL;
+}
+
+static void
+sweep_finish (void)
+{
+ mword total_evacuate_heap = 0;
+ mword total_evacuate_saved = 0;
+ int i;
+
for (i = 0; i < num_block_obj_sizes; ++i) {
- float usage = (float)slots_used [i] / (float)slots_available [i];
- if (num_blocks [i] > 5 && usage < evacuation_threshold) {
+ float usage = (float)sweep_slots_used [i] / (float)sweep_slots_available [i];
+ if (sweep_num_blocks [i] > 5 && usage < evacuation_threshold) {
evacuate_block_obj_sizes [i] = TRUE;
/*
g_print ("slot size %d - %d of %d used\n",
evacuate_block_obj_sizes [i] = FALSE;
}
{
- mword total_bytes = block_obj_sizes [i] * slots_available [i];
+ mword total_bytes = block_obj_sizes [i] * sweep_slots_available [i];
total_evacuate_heap += total_bytes;
if (evacuate_block_obj_sizes [i])
- total_evacuate_saved += total_bytes - block_obj_sizes [i] * slots_used [i];
+ total_evacuate_saved += total_bytes - block_obj_sizes [i] * sweep_slots_used [i];
}
}
want_evacuation = (float)total_evacuate_saved / (float)total_evacuate_heap > (1 - concurrent_evacuation_threshold);
- have_swept = TRUE;
+ set_sweep_state (SWEEP_STATE_SWEPT, SWEEP_STATE_COMPACTING);
+}
+
+static void
+major_sweep (void)
+{
+ set_sweep_state (SWEEP_STATE_SWEEPING, SWEEP_STATE_NEED_SWEEPING);
+
+ sweep_start ();
+
+ SGEN_ASSERT (0, num_major_sections == allocated_blocks.next_slot, "We don't know how many blocks we have?");
+
+ num_major_sections_before_sweep = num_major_sections;
+ num_major_sections_freed_in_sweep = 0;
+
+ SGEN_ASSERT (0, !sweep_job, "We haven't finished the last sweep?");
+ if (concurrent_sweep) {
+ sweep_job = sgen_thread_pool_job_alloc ("sweep", sweep_job_func, sizeof (SgenThreadPoolJob));
+ sgen_thread_pool_job_enqueue (sweep_job);
+ } else {
+ sweep_job_func (NULL, NULL);
+ }
}
static gboolean
-major_have_finished_sweeping (void)
+major_have_swept (void)
{
- return have_swept;
+ return sweep_state == SWEEP_STATE_SWEPT;
}
static int count_pinned_ref;
#ifdef MARKSWEEP_CONSISTENCY_CHECK
consistency_check ();
#endif
- sgen_register_major_sections_alloced (num_major_sections - old_num_major_sections);
}
static void
major_start_major_collection (void)
{
+ MSBlockInfo *block;
int i;
- /* clear the free lists */
+ major_finish_sweep_checking ();
+
+ /*
+ * Clear the free lists for block sizes where we do evacuation. For those block
+ * sizes we will have to allocate new blocks.
+ */
for (i = 0; i < num_block_obj_sizes; ++i) {
if (!evacuate_block_obj_sizes [i])
continue;
free_block_lists [MS_BLOCK_FLAG_REFS][i] = NULL;
}
- // Sweep all unswept blocks
- if (lazy_sweep) {
- MSBlockInfo *block;
-
+ if (lazy_sweep)
MONO_GC_SWEEP_BEGIN (GENERATION_OLD, TRUE);
- FOREACH_BLOCK (block) {
- sweep_block (block, TRUE);
- } END_FOREACH_BLOCK;
+ /* Sweep all unswept blocks and set them to MARKING */
+ FOREACH_BLOCK_NO_LOCK (block) {
+ if (lazy_sweep)
+ sweep_block (block);
+ SGEN_ASSERT (0, block->state == BLOCK_STATE_SWEPT, "All blocks must be swept when we're pinning.");
+ set_block_state (block, BLOCK_STATE_MARKING, BLOCK_STATE_SWEPT);
+ } END_FOREACH_BLOCK_NO_LOCK;
+ if (lazy_sweep)
MONO_GC_SWEEP_END (GENERATION_OLD, TRUE);
- }
- SGEN_ASSERT (0, have_swept, "Cannot start major collection without having finished sweeping");
- have_swept = FALSE;
+ set_sweep_state (SWEEP_STATE_NEED_SWEEPING, SWEEP_STATE_SWEPT);
}
static void
}
#endif
+/*
+ * This is called with sweep completed and the world stopped.
+ */
static void
-major_free_swept_blocks (void)
+major_free_swept_blocks (size_t allowance)
{
- size_t section_reserve = sgen_get_minor_collection_allowance () / MS_BLOCK_SIZE;
+ /* FIXME: This is probably too much. It's assuming all objects are small. */
+ size_t section_reserve = allowance / MS_BLOCK_SIZE;
- g_assert (have_swept);
+ SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Sweeping must have finished before freeing blocks");
#if SIZEOF_VOID_P != 8
{
for (i = 0; i < arr_length; ++i) {
int d = dest;
void *block = empty_block_arr [i];
- SGEN_ASSERT (0, block, "we're not shifting correctly");
+ SGEN_ASSERT (6, block, "we're not shifting correctly");
if (i != dest) {
empty_block_arr [dest] = block;
/*
continue;
}
- SGEN_ASSERT (0, first >= 0 && d > first, "algorithm is wrong");
+ SGEN_ASSERT (6, first >= 0 && d > first, "algorithm is wrong");
if ((char*)block != ((char*)empty_block_arr [d-1]) + MS_BLOCK_SIZE) {
first = d;
}
}
- SGEN_ASSERT (0, dest <= i && dest <= arr_length, "array length is off");
+ SGEN_ASSERT (6, dest <= i && dest <= arr_length, "array length is off");
arr_length = dest;
- SGEN_ASSERT (0, arr_length == num_empty_blocks, "array length is off");
+ SGEN_ASSERT (6, arr_length == num_empty_blocks, "array length is off");
num_blocks >>= 1;
}
rebuild_next = (void**)&empty_blocks;
for (i = 0; i < arr_length; ++i) {
void *block = empty_block_arr [i];
- SGEN_ASSERT (0, block, "we're missing blocks");
+ SGEN_ASSERT (6, block, "we're missing blocks");
*rebuild_next = block;
rebuild_next = (void**)block;
}
{
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
size_t first_entry, last_entry;
- SGEN_ASSERT (0, block->swept, "All blocks must be swept when we're pinning.");
+ SGEN_ASSERT (6, block_is_swept_or_marking (block), "All blocks must be swept when we're pinning.");
sgen_find_optimized_pin_queue_area (MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SKIP, MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE,
&first_entry, &last_entry);
mark_pinned_objects_in_block (block, first_entry, last_entry, queue);
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
}
static void
gint64 size = 0;
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ /*
+ * We're holding the GC lock, but the sweep thread might be running. Make sure it's
+ * finished, then we can iterate over the block array.
+ */
+ major_finish_sweep_checking ();
+
+ FOREACH_BLOCK_NO_LOCK_CONDITION (TRUE, block) {
int count = MS_BLOCK_FREE / block->obj_size;
void **iter;
size += count * block->obj_size;
for (iter = block->free_list; iter; iter = (void**)*iter)
size -= block->obj_size;
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
return size;
}
+/* FIXME: return number of bytes, not of sections */
static size_t
get_num_major_sections (void)
{
return num_major_sections;
}
+/*
+ * Returns the number of bytes in blocks that were present when the last sweep was
+ * initiated, and were not freed during the sweep. They are the basis for calculating the
+ * allowance.
+ */
+static size_t
+get_bytes_survived_last_sweep (void)
+{
+ SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Can only query unswept sections after sweep");
+ return (num_major_sections_before_sweep - num_major_sections_freed_in_sweep) * MS_BLOCK_SIZE;
+}
+
static gboolean
major_handle_gc_param (const char *opt)
{
} else if (!strcmp (opt, "no-lazy-sweep")) {
lazy_sweep = FALSE;
return TRUE;
+ } else if (!strcmp (opt, "concurrent-sweep")) {
+ concurrent_sweep = TRUE;
+ return TRUE;
+ } else if (!strcmp (opt, "no-concurrent-sweep")) {
+ concurrent_sweep = FALSE;
+ return TRUE;
}
return FALSE;
""
" evacuation-threshold=P (where P is a percentage, an integer in 0-100)\n"
" (no-)lazy-sweep\n"
+ " (no-)concurrent-sweep\n"
);
}
+/*
+ * This callback is used to clear cards, move cards to the shadow table and do counting.
+ */
static void
major_iterate_live_block_ranges (sgen_cardtable_block_callback callback)
{
MSBlockInfo *block;
gboolean has_references;
- FOREACH_BLOCK_HAS_REFERENCES (block, has_references) {
+ major_finish_sweep_checking ();
+ FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK (block, has_references) {
if (has_references)
callback ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE);
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
}
#ifdef HEAVY_STATISTICS
}
static void
-major_scan_card_table (gboolean mod_union, SgenGrayQueue *queue)
+scan_card_table_for_block (MSBlockInfo *block, gboolean mod_union, ScanObjectFunc scan_func, SgenGrayQueue *queue)
{
- MSBlockInfo *block;
- gboolean has_references;
- ScanObjectFunc scan_func = sgen_get_current_object_ops ()->scan_object;
-
- if (!concurrent_mark)
- g_assert (!mod_union);
-
- FOREACH_BLOCK_HAS_REFERENCES (block, has_references) {
#ifndef SGEN_HAVE_OVERLAPPING_CARDS
- guint8 cards_copy [CARDS_PER_BLOCK];
+ guint8 cards_copy [CARDS_PER_BLOCK];
#endif
- gboolean small_objects;
- int block_obj_size;
- char *block_start;
- guint8 *card_data, *card_base;
- guint8 *card_data_end;
- char *scan_front = NULL;
+ gboolean small_objects;
+ int block_obj_size;
+ char *block_start;
+ guint8 *card_data, *card_base;
+ guint8 *card_data_end;
+ char *scan_front = NULL;
-#ifdef PREFETCH_CARDS
- int prefetch_index = __index + 6;
- if (prefetch_index < allocated_blocks.next_slot) {
- MSBlockInfo *prefetch_block = BLOCK_UNTAG_HAS_REFERENCES (allocated_blocks.data [prefetch_index]);
- guint8 *prefetch_cards = sgen_card_table_get_card_scan_address ((mword)MS_BLOCK_FOR_BLOCK_INFO (prefetch_block));
- PREFETCH_READ (prefetch_block);
- PREFETCH_WRITE (prefetch_cards);
- PREFETCH_WRITE (prefetch_cards + 32);
- }
-#endif
+ block_obj_size = block->obj_size;
+ small_objects = block_obj_size < CARD_SIZE_IN_BYTES;
- if (!has_references)
- continue;
-
- block_obj_size = block->obj_size;
- small_objects = block_obj_size < CARD_SIZE_IN_BYTES;
-
- block_start = MS_BLOCK_FOR_BLOCK_INFO (block);
+ block_start = MS_BLOCK_FOR_BLOCK_INFO (block);
+ /*
+ * This is safe in face of card aliasing for the following reason:
+ *
+ * Major blocks are 16k aligned, or 32 cards aligned.
+ * Cards aliasing happens in powers of two, so as long as major blocks are aligned to their
+ * sizes, they won't overflow the cardtable overlap modulus.
+ */
+ if (mod_union) {
+ card_data = card_base = block->cardtable_mod_union;
/*
- * This is safe in face of card aliasing for the following reason:
- *
- * Major blocks are 16k aligned, or 32 cards aligned.
- * Cards aliasing happens in powers of two, so as long as major blocks are aligned to their
- * sizes, they won't overflow the cardtable overlap modulus.
+ * This happens when the nursery collection that precedes finishing
+ * the concurrent collection allocates new major blocks.
*/
- if (mod_union) {
- card_data = card_base = block->cardtable_mod_union;
- /*
- * This happens when the nursery collection that precedes finishing
- * the concurrent collection allocates new major blocks.
- */
- if (!card_data)
- continue;
- } else {
+ if (!card_data)
+ return;
+ } else {
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
- card_data = card_base = sgen_card_table_get_card_scan_address ((mword)block_start);
+ card_data = card_base = sgen_card_table_get_card_scan_address ((mword)block_start);
#else
- if (!sgen_card_table_get_card_data (cards_copy, (mword)block_start, CARDS_PER_BLOCK))
- continue;
- card_data = card_base = cards_copy;
+ if (!sgen_card_table_get_card_data (cards_copy, (mword)block_start, CARDS_PER_BLOCK))
+ return;
+ card_data = card_base = cards_copy;
#endif
- }
- card_data_end = card_data + CARDS_PER_BLOCK;
+ }
+ card_data_end = card_data + CARDS_PER_BLOCK;
- card_data += MS_BLOCK_SKIP >> CARD_BITS;
+ card_data += MS_BLOCK_SKIP >> CARD_BITS;
- card_data = initial_skip_card (card_data);
- while (card_data < card_data_end) {
- size_t card_index, first_object_index;
- char *start;
- char *end;
- char *first_obj, *obj;
+ card_data = initial_skip_card (card_data);
+ while (card_data < card_data_end) {
+ size_t card_index, first_object_index;
+ char *start;
+ char *end;
+ char *first_obj, *obj;
- HEAVY_STAT (++scanned_cards);
+ HEAVY_STAT (++scanned_cards);
- if (!*card_data) {
- ++card_data;
- continue;
- }
+ if (!*card_data) {
+ ++card_data;
+ continue;
+ }
- card_index = card_data - card_base;
- start = (char*)(block_start + card_index * CARD_SIZE_IN_BYTES);
- end = start + CARD_SIZE_IN_BYTES;
+ card_index = card_data - card_base;
+ start = (char*)(block_start + card_index * CARD_SIZE_IN_BYTES);
+ end = start + CARD_SIZE_IN_BYTES;
- if (!block->swept)
- sweep_block (block, FALSE);
+ if (!block_is_swept_or_marking (block))
+ sweep_block (block);
- HEAVY_STAT (++marked_cards);
+ HEAVY_STAT (++marked_cards);
- if (small_objects)
- sgen_card_table_prepare_card_for_scanning (card_data);
+ if (small_objects)
+ sgen_card_table_prepare_card_for_scanning (card_data);
- /*
- * If the card we're looking at starts at or in the block header, we
- * must start at the first object in the block, without calculating
- * the index of the object we're hypothetically starting at, because
- * it would be negative.
- */
- if (card_index <= (MS_BLOCK_SKIP >> CARD_BITS))
- first_object_index = 0;
- else
- first_object_index = MS_BLOCK_OBJ_INDEX_FAST (start, block_start, block_obj_size);
+ /*
+ * If the card we're looking at starts at or in the block header, we
+ * must start at the first object in the block, without calculating
+ * the index of the object we're hypothetically starting at, because
+ * it would be negative.
+ */
+ if (card_index <= (MS_BLOCK_SKIP >> CARD_BITS))
+ first_object_index = 0;
+ else
+ first_object_index = MS_BLOCK_OBJ_INDEX_FAST (start, block_start, block_obj_size);
- obj = first_obj = (char*)MS_BLOCK_OBJ_FAST (block_start, block_obj_size, first_object_index);
+ obj = first_obj = (char*)MS_BLOCK_OBJ_FAST (block_start, block_obj_size, first_object_index);
- while (obj < end) {
- if (obj < scan_front || !MS_OBJ_ALLOCED_FAST (obj, block_start))
- goto next_object;
+ binary_protocol_card_scan (first_obj, end - first_obj);
- if (mod_union) {
- /* FIXME: do this more efficiently */
- int w, b;
- MS_CALC_MARK_BIT (w, b, obj);
- if (!MS_MARK_BIT (block, w, b))
- goto next_object;
- }
+ while (obj < end) {
+ if (obj < scan_front || !MS_OBJ_ALLOCED_FAST (obj, block_start))
+ goto next_object;
- if (small_objects) {
- HEAVY_STAT (++scanned_objects);
- scan_func (obj, sgen_obj_get_descriptor (obj), queue);
- } else {
- size_t offset = card_offset (obj, block_start);
- sgen_cardtable_scan_object (obj, block_obj_size, card_base + offset, mod_union, queue);
- }
- next_object:
- obj += block_obj_size;
- g_assert (scan_front <= obj);
- scan_front = obj;
+ if (mod_union) {
+ /* FIXME: do this more efficiently */
+ int w, b;
+ MS_CALC_MARK_BIT (w, b, obj);
+ if (!MS_MARK_BIT (block, w, b))
+ goto next_object;
}
- HEAVY_STAT (if (*card_data) ++remarked_cards);
- binary_protocol_card_scan (first_obj, obj - first_obj);
-
- if (small_objects)
- ++card_data;
- else
- card_data = card_base + card_offset (obj, block_start);
+ if (small_objects) {
+ HEAVY_STAT (++scanned_objects);
+ scan_func (obj, sgen_obj_get_descriptor (obj), queue);
+ } else {
+ size_t offset = card_offset (obj, block_start);
+ sgen_cardtable_scan_object (obj, block_obj_size, card_base + offset, mod_union, queue);
+ }
+ next_object:
+ obj += block_obj_size;
+ g_assert (scan_front <= obj);
+ scan_front = obj;
}
- } END_FOREACH_BLOCK;
+
+ HEAVY_STAT (if (*card_data) ++remarked_cards);
+
+ if (small_objects)
+ ++card_data;
+ else
+ card_data = card_base + card_offset (obj, block_start);
+ }
+}
+
+static void
+major_scan_card_table (gboolean mod_union, SgenGrayQueue *queue)
+{
+ ScanObjectFunc scan_func = sgen_get_current_object_ops ()->scan_object;
+ MSBlockInfo *block;
+ gboolean has_references;
+
+ if (!concurrent_mark)
+ g_assert (!mod_union);
+
+ major_finish_sweep_checking ();
+ FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK (block, has_references) {
+#ifdef PREFETCH_CARDS
+ int prefetch_index = __index + 6;
+ if (prefetch_index < allocated_blocks.next_slot) {
+ MSBlockInfo *prefetch_block = BLOCK_UNTAG (allocated_blocks.data [prefetch_index]);
+ guint8 *prefetch_cards = sgen_card_table_get_card_scan_address ((mword)MS_BLOCK_FOR_BLOCK_INFO (prefetch_block));
+ PREFETCH_READ (prefetch_block);
+ PREFETCH_WRITE (prefetch_cards);
+ PREFETCH_WRITE (prefetch_cards + 32);
+ }
+#endif
+
+ if (!has_references)
+ continue;
+
+ scan_card_table_for_block (block, mod_union, scan_func, queue);
+ } END_FOREACH_BLOCK_NO_LOCK;
}
static void
long long total_cards = 0;
long long marked_cards = 0;
- FOREACH_BLOCK_HAS_REFERENCES (block, has_references) {
+ if (sweep_in_progress ()) {
+ *num_total_cards = -1;
+ *num_marked_cards = -1;
+ return;
+ }
+
+ FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK (block, has_references) {
guint8 *cards = sgen_card_table_get_card_scan_address ((mword) MS_BLOCK_FOR_BLOCK_INFO (block));
int i;
if (cards [i])
++marked_cards;
}
- } END_FOREACH_BLOCK;
+ } END_FOREACH_BLOCK_NO_LOCK;
*num_total_cards = total_cards;
*num_marked_cards = marked_cards;
{
MSBlockInfo *block;
- FOREACH_BLOCK (block) {
+ FOREACH_BLOCK_NO_LOCK (block) {
size_t num_cards;
block->cardtable_mod_union = sgen_card_table_update_mod_union (block->cardtable_mod_union,
MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE, &num_cards);
- SGEN_ASSERT (0, num_cards == CARDS_PER_BLOCK, "Number of cards calculation is wrong");
- } END_FOREACH_BLOCK;
+ SGEN_ASSERT (6, num_cards == CARDS_PER_BLOCK, "Number of cards calculation is wrong");
+ } END_FOREACH_BLOCK_NO_LOCK;
}
static guint8*
return &block->cardtable_mod_union [offset];
}
-static void
-alloc_free_block_lists (MSBlockInfo ***lists)
-{
- int i;
- for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i)
- lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
-}
-
#undef pthread_create
static void
post_param_init (SgenMajorCollector *collector)
{
collector->sweeps_lazily = lazy_sweep;
+ collector->needs_thread_pool = concurrent_mark || concurrent_sweep;
}
static void
for (i = 0; i < num_block_obj_sizes; ++i)
evacuate_block_obj_sizes [i] = FALSE;
+ sweep_slots_available = sgen_alloc_internal_dynamic (sizeof (size_t) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
+ sweep_slots_used = sgen_alloc_internal_dynamic (sizeof (size_t) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
+ sweep_num_blocks = sgen_alloc_internal_dynamic (sizeof (size_t) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
+
/*
{
int i;
}
*/
- alloc_free_block_lists (free_block_lists);
+ for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i)
+ free_block_lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
for (i = 0; i < MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES; ++i)
fast_block_obj_size_indexes [i] = ms_find_block_obj_size_index (i * 8);
collector->section_size = MAJOR_SECTION_SIZE;
concurrent_mark = is_concurrent;
- if (is_concurrent) {
- collector->is_concurrent = TRUE;
+ collector->is_concurrent = is_concurrent;
+ collector->needs_thread_pool = is_concurrent || concurrent_sweep;
+ if (is_concurrent)
collector->want_synchronous_collection = &want_evacuation;
- } else {
- collector->is_concurrent = FALSE;
+ else
collector->want_synchronous_collection = NULL;
- }
collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked;
collector->supports_cardtable = TRUE;
}
collector->init_to_space = major_init_to_space;
collector->sweep = major_sweep;
- collector->have_finished_sweeping = major_have_finished_sweeping;
+ collector->have_swept = major_have_swept;
+ collector->finish_sweeping = major_finish_sweep_checking;
collector->free_swept_blocks = major_free_swept_blocks;
collector->check_scan_starts = major_check_scan_starts;
collector->dump_heap = major_dump_heap;
collector->obj_is_from_pinned_alloc = obj_is_from_pinned_alloc;
collector->report_pinned_memory_usage = major_report_pinned_memory_usage;
collector->get_num_major_sections = get_num_major_sections;
+ collector->get_bytes_survived_last_sweep = get_bytes_survived_last_sweep;
collector->handle_gc_param = major_handle_gc_param;
collector->print_gc_param_usage = major_print_gc_param_usage;
collector->post_param_init = post_param_init;
}
#if !defined (FIXED_HEAP) && !defined (SGEN_PARALLEL_MARK)
- /* FIXME: this will not work with evacuation or the split nursery. */
if (!is_concurrent)
collector->drain_gray_stack = drain_gray_stack;
#include "metadata/sgen-gc.h"
#include "metadata/sgen-memory-governor.h"
+#include "metadata/sgen-thread-pool.h"
#include "metadata/mono-gc.h"
#include "utils/mono-counters.h"
/* use this to tune when to do a major/minor collection */
static mword memory_pressure = 0;
-static mword minor_collection_allowance;
-static mword minor_collection_sections_alloced = 0;
+static mword major_collection_trigger_size;
static mword last_major_num_sections = 0;
static mword last_los_memory_usage = 0;
static gboolean need_calculate_minor_collection_allowance;
-static mword last_collection_old_num_major_sections;
+/* The size of the LOS after the last major collection, after sweeping. */
static mword last_collection_los_memory_usage = 0;
-static mword last_collection_old_los_memory_usage;
-static mword last_collection_los_memory_alloced;
static mword sgen_memgov_available_free_space (void);
/* GC trigger heuristics. */
static void
-sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite)
+sgen_memgov_calculate_minor_collection_allowance (void)
{
- size_t num_major_sections;
- mword new_major, new_heap_size, allowance_target;
-
- if (overwrite)
- g_assert (need_calculate_minor_collection_allowance);
+ size_t new_major, new_heap_size, allowance_target, allowance;
if (!need_calculate_minor_collection_allowance)
return;
- if (!major_collector.have_finished_sweeping ()) {
- if (overwrite)
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
- return;
- }
-
- num_major_sections = major_collector.get_num_major_sections ();
+ SGEN_ASSERT (0, major_collector.have_swept (), "Can only calculate allowance if heap is swept");
- new_major = num_major_sections * major_collector.section_size;
+ new_major = major_collector.get_bytes_survived_last_sweep ();
new_heap_size = new_major + last_collection_los_memory_usage;
/*
*/
allowance_target = new_heap_size / 3;
- minor_collection_allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
+ allowance = MAX (allowance_target, MIN_MINOR_COLLECTION_ALLOWANCE);
- if (new_heap_size + minor_collection_allowance > soft_heap_limit) {
+ if (new_heap_size + allowance > soft_heap_limit) {
if (new_heap_size > soft_heap_limit)
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+ allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
else
- minor_collection_allowance = MAX (soft_heap_limit - new_heap_size, MIN_MINOR_COLLECTION_ALLOWANCE);
- }
-
- if (debug_print_allowance) {
- mword old_major = last_collection_old_num_major_sections * major_collector.section_size;
-
- SGEN_LOG (1, "Before collection: %ld bytes (%ld major, %ld LOS)",
- (long)(old_major + last_collection_old_los_memory_usage), (long)old_major, (long)last_collection_old_los_memory_usage);
- SGEN_LOG (1, "After collection: %ld bytes (%ld major, %ld LOS)",
- (long)new_heap_size, (long)new_major, (long)last_collection_los_memory_usage);
- SGEN_LOG (1, "Allowance: %ld bytes", (long)minor_collection_allowance);
+ allowance = MAX (soft_heap_limit - new_heap_size, MIN_MINOR_COLLECTION_ALLOWANCE);
}
+ /* FIXME: Why is this here? */
if (major_collector.free_swept_blocks)
- major_collector.free_swept_blocks ();
+ major_collector.free_swept_blocks (allowance);
+
+ major_collection_trigger_size = new_heap_size + allowance;
need_calculate_minor_collection_allowance = FALSE;
-}
+ if (debug_print_allowance) {
+ SGEN_LOG (0, "Surviving sweep: %ld bytes (%ld major, %ld LOS)", (long)new_heap_size, (long)new_major, (long)last_collection_los_memory_usage);
+ SGEN_LOG (0, "Allowance: %ld bytes", (long)allowance);
+ SGEN_LOG (0, "Trigger size: %ld bytes", (long)major_collection_trigger_size);
+ }
+}
gboolean
sgen_need_major_collection (mword space_needed)
{
- mword los_alloced;
+ size_t heap_size;
+
if (sgen_concurrent_collection_in_progress ())
return FALSE;
- los_alloced = los_memory_usage - MIN (last_collection_los_memory_usage, los_memory_usage);
- return (space_needed > sgen_memgov_available_free_space ()) ||
- minor_collection_sections_alloced * major_collector.section_size + los_alloced > minor_collection_allowance;
+
+ /* FIXME: This is a cop-out. We should have some way of figuring this out. */
+ if (!major_collector.have_swept ())
+ return FALSE;
+
+ if (space_needed > sgen_memgov_available_free_space ())
+ return TRUE;
+
+ sgen_memgov_calculate_minor_collection_allowance ();
+
+ heap_size = major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage;
+
+ return heap_size > major_collection_trigger_size;
}
void
sgen_memgov_minor_collection_start (void)
{
- sgen_memgov_try_calculate_minor_collection_allowance (FALSE);
}
void
void
sgen_memgov_major_collection_start (void)
{
- last_collection_old_num_major_sections = sgen_get_major_collector ()->get_num_major_sections ();
-
- /*
- * A domain could have been freed, resulting in
- * los_memory_usage being less than last_collection_los_memory_usage.
- */
- last_collection_los_memory_alloced = los_memory_usage - MIN (last_collection_los_memory_usage, los_memory_usage);
- last_collection_old_los_memory_usage = los_memory_usage;
-
need_calculate_minor_collection_allowance = TRUE;
+
+ if (debug_print_allowance) {
+ SGEN_LOG (0, "Starting collection with heap size %ld bytes", (long)(major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage));
+ }
}
void
-sgen_memgov_major_collection_end (void)
+sgen_memgov_major_collection_end (gboolean forced)
{
- sgen_memgov_try_calculate_minor_collection_allowance (TRUE);
-
- minor_collection_sections_alloced = 0;
last_collection_los_memory_usage = los_memory_usage;
-}
-void
-sgen_memgov_collection_start (int generation)
-{
- last_major_num_sections = major_collector.get_num_major_sections ();
- last_los_memory_usage = los_memory_usage;
+ if (forced) {
+ sgen_get_major_collector ()->finish_sweeping ();
+ sgen_memgov_calculate_minor_collection_allowance ();
+ }
}
static void
los_memory_usage / 1024);
}
+/* FIXME: Remove either these or the specialized ones above. */
+void
+sgen_memgov_collection_start (int generation)
+{
+}
+
void
sgen_memgov_collection_end (int generation, GGTimingInfo* info, int info_count)
{
}
}
-void
-sgen_register_major_sections_alloced (size_t num_sections)
-{
- minor_collection_sections_alloced += num_sections;
-}
-
-mword
-sgen_get_minor_collection_allowance (void)
-{
- return minor_collection_allowance;
-}
-
/* Memory pressure API */
/* Negative value to remove */
sgen_memgov_try_alloc_space (mword size, int space)
{
if (sgen_memgov_available_free_space () < size) {
- SGEN_ASSERT (4, !sgen_is_worker_thread (mono_native_thread_id_get ()), "Memory shouldn't run out in worker thread");
+ SGEN_ASSERT (4, !sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Memory shouldn't run out in worker thread");
return FALSE;
}
soft_heap_limit = soft_limit;
debug_print_allowance = debug_allowance;
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
+ major_collection_trigger_size = MIN_MINOR_COLLECTION_ALLOWANCE;
mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, &total_alloc);
mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, &total_alloc_max);
if (save_target)
save_target_ratio = save_target;
- minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE;
}
#endif
void sgen_memgov_minor_collection_end (void);
void sgen_memgov_major_collection_start (void);
-void sgen_memgov_major_collection_end (void);
+void sgen_memgov_major_collection_end (gboolean forced);
void sgen_memgov_collection_start (int generation);
void sgen_memgov_collection_end (int generation, GGTimingInfo* info, int info_count);
-void sgen_register_major_sections_alloced (size_t num_sections);
-mword sgen_get_minor_collection_allowance (void);
gboolean sgen_need_major_collection (mword space_needed);
#include "metadata/sgen-gc.h"
#include "metadata/sgen-archdep.h"
#include "metadata/sgen-protocol.h"
+#include "metadata/sgen-thread-pool.h"
#include "metadata/object-internals.h"
#include "metadata/gc-internal.h"
cur_thread->suspend_done = TRUE;
FOREACH_THREAD_SAFE (info) {
- if (info == cur_thread || sgen_is_worker_thread (mono_thread_info_get_tid (info)))
+ if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
continue;
info->suspend_done = FALSE;
SGEN_LOG (4, "Reallocated pointer queue to size: %lu", new_size);
}
+gboolean
+sgen_pointer_queue_will_grow (SgenPointerQueue *queue)
+{
+ return queue->next_slot >= queue->size;
+}
+
void
sgen_pointer_queue_add (SgenPointerQueue *queue, void *ptr)
{
- if (queue->next_slot >= queue->size)
+ if (sgen_pointer_queue_will_grow (queue))
realloc_queue (queue);
queue->data [queue->next_slot++] = ptr;
void* sgen_pointer_queue_pop (SgenPointerQueue *queue);
gboolean sgen_pointer_queue_is_empty (SgenPointerQueue *queue);
void sgen_pointer_queue_free (SgenPointerQueue *queue);
+gboolean sgen_pointer_queue_will_grow (SgenPointerQueue *queue);
#endif
IS_VTABLE_MATCH (FALSE)
END_PROTOCOL_ENTRY
+BEGIN_PROTOCOL_ENTRY_HEAVY2 (binary_protocol_block_alloc, TYPE_POINTER, addr, TYPE_SIZE, size)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (FALSE)
+MATCH_INDEX (matches_interval (ptr, entry->addr, entry->size) ? 0 : BINARY_PROTOCOL_NO_MATCH)
+IS_VTABLE_MATCH (FALSE)
+END_PROTOCOL_ENTRY_HEAVY
+
+BEGIN_PROTOCOL_ENTRY_HEAVY2 (binary_protocol_block_free, TYPE_POINTER, addr, TYPE_SIZE, size)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (FALSE)
+MATCH_INDEX (matches_interval (ptr, entry->addr, entry->size) ? 0 : BINARY_PROTOCOL_NO_MATCH)
+IS_VTABLE_MATCH (FALSE)
+END_PROTOCOL_ENTRY_HEAVY
+
+BEGIN_PROTOCOL_ENTRY_HEAVY4 (binary_protocol_block_set_state, TYPE_POINTER, addr, TYPE_SIZE, size, TYPE_INT, old, TYPE_INT, new)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (FALSE)
+MATCH_INDEX (matches_interval (ptr, entry->addr, entry->size) ? 0 : BINARY_PROTOCOL_NO_MATCH)
+IS_VTABLE_MATCH (FALSE)
+END_PROTOCOL_ENTRY_HEAVY
+
BEGIN_PROTOCOL_ENTRY_HEAVY3 (binary_protocol_alloc, TYPE_POINTER, obj, TYPE_POINTER, vtable, TYPE_INT, size)
DEFAULT_PRINT ()
IS_ALWAYS_MATCH (FALSE)
#include "sgen-gc.h"
#include "sgen-protocol.h"
#include "sgen-memory-governor.h"
+#include "sgen-thread-pool.h"
#include "utils/mono-mmap.h"
#include "utils/mono-threads.h"
if (binary_protocol_file == -1)
return;
- if (sgen_is_worker_thread (mono_native_thread_id_get ()))
+ if (sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()))
type |= 0x80;
lock_recursive ();
#include "metadata/sgen-gc.h"
#include "metadata/sgen-protocol.h"
#include "metadata/sgen-memory-governor.h"
+#include "metadata/sgen-thread-pool.h"
#include "metadata/profiler-private.h"
#include "utils/mono-time.h"
#include "utils/dtrace.h"
#include "utils/mono-counters.h"
#include "utils/mono-threads.h"
+static gboolean world_is_stopped = FALSE;
+
#define TV_DECLARE SGEN_TV_DECLARE
#define TV_GETTIME SGEN_TV_GETTIME
#define TV_ELAPSED SGEN_TV_ELAPSED
TV_DECLARE (end_handshake);
int count, dead;
+ SGEN_ASSERT (0, !world_is_stopped, "Why are we stopping a stopped world?");
+
mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
MONO_GC_WORLD_STOP_BEGIN ();
binary_protocol_world_stopping (sgen_timestamp ());
count -= dead;
}
+ world_is_stopped = TRUE;
+
SGEN_LOG (3, "world stopped %d thread(s)", count);
mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
MONO_GC_WORLD_STOP_END ();
TV_DECLARE (end_bridge);
unsigned long usec, bridge_usec;
+ SGEN_ASSERT (0, world_is_stopped, "Why are we restarting a running world?");
+
if (binary_protocol_is_enabled ()) {
long long major_total = -1, major_marked = -1, los_total = -1, los_marked = -1;
if (binary_protocol_is_heavy_enabled ())
time_restart_world += TV_ELAPSED (start_handshake, end_sw);
usec = TV_ELAPSED (stop_world_time, end_sw);
max_pause_usec = MAX (usec, max_pause_usec);
+
+ world_is_stopped = FALSE;
+
SGEN_LOG (2, "restarted %d thread(s) (pause time: %d usec, max: %d)", count, (int)usec, (int)max_pause_usec);
mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
MONO_GC_WORLD_RESTART_END (generation);
return count;
}
+gboolean
+sgen_is_world_stopped (void)
+{
+ return world_is_stopped;
+}
+
void
sgen_init_stw (void)
{
We can't suspend the workers that will do all the heavy lifting.
FIXME Use some state bit in SgenThreadInfo for this.
*/
- if (sgen_is_worker_thread (mono_thread_info_get_tid (info))) {
+ if (sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info))) {
return FALSE;
}
#define SGEN_POINTER_TAG_4(p) ((void*)((mword)(p) | 4))
#define SGEN_POINTER_UNTAG_4(p) ((void*)((mword)(p) & ~4))
+#define SGEN_POINTER_UNTAG_12(p) ((void*)((mword)(p) & ~3))
#define SGEN_POINTER_UNTAG_24(p) ((void*)((mword)(p) & ~6))
#define SGEN_POINTER_IS_TAGGED_ANY(p) ((mword)(p) & SGEN_TAGGED_POINTER_MASK)
--- /dev/null
+/*
+ * sgen-thread-pool.c: Threadpool for all concurrent GC work.
+ *
+ * Copyright (C) 2015 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+#ifdef HAVE_SGEN_GC
+
+#include "mono/metadata/sgen-gc.h"
+#include "mono/metadata/sgen-thread-pool.h"
+#include "mono/metadata/sgen-pointer-queue.h"
+#include "mono/utils/mono-mutex.h"
+#include "mono/utils/mono-threads.h"
+
+static mono_mutex_t lock;
+static mono_cond_t work_cond;
+static mono_cond_t done_cond;
+
+static MonoNativeThreadId thread;
+
+/* Only accessed with the lock held. */
+static SgenPointerQueue job_queue;
+static volatile gboolean idle_working;
+
+static SgenThreadPoolThreadInitFunc thread_init_func;
+static SgenThreadPoolIdleJobFunc idle_job_func;
+
+enum {
+ STATE_WAITING,
+ STATE_IN_PROGRESS,
+ STATE_DONE
+};
+
+/* Assumes that the lock is held. */
+static SgenThreadPoolJob*
+get_job_and_set_in_progress (void)
+{
+ for (size_t i = 0; i < job_queue.next_slot; ++i) {
+ SgenThreadPoolJob *job = job_queue.data [i];
+ if (job->state == STATE_WAITING) {
+ job->state = STATE_IN_PROGRESS;
+ return job;
+ }
+ }
+ return NULL;
+}
+
+/* Assumes that the lock is held. */
+static ssize_t
+find_job_in_queue (SgenThreadPoolJob *job)
+{
+ for (ssize_t i = 0; i < job_queue.next_slot; ++i) {
+ if (job_queue.data [i] == job)
+ return i;
+ }
+ return -1;
+}
+
+/* Assumes that the lock is held. */
+static void
+remove_job (SgenThreadPoolJob *job)
+{
+ ssize_t index;
+ SGEN_ASSERT (0, job->state == STATE_DONE, "Why are we removing a job that's not done?");
+ index = find_job_in_queue (job);
+ SGEN_ASSERT (0, index >= 0, "Why is the job we're trying to remove not in the queue?");
+ job_queue.data [index] = NULL;
+ sgen_pointer_queue_remove_nulls (&job_queue);
+ sgen_thread_pool_job_free (job);
+}
+
+static mono_native_thread_return_t
+thread_func (void *thread_data)
+{
+ thread_init_func (thread_data);
+
+ mono_mutex_lock (&lock);
+ for (;;) {
+ SgenThreadPoolJob *job;
+ gboolean do_idle = idle_working;
+
+ job = get_job_and_set_in_progress ();
+ if (!job && !do_idle) {
+ mono_cond_wait (&work_cond, &lock);
+ do_idle = idle_working;
+ job = get_job_and_set_in_progress ();
+ }
+
+ mono_mutex_unlock (&lock);
+
+ if (job) {
+ job->func (thread_data, job);
+
+ mono_mutex_lock (&lock);
+
+ SGEN_ASSERT (0, job->state == STATE_IN_PROGRESS, "The job should still be in progress.");
+ job->state = STATE_DONE;
+ remove_job (job);
+ /*
+ * Only the main GC thread will ever wait on the done condition, so we don't
+ * have to broadcast.
+ */
+ mono_cond_signal (&done_cond);
+ } else {
+ SGEN_ASSERT (0, do_idle, "Why did we unlock if we still have to wait for idle?");
+ SGEN_ASSERT (0, idle_job_func, "Why do we have idle work when there's no idle job function?");
+ do {
+ do_idle = idle_job_func (thread_data);
+ } while (do_idle && !job_queue.next_slot);
+
+ mono_mutex_lock (&lock);
+
+ if (!do_idle) {
+ idle_working = FALSE;
+ mono_cond_signal (&done_cond);
+ }
+ }
+ }
+}
+
+void
+sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, void **thread_datas)
+{
+ SGEN_ASSERT (0, num_threads == 1, "We only support 1 thread pool thread for now.");
+
+ mono_mutex_init (&lock);
+ mono_cond_init (&work_cond, NULL);
+ mono_cond_init (&done_cond, NULL);
+
+ thread_init_func = init_func;
+ idle_job_func = idle_func;
+ idle_working = idle_func != NULL;
+
+ mono_native_thread_create (&thread, thread_func, thread_datas ? thread_datas [0] : NULL);
+}
+
+SgenThreadPoolJob*
+sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size)
+{
+ SgenThreadPoolJob *job = sgen_alloc_internal_dynamic (size, INTERNAL_MEM_THREAD_POOL_JOB, TRUE);
+ job->name = name;
+ job->size = size;
+ job->state = STATE_WAITING;
+ job->func = func;
+ return job;
+}
+
+void
+sgen_thread_pool_job_free (SgenThreadPoolJob *job)
+{
+ sgen_free_internal_dynamic (job, job->size, INTERNAL_MEM_THREAD_POOL_JOB);
+}
+
+void
+sgen_thread_pool_job_enqueue (SgenThreadPoolJob *job)
+{
+ mono_mutex_lock (&lock);
+
+ sgen_pointer_queue_add (&job_queue, job);
+ /*
+ * FIXME: We could check whether there is a job in progress. If there is, there's
+ * no need to signal the condition, at least as long as we have only one thread.
+ */
+ mono_cond_signal (&work_cond);
+
+ mono_mutex_unlock (&lock);
+}
+
+void
+sgen_thread_pool_job_wait (SgenThreadPoolJob *job)
+{
+ SGEN_ASSERT (0, job, "Where's the job?");
+
+ mono_mutex_lock (&lock);
+
+ while (find_job_in_queue (job) >= 0)
+ mono_cond_wait (&done_cond, &lock);
+
+ mono_mutex_unlock (&lock);
+}
+
+void
+sgen_thread_pool_idle_signal (void)
+{
+ SGEN_ASSERT (0, idle_job_func, "Why are we signaling idle without an idle function?");
+
+ if (idle_working)
+ return;
+
+ mono_mutex_lock (&lock);
+
+ idle_working = TRUE;
+ mono_cond_signal (&work_cond);
+
+ mono_mutex_unlock (&lock);
+}
+
+void
+sgen_thread_pool_idle_wait (void)
+{
+ SGEN_ASSERT (0, idle_job_func, "Why are we waiting for idle without an idle function?");
+
+ if (!idle_working)
+ return;
+
+ mono_mutex_lock (&lock);
+
+ while (idle_working)
+ mono_cond_wait (&done_cond, &lock);
+
+ mono_mutex_unlock (&lock);
+}
+
+void
+sgen_thread_pool_wait_for_all_jobs (void)
+{
+ mono_mutex_lock (&lock);
+
+ while (!sgen_pointer_queue_is_empty (&job_queue))
+ mono_cond_wait (&done_cond, &lock);
+
+ mono_mutex_unlock (&lock);
+}
+
+gboolean
+sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread)
+{
+ return some_thread == thread;
+}
+
+#endif
--- /dev/null
+/*
+ * sgen-thread-pool.h: Threadpool for all concurrent GC work.
+ *
+ * Copyright (C) 2015 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MONO_SGEN_THREAD_POOL_H__
+#define __MONO_SGEN_THREAD_POOL_H__
+
+typedef struct _SgenThreadPoolJob SgenThreadPoolJob;
+
+typedef void (*SgenThreadPoolJobFunc) (void *thread_data, SgenThreadPoolJob *job);
+
+struct _SgenThreadPoolJob {
+ const char *name;
+ SgenThreadPoolJobFunc func;
+ size_t size;
+ volatile gint32 state;
+};
+
+typedef void (*SgenThreadPoolThreadInitFunc) (void*);
+typedef gboolean (*SgenThreadPoolIdleJobFunc) (void*);
+
+void sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, void **thread_datas);
+
+SgenThreadPoolJob* sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size);
+/* This only needs to be called on jobs that are not enqueued. */
+void sgen_thread_pool_job_free (SgenThreadPoolJob *job);
+
+void sgen_thread_pool_job_enqueue (SgenThreadPoolJob *job);
+/* This must only be called after the job has been enqueued. */
+void sgen_thread_pool_job_wait (SgenThreadPoolJob *job);
+
+void sgen_thread_pool_idle_signal (void);
+void sgen_thread_pool_idle_wait (void);
+
+void sgen_thread_pool_wait_for_all_jobs (void);
+
+gboolean sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId thread);
+
+#endif
#include "metadata/sgen-gc.h"
#include "metadata/sgen-workers.h"
+#include "metadata/sgen-thread-pool.h"
#include "utils/mono-counters.h"
static int workers_num;
static WorkerData *workers_data;
-static void *workers_gc_thread_major_collector_data = NULL;
static SgenSectionGrayQueue workers_distribute_gray_queue;
static gboolean workers_distribute_gray_queue_inited;
-static gboolean workers_started = FALSE;
-
enum {
STATE_NOT_WORKING,
STATE_WORKING,
STATE_NURSERY_COLLECTION
} WorkersStateName;
-/*
- * | state | num_awake | num_posted | post_done |
- * |--------------------------+-----------+----------------------------+-----------|
- * | STATE_NOT_WORKING | 0 | * | 0 |
- * | STATE_WORKING | > 0 | <= workers_num - num_awake | * |
- * | STATE_NURSERY_COLLECTION | * | <= workers_num - num_awake | 1 |
- * | STATE_NURSERY_COLLECTION | 0 | 0 | 0 |
- */
-typedef union {
- gint32 value;
- struct {
- guint state : 4; /* WorkersStateName */
- /* Number of worker threads awake. */
- guint num_awake : 8;
- /* The state of the waiting semaphore. */
- guint num_posted : 8;
- /* Whether to post `workers_done_sem` */
- guint post_done : 1;
- } data;
-} State;
+typedef gint32 State;
static volatile State workers_state;
-static MonoSemType workers_waiting_sem;
-static MonoSemType workers_done_sem;
-
-static volatile int workers_job_queue_num_entries = 0;
-static volatile JobQueueEntry *workers_job_queue = NULL;
-static LOCK_DECLARE (workers_job_queue_mutex);
-static int workers_num_jobs_enqueued = 0;
-static volatile int workers_num_jobs_finished = 0;
-
-static guint64 stat_workers_stolen_from_self_lock;
-static guint64 stat_workers_stolen_from_self_no_lock;
-static guint64 stat_workers_stolen_from_others;
-static guint64 stat_workers_num_waited;
+static guint64 stat_workers_num_finished;
static gboolean
set_state (State old_state, State new_state)
{
- if (old_state.data.state == STATE_NURSERY_COLLECTION)
- SGEN_ASSERT (0, new_state.data.state != STATE_NOT_WORKING, "Can't go from nursery collection to not working");
+ if (old_state == STATE_NURSERY_COLLECTION)
+ SGEN_ASSERT (0, new_state != STATE_NOT_WORKING, "Can't go from nursery collection to not working");
- return InterlockedCompareExchange (&workers_state.value,
- new_state.value, old_state.value) == old_state.value;
+ return InterlockedCompareExchange (&workers_state, new_state, old_state) == old_state;
}
static void
assert_not_working (State state)
{
- SGEN_ASSERT (0, state.data.state == STATE_NOT_WORKING, "Can only signal enqueue work when in no work state");
- SGEN_ASSERT (0, state.data.num_awake == 0, "No workers can be awake when not working");
- SGEN_ASSERT (0, state.data.num_posted == 0, "Can't have posted already");
- SGEN_ASSERT (0, !state.data.post_done, "post_done can only be set when working");
-
+ SGEN_ASSERT (0, state == STATE_NOT_WORKING, "Can only signal enqueue work when in no work state");
}
static void
-assert_working (State state, gboolean from_worker)
+assert_working (State state)
{
- SGEN_ASSERT (0, state.data.state == STATE_WORKING, "A worker can't wait without being in working state");
- if (from_worker)
- SGEN_ASSERT (0, state.data.num_awake > 0, "How can we be awake, yet we are not counted?");
- else
- SGEN_ASSERT (0, state.data.num_awake + state.data.num_posted > 0, "How can we be working, yet no worker threads are awake or to be awoken?");
- SGEN_ASSERT (0, state.data.num_awake + state.data.num_posted <= workers_num, "There are too many worker threads awake");
+ SGEN_ASSERT (0, state == STATE_WORKING, "A worker can't wait without being in working state");
}
static void
-assert_nursery_collection (State state, gboolean from_worker)
+assert_nursery_collection (State state)
{
- SGEN_ASSERT (0, state.data.state == STATE_NURSERY_COLLECTION, "Must be in the nursery collection state");
- if (from_worker) {
- SGEN_ASSERT (0, state.data.num_awake > 0, "We're awake, but num_awake is zero");
- SGEN_ASSERT (0, state.data.post_done, "post_done must be set in the nursery collection state");
- }
- SGEN_ASSERT (0, state.data.num_awake <= workers_num, "There are too many worker threads awake");
- if (!state.data.post_done) {
- SGEN_ASSERT (0, state.data.num_awake == 0, "Once done has been posted no threads can be awake");
- SGEN_ASSERT (0, state.data.num_posted == 0, "Once done has been posted no thread must be awoken");
- }
+ SGEN_ASSERT (0, state == STATE_NURSERY_COLLECTION, "Must be in the nursery collection state");
}
static void
assert_working_or_nursery_collection (State state)
{
- if (state.data.state == STATE_WORKING)
- assert_working (state, TRUE);
- else
- assert_nursery_collection (state, TRUE);
+ if (state != STATE_WORKING)
+ assert_nursery_collection (state);
}
static void
-workers_signal_enqueue_work (int num_wake_up, gboolean from_nursery_collection)
+workers_signal_enqueue_work (gboolean from_nursery_collection)
{
State old_state = workers_state;
- State new_state = old_state;
- int i;
gboolean did_set_state;
- SGEN_ASSERT (0, num_wake_up <= workers_num, "Cannot wake up more workers than are present");
-
if (from_nursery_collection)
- assert_nursery_collection (old_state, FALSE);
+ assert_nursery_collection (old_state);
else
assert_not_working (old_state);
- new_state.data.state = STATE_WORKING;
- new_state.data.num_posted = num_wake_up;
-
- did_set_state = set_state (old_state, new_state);
+ did_set_state = set_state (old_state, STATE_WORKING);
SGEN_ASSERT (0, did_set_state, "Nobody else should be mutating the state");
- for (i = 0; i < num_wake_up; ++i)
- MONO_SEM_POST (&workers_waiting_sem);
+ sgen_thread_pool_idle_signal ();
}
static void
-workers_signal_enqueue_work_if_necessary (int num_wake_up)
+workers_signal_enqueue_work_if_necessary (void)
{
- if (workers_state.data.state == STATE_NOT_WORKING)
- workers_signal_enqueue_work (num_wake_up, FALSE);
+ if (workers_state == STATE_NOT_WORKING)
+ workers_signal_enqueue_work (FALSE);
}
void
sgen_workers_ensure_awake (void)
{
- SGEN_ASSERT (0, workers_state.data.state != STATE_NURSERY_COLLECTION, "Can't wake workers during nursery collection");
- workers_signal_enqueue_work_if_necessary (workers_num);
+ SGEN_ASSERT (0, workers_state != STATE_NURSERY_COLLECTION, "Can't wake workers during nursery collection");
+ workers_signal_enqueue_work_if_necessary ();
}
static void
-workers_wait (void)
+worker_finish (void)
{
- State old_state, new_state;
- gboolean post_done;
+ State old_state;
- ++stat_workers_num_waited;
+ ++stat_workers_num_finished;
do {
- new_state = old_state = workers_state;
+ old_state = workers_state;
assert_working_or_nursery_collection (old_state);
+ if (old_state == STATE_NURSERY_COLLECTION)
+ return;
- --new_state.data.num_awake;
- post_done = FALSE;
- if (!new_state.data.num_awake && !new_state.data.num_posted) {
- /* We are the last thread to go to sleep. */
- if (old_state.data.state == STATE_WORKING)
- new_state.data.state = STATE_NOT_WORKING;
-
- new_state.data.post_done = 0;
- if (old_state.data.post_done)
- post_done = TRUE;
- }
- } while (!set_state (old_state, new_state));
-
- if (post_done)
- MONO_SEM_POST (&workers_done_sem);
-
- MONO_SEM_WAIT (&workers_waiting_sem);
-
- do {
- new_state = old_state = workers_state;
-
- SGEN_ASSERT (0, old_state.data.num_posted > 0, "How can we be awake without the semaphore having been posted?");
- SGEN_ASSERT (0, old_state.data.num_awake < workers_num, "There are too many worker threads awake");
-
- --new_state.data.num_posted;
- ++new_state.data.num_awake;
-
- assert_working_or_nursery_collection (new_state);
- } while (!set_state (old_state, new_state));
+ /* We are the last thread to go to sleep. */
+ } while (!set_state (old_state, STATE_NOT_WORKING));
}
static gboolean
}
void
-sgen_workers_enqueue_job (const char *name, JobFunc func, void *data)
+sgen_workers_enqueue_job (SgenThreadPoolJob *job)
{
- int num_entries;
- JobQueueEntry *entry;
-
if (!collection_needs_workers ()) {
- func (NULL, data);
+ job->func (NULL, job);
+ sgen_thread_pool_job_free (job);
return;
}
- entry = sgen_alloc_internal (INTERNAL_MEM_JOB_QUEUE_ENTRY);
- entry->name = name;
- entry->func = func;
- entry->data = data;
-
- mono_mutex_lock (&workers_job_queue_mutex);
- entry->next = workers_job_queue;
- workers_job_queue = entry;
- num_entries = ++workers_job_queue_num_entries;
- ++workers_num_jobs_enqueued;
- mono_mutex_unlock (&workers_job_queue_mutex);
-
- if (workers_state.data.state != STATE_NURSERY_COLLECTION)
- workers_signal_enqueue_work_if_necessary (num_entries < workers_num ? num_entries : workers_num);
+ sgen_thread_pool_job_enqueue (job);
}
void
sgen_workers_wait_for_jobs_finished (void)
{
- // FIXME: implement this properly
- while (workers_num_jobs_finished < workers_num_jobs_enqueued) {
- workers_signal_enqueue_work_if_necessary (workers_num);
- /* FIXME: sleep less? */
- g_usleep (1000);
- }
+ sgen_thread_pool_wait_for_all_jobs ();
}
void
sgen_workers_signal_start_nursery_collection_and_wait (void)
{
- State old_state, new_state;
+ State old_state;
do {
- new_state = old_state = workers_state;
-
- new_state.data.state = STATE_NURSERY_COLLECTION;
-
- if (old_state.data.state == STATE_NOT_WORKING) {
- assert_not_working (old_state);
- } else {
- assert_working (old_state, FALSE);
- SGEN_ASSERT (0, !old_state.data.post_done, "We are not waiting for the workers");
+ old_state = workers_state;
- new_state.data.post_done = 1;
- }
- } while (!set_state (old_state, new_state));
+ if (old_state != STATE_NOT_WORKING)
+ assert_working (old_state);
+ } while (!set_state (old_state, STATE_NURSERY_COLLECTION));
- if (new_state.data.post_done)
- MONO_SEM_WAIT (&workers_done_sem);
+ sgen_thread_pool_idle_wait ();
- old_state = workers_state;
- assert_nursery_collection (old_state, FALSE);
- SGEN_ASSERT (0, !old_state.data.post_done, "We got the semaphore, so it must have been posted");
+ assert_nursery_collection (workers_state);
}
void
sgen_workers_signal_finish_nursery_collection (void)
{
- State old_state = workers_state;
-
- assert_nursery_collection (old_state, FALSE);
- SGEN_ASSERT (0, !old_state.data.post_done, "We are finishing the nursery collection, so we should have waited for the semaphore earlier");
-
- workers_signal_enqueue_work (workers_num, TRUE);
-}
-
-static gboolean
-workers_dequeue_and_do_job (WorkerData *data)
-{
- JobQueueEntry *entry;
-
- /*
- * At this point the GC might not be running anymore. We
- * could have been woken up by a job that was then taken by
- * another thread, after which the collection finished, so we
- * first have to successfully dequeue a job before doing
- * anything assuming that the collection is still ongoing.
- */
-
- if (!workers_job_queue_num_entries)
- return FALSE;
-
- mono_mutex_lock (&workers_job_queue_mutex);
- entry = (JobQueueEntry*)workers_job_queue;
- if (entry) {
- workers_job_queue = entry->next;
- --workers_job_queue_num_entries;
- }
- mono_mutex_unlock (&workers_job_queue_mutex);
-
- if (!entry)
- return FALSE;
-
- g_assert (collection_needs_workers ());
-
- entry->func (data, entry->data);
- sgen_free_internal (entry, INTERNAL_MEM_JOB_QUEUE_ENTRY);
-
- SGEN_ATOMIC_ADD (workers_num_jobs_finished, 1);
-
- return TRUE;
+ assert_nursery_collection (workers_state);
+ workers_signal_enqueue_work (TRUE);
}
static gboolean
sgen_get_major_collector ()->is_concurrent ? concurrent_enqueue_check : NULL);
}
-static mono_native_thread_return_t
-workers_thread_func (void *data_untyped)
+static void
+thread_pool_init_func (void *data_untyped)
{
WorkerData *data = data_untyped;
SgenMajorCollector *major = sgen_get_major_collector ();
mono_thread_info_register_small_id ();
- if (major->init_worker_thread)
- major->init_worker_thread (data->major_collector_data);
+ if (!major->is_concurrent)
+ return;
init_private_gray_queue (data);
+}
- for (;;) {
- gboolean did_work = FALSE;
-
- SGEN_ASSERT (0, sgen_get_current_collection_generation () != GENERATION_NURSERY, "Why are we doing work while there's a nursery collection happening?");
-
- while (workers_state.data.state == STATE_WORKING && workers_dequeue_and_do_job (data)) {
- did_work = TRUE;
- /* FIXME: maybe distribute the gray queue here? */
- }
+static gboolean
+marker_idle_func (void *data_untyped)
+{
+ WorkerData *data = data_untyped;
+ SgenMajorCollector *major = sgen_get_major_collector ();
- if (!did_work && (!sgen_gray_object_queue_is_empty (&data->private_gray_queue) || workers_get_work (data))) {
- SgenObjectOperations *ops = sgen_concurrent_collection_in_progress ()
- ? &major->major_concurrent_ops
- : &major->major_ops;
- ScanCopyContext ctx = { ops->scan_object, NULL, &data->private_gray_queue };
+ if (workers_state != STATE_WORKING)
+ return FALSE;
- g_assert (!sgen_gray_object_queue_is_empty (&data->private_gray_queue));
+ SGEN_ASSERT (0, sgen_get_current_collection_generation () != GENERATION_NURSERY, "Why are we doing work while there's a nursery collection happening?");
- while (!sgen_drain_gray_stack (32, ctx)) {
- if (workers_state.data.state == STATE_NURSERY_COLLECTION)
- workers_wait ();
- }
- g_assert (sgen_gray_object_queue_is_empty (&data->private_gray_queue));
+ if (!sgen_gray_object_queue_is_empty (&data->private_gray_queue) || workers_get_work (data)) {
+ SgenObjectOperations *ops = sgen_concurrent_collection_in_progress ()
+ ? &major->major_concurrent_ops
+ : &major->major_ops;
+ ScanCopyContext ctx = { ops->scan_object, NULL, &data->private_gray_queue };
- init_private_gray_queue (data);
+ SGEN_ASSERT (0, !sgen_gray_object_queue_is_empty (&data->private_gray_queue), "How is our gray queue empty if we just got work?");
- did_work = TRUE;
- }
+ sgen_drain_gray_stack (32, ctx);
- if (!did_work)
- workers_wait ();
+ return TRUE;
}
- /* dummy return to make compilers happy */
- return NULL;
+ worker_finish ();
+
+ return FALSE;
}
static void
-init_distribute_gray_queue (gboolean locked)
+init_distribute_gray_queue (void)
{
if (workers_distribute_gray_queue_inited) {
g_assert (sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue));
- g_assert (!workers_distribute_gray_queue.locked == !locked);
+ g_assert (workers_distribute_gray_queue.locked);
return;
}
- sgen_section_gray_queue_init (&workers_distribute_gray_queue, locked,
+ sgen_section_gray_queue_init (&workers_distribute_gray_queue, TRUE,
sgen_get_major_collector ()->is_concurrent ? concurrent_enqueue_check : NULL);
workers_distribute_gray_queue_inited = TRUE;
}
void
sgen_workers_init_distribute_gray_queue (void)
{
- if (!collection_needs_workers ())
- return;
-
- init_distribute_gray_queue (sgen_get_major_collector ()->is_concurrent);
+ SGEN_ASSERT (0, sgen_get_major_collector ()->is_concurrent && collection_needs_workers (),
+ "Why should we init the distribute gray queue if we don't need it?");
+ init_distribute_gray_queue ();
}
void
sgen_workers_init (int num_workers)
{
int i;
+ void *workers_data_ptrs [num_workers];
- if (!sgen_get_major_collector ()->is_concurrent)
+ if (!sgen_get_major_collector ()->is_concurrent) {
+ sgen_thread_pool_init (num_workers, thread_pool_init_func, NULL, NULL);
return;
+ }
//g_print ("initing %d workers\n", num_workers);
workers_data = sgen_alloc_internal_dynamic (sizeof (WorkerData) * num_workers, INTERNAL_MEM_WORKER_DATA, TRUE);
memset (workers_data, 0, sizeof (WorkerData) * num_workers);
- MONO_SEM_INIT (&workers_waiting_sem, 0);
- MONO_SEM_INIT (&workers_done_sem, 0);
-
- init_distribute_gray_queue (sgen_get_major_collector ()->is_concurrent);
-
- if (sgen_get_major_collector ()->alloc_worker_data)
- workers_gc_thread_major_collector_data = sgen_get_major_collector ()->alloc_worker_data ();
-
- for (i = 0; i < workers_num; ++i) {
- workers_data [i].index = i;
-
- if (sgen_get_major_collector ()->alloc_worker_data)
- workers_data [i].major_collector_data = sgen_get_major_collector ()->alloc_worker_data ();
- }
-
- LOCK_INIT (workers_job_queue_mutex);
+ init_distribute_gray_queue ();
- sgen_register_fixed_internal_mem_type (INTERNAL_MEM_JOB_QUEUE_ENTRY, sizeof (JobQueueEntry));
-
- mono_counters_register ("Stolen from self lock", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_workers_stolen_from_self_lock);
- mono_counters_register ("Stolen from self no lock", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_workers_stolen_from_self_no_lock);
- mono_counters_register ("Stolen from others", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_workers_stolen_from_others);
- mono_counters_register ("# workers waited", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_workers_num_waited);
-}
-
-/* only the GC thread is allowed to start and join workers */
+ for (i = 0; i < workers_num; ++i)
+ workers_data_ptrs [i] = &workers_data [i];
-static void
-workers_start_worker (int index)
-{
- g_assert (index >= 0 && index < workers_num);
+ sgen_thread_pool_init (num_workers, thread_pool_init_func, marker_idle_func, workers_data_ptrs);
- g_assert (!workers_data [index].thread);
- mono_native_thread_create (&workers_data [index].thread, workers_thread_func, &workers_data [index]);
+ mono_counters_register ("# workers finished", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_workers_num_finished);
}
void
sgen_workers_start_all_workers (void)
{
- State old_state, new_state;
- int i;
- gboolean result;
-
if (!collection_needs_workers ())
return;
- if (sgen_get_major_collector ()->init_worker_thread)
- sgen_get_major_collector ()->init_worker_thread (workers_gc_thread_major_collector_data);
-
- old_state = new_state = workers_state;
- assert_not_working (old_state);
-
- g_assert (workers_job_queue_num_entries == 0);
- workers_num_jobs_enqueued = 0;
- workers_num_jobs_finished = 0;
-
- if (workers_started) {
- workers_signal_enqueue_work (workers_num, FALSE);
- return;
- }
-
- new_state.data.state = STATE_WORKING;
- new_state.data.num_awake = workers_num;
- result = set_state (old_state, new_state);
- SGEN_ASSERT (0, result, "Nobody else should have modified the state - workers have not been started yet");
-
- for (i = 0; i < workers_num; ++i)
- workers_start_worker (i);
-
- workers_started = TRUE;
-}
-
-gboolean
-sgen_workers_have_started (void)
-{
- return workers_started;
+ workers_signal_enqueue_work (FALSE);
}
void
sgen_workers_join (void)
{
- State old_state;
int i;
if (!collection_needs_workers ())
return;
- for (;;) {
- old_state = workers_state;
- SGEN_ASSERT (0, old_state.data.state != STATE_NURSERY_COLLECTION, "Can't be in nursery collection when joining");
-
- if (old_state.data.state == STATE_WORKING) {
- State new_state = old_state;
-
- SGEN_ASSERT (0, !old_state.data.post_done, "Why is post_done already set?");
- new_state.data.post_done = 1;
- if (!set_state (old_state, new_state))
- continue;
-
- MONO_SEM_WAIT (&workers_done_sem);
+ sgen_thread_pool_wait_for_all_jobs ();
- old_state = workers_state;
- }
-
- assert_not_working (old_state);
+ for (;;) {
+ SGEN_ASSERT (0, workers_state != STATE_NURSERY_COLLECTION, "Can't be in nursery collection when joining");
+ sgen_thread_pool_idle_wait ();
+ assert_not_working (workers_state);
/*
* Checking whether there is still work left and, if not, going to sleep,
* workers. Therefore there's a race condition where work can be added
* after they've checked for work, and before they've gone to sleep.
*/
- if (!workers_job_queue_num_entries && sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue))
+ if (sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue))
break;
- workers_signal_enqueue_work (workers_num, FALSE);
+ workers_signal_enqueue_work (FALSE);
}
/* At this point all the workers have stopped. */
- if (sgen_get_major_collector ()->reset_worker_data) {
- for (i = 0; i < workers_num; ++i)
- sgen_get_major_collector ()->reset_worker_data (workers_data [i].major_collector_data);
- }
-
- g_assert (workers_job_queue_num_entries == 0);
g_assert (sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue));
for (i = 0; i < workers_num; ++i)
g_assert (sgen_gray_object_queue_is_empty (&workers_data [i].private_gray_queue));
gboolean
sgen_workers_all_done (void)
{
- return workers_state.data.state == STATE_NOT_WORKING;
+ return workers_state == STATE_NOT_WORKING;
}
gboolean
sgen_workers_are_working (void)
{
- State state = workers_state;
- return state.data.num_awake > 0 || state.data.num_posted > 0;
+ return workers_state == STATE_WORKING;
}
-gboolean
-sgen_is_worker_thread (MonoNativeThreadId thread)
+void
+sgen_workers_wait (void)
{
- int i;
-
- if (sgen_get_major_collector ()->is_worker_thread && sgen_get_major_collector ()->is_worker_thread (thread))
- return TRUE;
-
- for (i = 0; i < workers_num; ++i) {
- if (workers_data [i].thread == thread)
- return TRUE;
- }
- return FALSE;
+ sgen_thread_pool_idle_wait ();
+ SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done after we wait for them?");
}
SgenSectionGrayQueue*
return &workers_distribute_gray_queue;
}
-void
-sgen_workers_reset_data (void)
-{
- if (sgen_get_major_collector ()->reset_worker_data)
- sgen_get_major_collector ()->reset_worker_data (workers_gc_thread_major_collector_data);
-}
#endif
#ifndef __MONO_SGEN_WORKER_H__
#define __MONO_SGEN_WORKER_H__
+#include "mono/metadata/sgen-thread-pool.h"
+
typedef struct _WorkerData WorkerData;
struct _WorkerData {
- int index;
- MonoNativeThreadId thread;
- void *major_collector_data;
-
SgenGrayQueue private_gray_queue; /* only read/written by worker thread */
};
-typedef void (*JobFunc) (WorkerData *worker_data, void *job_data);
-
-typedef struct _JobQueueEntry JobQueueEntry;
-struct _JobQueueEntry {
- const char *name;
- JobFunc func;
- void *data;
-
- volatile JobQueueEntry *next;
-};
-
void sgen_workers_init (int num_workers);
void sgen_workers_start_all_workers (void);
-gboolean sgen_workers_have_started (void);
void sgen_workers_ensure_awake (void);
void sgen_workers_init_distribute_gray_queue (void);
-void sgen_workers_enqueue_job (const char *name, JobFunc func, void *data);
+void sgen_workers_enqueue_job (SgenThreadPoolJob *job);
void sgen_workers_wait_for_jobs_finished (void);
void sgen_workers_distribute_gray_queue_sections (void);
void sgen_workers_reset_data (void);
void sgen_workers_join (void);
gboolean sgen_workers_all_done (void);
gboolean sgen_workers_are_working (void);
+void sgen_workers_wait (void);
SgenSectionGrayQueue* sgen_workers_get_distribute_section_gray_queue (void);
void sgen_workers_signal_start_nursery_collection_and_wait (void);
MonoVTable *vtable;
socket_class = mono_class_from_name (get_socket_assembly (), "System.Net.Sockets", "Socket");
- ipv4_field = mono_class_get_field_from_name (socket_class, "ipv4Supported");
- ipv6_field = mono_class_get_field_from_name (socket_class, "ipv6Supported");
+ ipv4_field = mono_class_get_field_from_name (socket_class, "ipv4_supported");
+ ipv6_field = mono_class_get_field_from_name (socket_class, "ipv6_supported");
vtable = mono_class_vtable (mono_domain_get (), socket_class);
g_assert (vtable);
mono_runtime_class_init (vtable);
return(recv);
}
-gint32 ves_icall_System_Net_Sockets_Socket_RecvFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *error)
+gint32 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *error)
{
int ret;
guchar *buf;
MonoSafeHandle *safe_handle;
MonoClassField *field;
- field = mono_class_get_field_from_name (sockobj->vtable->klass, "socket");
+ field = mono_class_get_field_from_name (sockobj->vtable->klass, "safe_handle");
safe_handle = ((MonoSafeHandle*) (*(gpointer *)(((char *)sockobj)+field->offset)));
if (safe_handle == NULL)
}
gint
-ves_icall_System_Net_Sockets_Socket_WSAIoctl (SOCKET sock, gint32 code,
+ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code,
MonoArray *input,
MonoArray *output, gint32 *error)
{
}
gboolean
-ves_icall_System_Net_Sockets_Socket_SendFile (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags)
+ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags)
{
HANDLE file;
gint32 error;
extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, MonoObject *sockaddr, gint32 *error);
extern gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error);
extern gint32 ves_icall_System_Net_Sockets_Socket_Receive_array_internal(SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *error);
-extern gint32 ves_icall_System_Net_Sockets_Socket_RecvFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *error);
+extern gint32 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *error);
extern gint32 ves_icall_System_Net_Sockets_Socket_Send_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error);
extern gint32 ves_icall_System_Net_Sockets_Socket_Send_array_internal(SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *error);
extern gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr, gint32 *error);
extern void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *error);
extern void ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal(SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *error);
extern void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error);
-extern int ves_icall_System_Net_Sockets_Socket_WSAIoctl (SOCKET sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *error);
+extern int ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *error);
extern MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list);
extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list);
extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name);
extern MonoBoolean ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode, gint timeout, gint32 *error);
extern void ves_icall_System_Net_Sockets_Socket_Disconnect_internal(SOCKET sock, MonoBoolean reuse, gint32 *error);
-extern gboolean ves_icall_System_Net_Sockets_Socket_SendFile (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags);
+extern gboolean ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags);
void icall_cancel_blocking_socket_operation (MonoThread *thread);
extern void mono_network_init(void);
#ifdef EPOOL_CLOEXEC
threadpool_io->epoll.fd = epoll_create1 (EPOLL_CLOEXEC);
#else
- threadpool_io->epoll.fd = epoll_create1 (256);
+ threadpool_io->epoll.fd = epoll_create (256);
fcntl (threadpool_io->epoll.fd, F_SETFD, FD_CLOEXEC);
#endif
io_status = STATUS_CLEANED_UP;
}
-gboolean
-mono_threadpool_ms_is_io (MonoObject *target, MonoObject *state)
+static gboolean
+is_socket_async_callback (MonoImage *system_image, MonoClass *class)
{
- static MonoClass *socket_class = NULL;
- static MonoClass *socket_async_class = NULL;
- static MonoClass *process_class = NULL;
- static MonoClass *async_read_handler_class = NULL;
- MonoClass *class;
- MonoSocketAsyncResult *sockares;
+ MonoClass *socket_async_callback_class = NULL;
- if (!mono_defaults.system)
- mono_defaults.system = mono_image_loaded ("System");
- if (!mono_defaults.system)
- return FALSE;
- g_assert (mono_defaults.system);
+ socket_async_callback_class = mono_class_from_name (system_image, "System.Net.Sockets", "SocketAsyncCallback");
+ g_assert (socket_async_callback_class);
- if (!socket_class)
- socket_class = mono_class_from_name (mono_defaults.system, "System.Net.Sockets", "Socket");
- g_assert (socket_class);
+ return class == socket_async_callback_class;
+}
+
+static gboolean
+is_async_read_handler (MonoImage *system_image, MonoClass *class)
+{
+ MonoClass *process_class = NULL;
- if (!process_class)
- process_class = mono_class_from_name (mono_defaults.system, "System.Diagnostics", "Process");
+ process_class = mono_class_from_name (system_image, "System.Diagnostics", "Process");
g_assert (process_class);
- class = target->vtable->klass;
+ return class->nested_in && class->nested_in == process_class && strcmp (class->name, "AsyncReadHandler") == 0;
+}
- if (!socket_async_class) {
- if (class->nested_in && class->nested_in == socket_class && strcmp (class->name, "SocketAsyncCall") == 0)
- socket_async_class = class;
- }
+gboolean
+mono_threadpool_ms_is_io (MonoObject *target, MonoObject *state)
+{
+ MonoImage *system_image;
+ MonoSocketAsyncResult *sockares;
- if (!async_read_handler_class) {
- if (class->nested_in && class->nested_in == process_class && strcmp (class->name, "AsyncReadHandler") == 0)
- async_read_handler_class = class;
- }
+ system_image = mono_image_loaded ("System");
+ if (!system_image)
+ return FALSE;
- if (class != socket_async_class && class != async_read_handler_class)
+ if (!is_socket_async_callback (system_image, target->vtable->klass) && !is_async_read_handler (system_image, target->vtable->klass))
return FALSE;
sockares = (MonoSocketAsyncResult*) state;
void
mono_threadpool_io_enqueue_socket_async_result (MonoDomain *domain, MonoSocketAsyncResult *sockares)
{
- static MonoClass *socket_runtime_work_item_class = NULL;
+ MonoImage *system_image;
+ MonoClass *socket_runtime_work_item_class;
MonoSocketRuntimeWorkItem *srwi;
g_assert (sockares);
- if (!mono_defaults.system)
- mono_defaults.system = mono_image_loaded ("System");
- g_assert (mono_defaults.system);
+ system_image = mono_image_loaded ("System");
+ g_assert (system_image);
- if (!socket_runtime_work_item_class)
- socket_runtime_work_item_class = mono_class_from_name (mono_defaults.system, "System.Net.Sockets", "MonoSocketRuntimeWorkItem");
+ socket_runtime_work_item_class = mono_class_from_name (system_image, "System.Net.Sockets", "MonoSocketRuntimeWorkItem");
g_assert (socket_runtime_work_item_class);
srwi = (MonoSocketRuntimeWorkItem*) mono_object_new (domain, socket_runtime_work_item_class);
#include <stdlib.h>
#include <math.h>
+#include <config.h>
+#include <glib.h>
-#ifdef PLATFORM_ANDROID
+#if !defined (HAVE_COMPLEX_H)
#include <../../support/libm/complex.h>
#else
#include <complex.h>
#endif
-#include <config.h>
-#include <glib.h>
-
#include <mono/metadata/class-internals.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/object.h>
{
return worker_request (mono_domain_get ());
}
+
+gboolean G_GNUC_UNUSED
+ves_icall_System_Threading_Microsoft_ThreadPool_PostQueuedCompletionStatus (MonoNativeOverlapped *native_overlapped)
+{
+ /* This copy the behavior of the current Mono implementation */
+ mono_raise_exception (mono_get_exception_not_implemented (NULL));
+ return FALSE;
+}
+
+gboolean G_GNUC_UNUSED
+ves_icall_System_Threading_Microsoft_ThreadPool_BindIOCompletionCallbackNative (gpointer file_handle)
+{
+ /* This copy the behavior of the current Mono implementation */
+ return TRUE;
+}
+
+gboolean G_GNUC_UNUSED
+ves_icall_System_Threading_Microsoft_ThreadPool_IsThreadPoolHosted (void)
+{
+ return FALSE;
+}
gboolean
ves_icall_System_Threading_Microsoft_ThreadPool_RequestWorkerThread (void);
-static gboolean G_GNUC_UNUSED
-ves_icall_System_Threading_Microsoft_ThreadPool_PostQueuedCompletionStatus (MonoNativeOverlapped *native_overlapped)
-{
- /* This copy the behavior of the current Mono implementation */
- mono_raise_exception (mono_get_exception_not_implemented (NULL));
- return FALSE;
-}
+gboolean
+ves_icall_System_Threading_Microsoft_ThreadPool_PostQueuedCompletionStatus (MonoNativeOverlapped *native_overlapped);
-static gboolean G_GNUC_UNUSED
-ves_icall_System_Threading_Microsoft_ThreadPool_BindIOCompletionCallbackNative (gpointer file_handle)
-{
- /* This copy the behavior of the current Mono implementation */
- return TRUE;
-}
+gboolean
+ves_icall_System_Threading_Microsoft_ThreadPool_BindIOCompletionCallbackNative (gpointer file_handle);
-static gboolean G_GNUC_UNUSED
-ves_icall_System_Threading_Microsoft_ThreadPool_IsThreadPoolHosted (void)
-{
- return FALSE;
-}
+gboolean
+ves_icall_System_Threading_Microsoft_ThreadPool_IsThreadPoolHosted (void);
/* Internals */
return klass->image == mono_defaults.corlib;
}
-/*
- * Note that we call it is_socket_type() where 'socket' refers to the image
- * that contains the System.Net.Sockets.Socket type.
-*/
-static gboolean
-is_socket_type (MonoDomain *domain, MonoClass *klass)
-{
- return is_system_type (domain, klass);
-}
-
#define check_type_cached(domain, ASSEMBLY, _class, _namespace, _name, loc) do { \
if (*loc) \
return *loc == _class; \
#define check_corlib_type_cached(domain, _class, _namespace, _name, loc) check_type_cached (domain, corlib, _class, _namespace, _name, loc)
-#define check_socket_type_cached(domain, _class, _namespace, _name, loc) check_type_cached (domain, socket, _class, _namespace, _name, loc)
-
#define check_system_type_cached(domain, _class, _namespace, _name, loc) check_type_cached (domain, system, _class, _namespace, _name, loc)
static gboolean
check_corlib_type_cached (domain, klass, "System.Runtime.Remoting.Messaging", "AsyncResult", &domain->corlib_asyncresult_class);
}
-static gboolean
-is_socket (MonoDomain *domain, MonoClass *klass)
-{
- check_socket_type_cached (domain, klass, "System.Net.Sockets", "Socket", &domain->socket_class);
-}
-
static gboolean
is_socketasyncresult (MonoDomain *domain, MonoClass *klass)
{
- return (klass->nested_in &&
- is_socket (domain, klass->nested_in) &&
- !strcmp (klass->name, "SocketAsyncResult"));
+ static MonoClass *socket_async_result_klass = NULL;
+ check_system_type_cached (domain, klass, "System.Net.Sockets", "SocketAsyncResult", &socket_async_result_klass);
}
static gboolean
is_socketasynccall (MonoDomain *domain, MonoClass *klass)
{
- return (klass->nested_in &&
- is_socket (domain, klass->nested_in) &&
- !strcmp (klass->name, "SocketAsyncCall"));
+ static MonoClass *socket_async_callback_klass = NULL;
+ check_system_type_cached (domain, klass, "System.Net.Sockets", "SocketAsyncCallback", &socket_async_callback_klass);
}
static gboolean
+++ /dev/null
-Mini is the new JIT compiler for Mono.
+++ /dev/null
-* use a pool of MBState structures to speedup monoburg instead of using a
- mempool.
-* the decode tables in the burg-generated could use short instead of int
- (this should save about 1 KB)
-* track the use of ESP, so that we can avoid the x86_lea in the epilog
-
-
-Other Ideas:
-
-* the ORP people avoids optimizations inside catch handlers - just to save
- memory (for example allocation of strings - instead they allocate strings when
- the code is executed (like the --shared option)). But there are only a few
- functions using catch handlers, so I consider this a minor issue.
-
-* some performance critical functions should be inlined. These include:
- - mono_mempool_alloc and mono_mempool_alloc0
- - EnterCriticalSection and LeaveCriticalSection
- - TlsSetValue
- - mono_metadata_row_col
- - mono_g_hash_table_lookup
- - mono_domain_get
-
-* if a function which involves locking is called from another function which
- acquires the same lock, it might be useful to create a separate _inner
- version of the function which does not re-acquire the lock. This is a perf
- win only if the function is called a lot of times, like mono_get_method.
-
-* we can avoid calls to class init trampolines if the are multiple calls to the
- same trampoline in the same basic block. See:
-
- http://bugzilla.ximian.com/show_bug.cgi?id=51096
-
-Usability
----------
-
-* Remove the various optimization list of flags description, have an
- extra --help-optimizations flag.
-
-* Remove the various graph options, have a separate --help-graph for
- that list.
-
-Cleanup
--------
-
-Clean up the usage of the various CEE_/OP_ constants inside the JIT.
-
-Currently, there are the 5 variants for each opcode:
-- CEE_...
-- OP_...
-- OP_I...
-- OP_L...
-- OP_P...
-
-Some opcodes have some variants, while others don't.
-
-They are used as follows:
-- In method_to_ir, CEE_ means the IL opcode ie. without operand size information
-- In the rules inside the .brg files CEE_ means the same as OP_I..., since
- long opcodes were transformed into OP_L.... by method_to_ir.
-- In the IR emitted by the rules inside the .brg files, CEE_ means the same as
- OP_P..., since it is usually generated for pointer manipulation.
-- In mono_arch_emit_opcode, CEE_ means OP_P....
-
-As can be seen above, this is a mess. A proposed solution would be the
-following:
-
-- In method_to_ir, transform CEE_ opcodes into the appropriate OP_I/OP_L
- opcodes.
-- Get rid of the OP_P opcodes, and use the OP_... opcodes instead, since the
- two usually means the same.
-- In the IR emitted by the burg rules, use the OP_... opcodes instead of the
- CEE and OP_P opcodes.
-
-Using these rules would ensure that the same opcode means the same thing in
-all parts of the JIT.
-
-
typedef struct MonoAotStats {
int ccount, mcount, lmfcount, abscount, gcount, ocount, genericcount;
- int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, plt_size;
+ gint64 code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, plt_size;
int methods_without_got_slots, direct_calls, all_calls, llvm_count;
int got_slots, offsets_size;
int got_slot_types [MONO_PATCH_INFO_NONE];
encode_klass_ref (acfg, container->owner.klass, p, &p);
} else {
encode_value (par->gshared_constraint, p, &p);
+ if (par->gshared_constraint) {
+ const char *name = mono_generic_param_name (par);
+
+ if (name) {
+ int len = strlen (name);
+
+ encode_value (len, p, &p);
+ memcpy (p, name, len);
+ p += len;
+ } else {
+ encode_value (0, p, &p);
+ }
+ }
}
} else if (klass->byval_arg.type == MONO_TYPE_PTR) {
encode_value (MONO_AOT_TYPEREF_PTR, p, &p);
get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
{
MonoPltEntry *res;
+ gboolean synchronized = FALSE;
+ static int synchronized_symbol_idx;
if (!is_plt_patch (patch_info))
return NULL;
* wrapper.
*/
res = NULL;
+ synchronized = TRUE;
}
if (!res) {
res->symbol = get_plt_symbol (acfg, res->plt_offset, patch_info);
if (acfg->aot_opts.write_symbols)
res->debug_sym = get_plt_entry_debug_sym (acfg, res->ji, acfg->plt_entry_debug_sym_cache);
+ if (synchronized) {
+ /* Avoid duplicate symbols because we don't cache */
+ res->symbol = g_strdup_printf ("%s_%d", res->symbol, synchronized_symbol_idx);
+ if (res->debug_sym)
+ res->debug_sym = g_strdup_printf ("%s_%d", res->debug_sym, synchronized_symbol_idx);
+ synchronized_symbol_idx ++;
+ }
if (res->debug_sym)
res->llvm_symbol = g_strdup_printf ("%s_%s_llvm", res->symbol, res->debug_sym);
else
p += len + 1;
break;
}
+ case MONO_PATCH_INFO_VIRT_METHOD:
+ encode_klass_ref (acfg, patch_info->data.virt_method->klass, p, &p);
+ encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
+ break;
default:
g_warning ("unable to handle jump info %d", patch_info->type);
g_assert_not_reached ();
// By design aot-runtime decode_exception_debug_info is not able to load sequence point debug data from a file.
// As it is not possible to load debug data from a file its is also not possible to store it in a file.
gboolean method_seq_points_to_file = acfg->aot_opts.gen_seq_points_file &&
- cfg->gen_seq_points && !cfg->gen_seq_points_debug_data;
+ cfg->gen_seq_points && !cfg->gen_sdb_seq_points;
gboolean method_seq_points_to_binary = cfg->gen_seq_points && !method_seq_points_to_file;
emit_exception_debug_info (acfg, cfg, method_seq_points_to_binary);
mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
{
MonoImage *image = ass->image;
- int i, res, all_sizes;
+ int i, res;
+ gint64 all_sizes;
MonoAotCompile *acfg;
char *outfile_name, *tmp_outfile_name, *p;
char llvm_stats_msg [256];
MonoDebugOptions *opt = mini_get_debug_options ();
opt->mdb_optimizations = TRUE;
- opt->gen_seq_points_debug_data = TRUE;
+ opt->gen_sdb_seq_points = TRUE;
if (!mono_debug_enabled ()) {
aot_printerrf (acfg, "The soft-debug AOT option requires the --debug option.\n");
all_sizes = acfg->stats.code_size + acfg->stats.info_size + acfg->stats.ex_info_size + acfg->stats.unwind_info_size + acfg->stats.class_info_size + acfg->stats.got_info_size + acfg->stats.offsets_size + acfg->stats.plt_size;
aot_printf (acfg, "Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n",
- acfg->stats.code_size, acfg->stats.code_size * 100 / all_sizes,
- acfg->stats.info_size, acfg->stats.info_size * 100 / all_sizes,
- acfg->stats.ex_info_size, acfg->stats.ex_info_size * 100 / all_sizes,
- acfg->stats.unwind_info_size, acfg->stats.unwind_info_size * 100 / all_sizes,
- acfg->stats.class_info_size, acfg->stats.class_info_size * 100 / all_sizes,
- acfg->stats.plt_size ? acfg->stats.plt_size : acfg->plt_offset, acfg->stats.plt_size ? acfg->stats.plt_size * 100 / all_sizes : 0,
- acfg->stats.got_info_size, acfg->stats.got_info_size * 100 / all_sizes,
- acfg->stats.offsets_size, acfg->stats.offsets_size * 100 / all_sizes,
+ (int)acfg->stats.code_size, (int)(acfg->stats.code_size * 100 / all_sizes),
+ (int)acfg->stats.info_size, (int)(acfg->stats.info_size * 100 / all_sizes),
+ (int)acfg->stats.ex_info_size, (int)(acfg->stats.ex_info_size * 100 / all_sizes),
+ (int)acfg->stats.unwind_info_size, (int)(acfg->stats.unwind_info_size * 100 / all_sizes),
+ (int)acfg->stats.class_info_size, (int)(acfg->stats.class_info_size * 100 / all_sizes),
+ acfg->stats.plt_size ? (int)acfg->stats.plt_size : (int)acfg->plt_offset, acfg->stats.plt_size ? (int)(acfg->stats.plt_size * 100 / all_sizes) : 0,
+ (int)acfg->stats.got_info_size, (int)(acfg->stats.got_info_size * 100 / all_sizes),
+ (int)acfg->stats.offsets_size, (int)(acfg->stats.offsets_size * 100 / all_sizes),
(int)(acfg->got_offset * sizeof (gpointer)));
aot_printf (acfg, "Compiled: %d/%d (%d%%)%s, No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n",
acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100,
int num = decode_value (p, &p);
gboolean has_container = decode_value (p, &p);
MonoTypeEnum gshared_constraint = 0;
+ char *par_name = NULL;
if (has_container) {
gboolean is_method = decode_value (p, &p);
}
} else {
gshared_constraint = decode_value (p, &p);
+ if (gshared_constraint) {
+ int len = decode_value (p, &p);
+ if (len) {
+ par_name = mono_image_alloc (module->assembly->image, len + 1);
+ memcpy (par_name, p, len);
+ p += len;
+ par_name [len] = '\0';
+ }
+ }
}
t = g_new0 (MonoType, 1);
// FIXME:
par->image = mono_defaults.corlib;
t->data.generic_param = par;
+ if (par_name)
+ ((MonoGenericParamFull*)par)->info.name = par_name;
}
// FIXME: Maybe use types directly to avoid
int atype = decode_value (p, &p);
ref->method = mono_gc_get_managed_allocator_by_type (atype);
- g_assert (ref->method);
+ if (!ref->method) {
+ fprintf (stderr, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
+ exit (1);
+ }
break;
}
case MONO_WRAPPER_WRITE_BARRIER:
ji->data.target = s;
break;
}
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
+
+ info->klass = decode_klass_ref (aot_module, p, &p);
+ g_assert (info->klass);
+ info->method = decode_resolve_method_ref (aot_module, p, &p);
+ g_assert (info->method);
+
+ ji->data.target = info;
+ break;
+ }
default:
g_warning ("unhandled type %d", ji->type);
g_assert_not_reached ();
float_sub: dest:f src1:f src2:f len:6
fmove: dest:f src1:f len:4
move_f_to_i4: dest:i src1:f len:4
-move_i4_to_f: dest:f src1:i len:4
+move_i4_to_f: dest:f src1:i len:8
move_f_to_i8: dest:i src1:f len:4
-move_i8_to_f: dest:f src1:i len:4
+move_i8_to_f: dest:f src1:i len:8
i8const: dest:i len:20
icompare: src1:i src2:i len:4
icompare_imm: src1:i len:18
breakpoints_init ();
suspend_init ();
- mini_get_debug_options ()->gen_seq_points_debug_data = TRUE;
+ mini_get_debug_options ()->gen_sdb_seq_points = TRUE;
/*
* This is needed because currently we don't handle liveness info.
*/
dbg_unlock ();
if (res->domain == NULL) {
- DEBUG_PRINTF (0, "ERR_UNLOADED, id=%d, type=%d.\n", id, type);
+ DEBUG_PRINTF (1, "ERR_UNLOADED, id=%d, type=%d.\n", id, type);
*err = ERR_UNLOADED;
return NULL;
}
if (ss_req->nframes == 0)
ss_req->nframes = nframes;
+
+ if ((ss_req->depth == STEP_DEPTH_OVER) && (!sp && !parent_sp)) {
+ DEBUG_PRINTF (1, "[dbg] No parent frame for step over, transition to step into.\n");
+ /*
+ * This is needed since if we leave managed code, and later return to it, step over
+ * is not going to stop.
+ * This approach is a bit ugly, since we change the step depth, but it only affects
+ * clients who reuse the same step request, and only in this special case.
+ */
+ ss_req->depth = STEP_DEPTH_INTO;
+ }
+
if (ss_req->depth == STEP_DEPTH_OVER) {
/* Need to stop in catch clauses as well */
for (i = 0; i < nframes; ++i) {
g_assert ((code - start) < sizeof(start));
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
return start;
}
g_assert ((code - start) < sizeof(start));
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
return start;
}
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
return start;
}
start = code = mono_global_codeman_reserve (size);
mips_break (code, 0xfd);
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
return start;
}
g_assert ((code - start) <= size);
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
if (info)
*info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
g_assert ((code - start) < size);
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
if (info)
*info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
ppc_break (code);
g_assert ((code - start) <= size);
mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
if (info)
*info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops);
g_assert ((code - start) < SZ_THROW);
+ mono_arch_flush_icache(start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
if (info)
*info = mono_tramp_info_create ("call_filter",
start, code - start, ji,
s390_break (code);
g_assert ((code - start) < size);
+ mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
if (info)
*info = mono_tramp_info_create (corlib ? "throw_corlib_exception"
: (rethrow ? "rethrow_exception"
/* return */
x86_ret (code);
+ mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
return start;
}
g_slist_free (unwind_ops);
}
+ mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
return start;
}
g_slist_free (unwind_ops);
}
+ mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
g_assert ((code - start) < kMaxCodeSize);
return start;
}
g_slist_free (unwind_ops);
}
+ mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
return start;
}
g_slist_free (unwind_ops);
}
+ mono_arch_flush_icache (start, code - start);
+ mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
return start;
}
MyClass<FooStruct2>.foo ();
return 0;
}
+
+ enum AnEnum {
+ A,
+ B
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static string constrained_tostring<T> (T t) {
+ return t.ToString ();
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static bool constrained_equals<T> (T t1, T t2) {
+ var c = EqualityComparer<T>.Default;
+
+ return c.Equals (t1, t2);
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static int constrained_gethashcode<T> (T t) {
+ return t.GetHashCode ();
+ }
+
+ public static int test_0_constrained_partial_sharing () {
+ string s;
+
+ s = constrained_tostring<int> (5);
+ if (s != "5")
+ return 1;
+ s = constrained_tostring<AnEnum> (AnEnum.B);
+ if (s != "B")
+ return 2;
+
+ if (!constrained_equals<int> (1, 1))
+ return 3;
+ if (constrained_equals<int> (1, 2))
+ return 4;
+ if (!constrained_equals<AnEnum> (AnEnum.A, AnEnum.A))
+ return 5;
+ if (constrained_equals<AnEnum> (AnEnum.A, AnEnum.B))
+ return 6;
+
+ int i = constrained_gethashcode<int> (5);
+ if (i != 5)
+ return 7;
+ i = constrained_gethashcode<AnEnum> (AnEnum.B);
+ if (i != 1)
+ return 8;
+ return 0;
+ }
}
#if !MOBILE
} while (0)
#define NEW_SEQ_POINT(cfg,dest,il_offset,intr_loc) do { \
- MONO_INST_NEW ((cfg), (dest), cfg->gen_seq_points_debug_data ? OP_SEQ_POINT : OP_IL_SEQ_POINT); \
+ MONO_INST_NEW ((cfg), (dest), cfg->gen_sdb_seq_points ? OP_SEQ_POINT : OP_IL_SEQ_POINT); \
(dest)->inst_imm = (il_offset); \
(dest)->flags = intr_loc ? MONO_INST_SINGLE_STEP_LOC : 0; \
} while (0)
}
else {
/* Try dead code elimination */
- if ((var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST)) && !(var->flags & MONO_INST_VOLATILE)) {
+ if (!cfg->disable_deadce_vars && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST)) && !(var->flags & MONO_INST_VOLATILE)) {
LIVENESS_DEBUG (printf ("\tdead def of R%d, eliminated\n", ins->dreg));
NULLIFY_INS (ins);
return;
gshared_failure (MonoCompile *cfg, int opcode, const char *file, int line)
{
if (cfg->verbose_level > 2) \
- printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), __LINE__);
+ printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), line);
mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED);
}
if (cfg->compile_llvm)
return FALSE;
#endif
- if (cfg->gen_seq_points_debug_data || cfg->disable_direct_icalls)
+ if (cfg->gen_sdb_seq_points || cfg->disable_direct_icalls)
return FALSE;
return TRUE;
}
return emit_rgctx_fetch (cfg, rgctx, entry);
}
+/*
+ * emit_get_rgctx_virt_method:
+ *
+ * Return data for method VIRT_METHOD for a receiver of type KLASS.
+ */
+static MonoInst*
+emit_get_rgctx_virt_method (MonoCompile *cfg, int context_used,
+ MonoClass *klass, MonoMethod *virt_method, MonoRgctxInfoType rgctx_type)
+{
+ MonoJumpInfoVirtMethod *info;
+ MonoJumpInfoRgctxEntry *entry;
+ MonoInst *rgctx;
+
+ info = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfoVirtMethod));
+ info->klass = klass;
+ info->method = virt_method;
+
+ entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_VIRT_METHOD, info, rgctx_type);
+ rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+
+ return emit_rgctx_fetch (cfg, rgctx, entry);
+}
static MonoInst*
emit_get_rgctx_gsharedvt_method (MonoCompile *cfg, int context_used,
cfg->stat_cil_code_size += header->code_size;
seq_points = cfg->gen_seq_points && cfg->method == method;
-#ifdef PLATFORM_ANDROID
- seq_points &= cfg->method->wrapper_type == MONO_WRAPPER_NONE;
-#endif
if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
/* We could hit a seq point before attaching to the JIT (#8338) */
seq_points = FALSE;
}
- if (cfg->gen_seq_points_debug_data && cfg->method == method) {
+ if (cfg->gen_sdb_seq_points && cfg->method == method) {
minfo = mono_debug_lookup_method (method);
if (minfo) {
int i, n_il_offsets;
gboolean skip_ret = FALSE;
gboolean delegate_invoke = FALSE;
gboolean direct_icall = FALSE;
+ gboolean constrained_partial_call = FALSE;
MonoMethod *cil_method;
CHECK_OPSIZE (5);
if ((constrained_class->byval_arg.type == MONO_TYPE_VAR || constrained_class->byval_arg.type == MONO_TYPE_MVAR) && cfg->generic_sharing_context) {
if (!mini_is_gsharedvt_klass (cfg, constrained_class)) {
g_assert (!cmethod->klass->valuetype);
- if (!mini_type_is_reference (cfg, &constrained_class->byval_arg)) {
- /* FIXME: gshared type constrained to a primitive type */
- GENERIC_SHARING_FAILURE (CEE_CALL);
- }
+ if (!mini_type_is_reference (cfg, &constrained_class->byval_arg))
+ constrained_partial_call = TRUE;
}
}
/*
* We have the `constrained.' prefix opcode.
*/
- if (constrained_class->valuetype && (cmethod->klass == mono_defaults.object_class || cmethod->klass == mono_defaults.enum_class->parent || cmethod->klass == mono_defaults.enum_class)) {
+ if (constrained_partial_call) {
+ gboolean need_box = TRUE;
+
+ /*
+ * The receiver is a valuetype, but the exact type is not known at compile time. This means the
+ * called method is not known at compile time either. The called method could end up being
+ * one of the methods on the parent classes (object/valuetype/enum), in which case we need
+ * to box the receiver.
+ * A simple solution would be to box always and make a normal virtual call, but that would
+ * be bad performance wise.
+ */
+ if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE && cmethod->klass->generic_class) {
+ /*
+ * The parent classes implement no generic interfaces, so the called method will be a vtype method, so no boxing neccessary.
+ */
+ need_box = FALSE;
+ }
+
+ if (need_box) {
+ MonoInst *box_type;
+ MonoBasicBlock *is_ref_bb, *end_bb;
+ MonoInst *nonbox_call;
+
+ /*
+ * Determine at runtime whenever the called method is defined on object/valuetype/enum, and emit a boxing call
+ * if needed.
+ * FIXME: It is possible to inline the called method in a lot of cases, i.e. for T_INT,
+ * the no-box case goes to a method in Int32, while the box case goes to a method in Enum.
+ */
+ addr = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_CODE);
+
+ NEW_BBLOCK (cfg, is_ref_bb);
+ NEW_BBLOCK (cfg, end_bb);
+
+ box_type = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, box_type->dreg, 1);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
+
+ /* Non-ref case */
+ nonbox_call = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
+
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+ /* Ref case */
+ MONO_START_BB (cfg, is_ref_bb);
+ EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &constrained_class->byval_arg, sp [0]->dreg, 0);
+ ins->klass = constrained_class;
+ sp [0] = handle_box (cfg, ins, constrained_class, mono_class_check_context_used (constrained_class), &bblock);
+ ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
+
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+ MONO_START_BB (cfg, end_bb);
+ bblock = end_bb;
+
+ nonbox_call->dreg = ins->dreg;
+ } else {
+ g_assert (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
+ addr = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_CODE);
+ ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
+ }
+ goto call_end;
+ } else if (constrained_class->valuetype && (cmethod->klass == mono_defaults.object_class || cmethod->klass == mono_defaults.enum_class->parent || cmethod->klass == mono_defaults.enum_class)) {
/*
* The type parameter is instantiated as a valuetype,
* but that type doesn't override the method we're
}
/* Add a sequence point for method entry/exit events */
- if (seq_points && cfg->gen_seq_points_debug_data) {
+ if (seq_points && cfg->gen_sdb_seq_points) {
NEW_SEQ_POINT (cfg, ins, METHOD_ENTRY_IL_OFFSET, FALSE);
MONO_ADD_INS (init_localsbb, ins);
NEW_SEQ_POINT (cfg, ins, METHOD_EXIT_IL_OFFSET, FALSE);
#define IS_REX(inst) (((inst) >= 0x40) && ((inst) <= 0x4f))
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
/* Under windows, the calling convention is never stdcall */
#define CALLCONV_IS_STDCALL(call_conv) (FALSE)
#else
#define DEBUG(a) if (cfg->verbose_level > 1) a
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
static AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 };
static AMD64_Reg_No return_regs [] = { AMD64_RAX, AMD64_RDX };
}
}
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
#define FLOAT_PARAM_REGS 4
#else
#define FLOAT_PARAM_REGS 8
break;
case MONO_TYPE_R4:
case MONO_TYPE_R8:
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
class2 = ARG_CLASS_INTEGER;
#else
class2 = ARG_CLASS_SSE;
klass = mono_class_from_mono_type (type);
size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke);
-#ifndef HOST_WIN32
+#ifndef TARGET_WIN32
if (!sig->pinvoke && ((is_return && (size == 8)) || (!is_return && (size <= 16)))) {
/* We pass and return vtypes of size 8 in a register */
} else if (!sig->pinvoke || (size == 0) || (size > 16)) {
g_assert (info);
g_assert (fields);
-#ifndef HOST_WIN32
+#ifndef TARGET_WIN32
if (info->native_size > 16) {
ainfo->offset = *stack_size;
*stack_size += ALIGN_TO (info->native_size, 8);
gr = 0;
fr = 0;
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
/* Reserve space where the callee can save the argument registers */
stack_size = 4 * sizeof (mgreg_t);
#endif
ArgInfo *ainfo = &cinfo->args [sig->hasthis + i];
MonoType *ptype;
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
/* The float param registers and other param registers must be the same index on Windows x64.*/
if (gr > fr)
fr = gr;
#ifndef __native_client_codegen__
regs = g_list_prepend (regs, (gpointer)AMD64_R15);
#endif
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
regs = g_list_prepend (regs, (gpointer)AMD64_RDI);
regs = g_list_prepend (regs, (gpointer)AMD64_RSI);
#endif
}
}
- if (cfg->gen_seq_points_debug_data) {
+ if (cfg->gen_sdb_seq_points) {
MonoInst *ins;
if (cfg->compile_aot) {
if (cfg->method->save_lmf) {
cfg->lmf_ir = TRUE;
-#if !defined(HOST_WIN32)
+#if !defined(TARGET_WIN32)
if (mono_get_lmf_tls_offset () != -1 && !optimize_for_xen)
cfg->lmf_ir_mono_lmf = TRUE;
#endif
static inline guint8*
emit_call (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointer data, gboolean win64_adjust_stack)
{
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (win64_adjust_stack)
amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 32);
#endif
code = emit_call_body (cfg, code, patch_type, data);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (win64_adjust_stack)
amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 32);
#endif
int sreg = tree->sreg1;
int need_touch = FALSE;
-#if defined(HOST_WIN32)
+#if defined(TARGET_WIN32)
need_touch = TRUE;
#elif defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
if (!tree->flags & MONO_INST_INIT)
guint8*
mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset)
{
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (tls_offset < 64) {
x86_prefix (code, X86_GS_PREFIX);
amd64_mov_reg_mem (code, dreg, (tls_offset * 8) + 0x1480, 8);
static guint8*
amd64_emit_tls_set (guint8 *code, int sreg, int tls_offset)
{
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
g_assert_not_reached ();
#elif defined(__APPLE__)
x86_prefix (code, X86_GS_PREFIX);
amd64_emit_tls_set_reg (guint8 *code, int sreg, int offset_reg)
{
/* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
g_assert_not_reached ();
#elif defined(__APPLE__)
x86_prefix (code, X86_GS_PREFIX);
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
mono_emit_unwind_op_offset (cfg, code, AMD64_RBP, - cfa_offset);
async_exc_point (code);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
mono_arch_unwindinfo_add_push_nonvol (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP);
#endif
/* These are handled automatically by the stack marking code */
amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof(mgreg_t));
mono_emit_unwind_op_def_cfa_reg (cfg, code, AMD64_RBP);
async_exc_point (code);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
mono_arch_unwindinfo_add_set_fpreg (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP);
#endif
}
/* Allocate stack frame */
if (alloc_size) {
/* See mono_emit_stack_alloc */
-#if defined(HOST_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
+#if defined(TARGET_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
guint32 remaining_size = alloc_size;
/*FIXME handle unbounded code expansion, we should use a loop in case of more than X interactions*/
guint32 required_code_size = ((remaining_size / 0x1000) + 1) * 10; /*10 is the max size of amd64_alu_reg_imm + amd64_test_membase_reg*/
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
}
async_exc_point (code);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (cfg->arch.omit_fp)
mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, 0x1000);
#endif
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
async_exc_point (code);
}
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (cfg->arch.omit_fp)
mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, remaining_size);
#endif
}
}
- if (cfg->gen_seq_points_debug_data) {
+ if (cfg->gen_sdb_seq_points) {
MonoInst *info_var = cfg->arch.seq_point_info_var;
/* Initialize seq_point_info_var */
/* We have to shift the arguments left */
amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
for (i = 0; i < param_count; ++i) {
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (i < 3)
amd64_mov_reg_reg (code, param_regs [i], param_regs [i + 1], 8);
else
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
#define PARAM_REGS 4
#else
#define PARAM_REGS 6
#define MONO_ARCH_NOMAP32BIT 1
#endif
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
#define MONO_AMD64_ARG_REG1 AMD64_RCX
#define MONO_AMD64_ARG_REG2 AMD64_RDX
#define MONO_AMD64_ARG_REG3 AMD64_R8
extern MonoBreakpointInfo mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
void mono_arch_unwindinfo_add_push_nonvol (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
void mono_arch_unwindinfo_add_set_fpreg (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg );
}
}
- if (cfg->gen_seq_points_debug_data) {
+ if (cfg->gen_sdb_seq_points) {
if (cfg->soft_breakpoints) {
MonoInst *ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
ins->flags |= MONO_INST_VOLATILE;
if (sigctx)
mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
else
-#if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
+#if defined(MONO_CROSS_COMPILE)
+ ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
+#elif MONO_ARCH_HAS_MONO_CONTEXT
MONO_CONTEXT_GET_CURRENT (ctx->ctx);
#else
g_error ("Use a null sigctx requires a working mono-context");
#include "mini.h"
-//#define ALLOW_PARTIAL_SHARING TRUE
-#define ALLOW_PARTIAL_SHARING FALSE
+#define ALLOW_PARTIAL_SHARING TRUE
+//#define ALLOW_PARTIAL_SHARING FALSE
#if 0
#define DEBUG(...) __VA_ARGS__
g_assert (mono_error_ok (&error));
return isig;
}
+ case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
+ case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
+ MonoJumpInfoVirtMethod *info = data;
+ MonoJumpInfoVirtMethod *res;
+ MonoType *t;
+ MonoDomain *domain = mono_domain_get ();
+ MonoError error;
+
+ // FIXME: Temporary
+ res = mono_domain_alloc0 (domain, sizeof (MonoJumpInfoVirtMethod));
+ t = mono_class_inflate_generic_type (&info->klass->byval_arg, context);
+ res->klass = mono_class_from_mono_type (t);
+ mono_metadata_free_type (t);
+ res->method = mono_class_inflate_generic_method_checked (info->method, context, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
+ return res;
+ }
default:
g_assert_not_reached ();
}
addr = mono_compile_method (data);
return mini_add_method_trampoline (NULL, data, addr, mono_method_needs_static_rgctx_invoke (data, FALSE), FALSE);
}
+ case MONO_RGCTX_INFO_VIRT_METHOD_CODE: {
+ MonoJumpInfoVirtMethod *info = data;
+ MonoClass *iface_class = info->method->klass;
+ MonoMethod *method;
+ int ioffset, slot;
+ gpointer addr;
+
+ mono_class_setup_vtable (info->klass);
+ // FIXME: Check type load
+ if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ ioffset = mono_class_interface_offset (info->klass, iface_class);
+ g_assert (ioffset != -1);
+ } else {
+ ioffset = 0;
+ }
+ slot = mono_method_get_vtable_slot (info->method);
+ g_assert (slot != -1);
+ g_assert (info->klass->vtable);
+ method = info->klass->vtable [ioffset + slot];
+
+ addr = mono_compile_method (method);
+ return mini_add_method_trampoline (NULL, method, addr, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE);
+ }
+ case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
+ MonoJumpInfoVirtMethod *info = data;
+ MonoClass *iface_class = info->method->klass;
+ MonoMethod *method;
+ MonoClass *impl_class;
+ int ioffset, slot;
+
+ mono_class_setup_vtable (info->klass);
+ // FIXME: Check type load
+ if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ ioffset = mono_class_interface_offset (info->klass, iface_class);
+ g_assert (ioffset != -1);
+ } else {
+ ioffset = 0;
+ }
+ slot = mono_method_get_vtable_slot (info->method);
+ g_assert (slot != -1);
+ g_assert (info->klass->vtable);
+ method = info->klass->vtable [ioffset + slot];
+
+ impl_class = method->klass;
+ if (MONO_TYPE_IS_REFERENCE (&impl_class->byval_arg))
+ return GUINT_TO_POINTER (1);
+ else if (mono_class_is_nullable (impl_class))
+ return GUINT_TO_POINTER (2);
+ else
+ return GUINT_TO_POINTER (0);
+ }
#ifndef DISABLE_REMOTING
case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
return mono_compile_method (mono_marshal_get_remoting_invoke_with_check (data));
case MONO_RGCTX_INFO_BZERO: return "BZERO";
case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX: return "NULLABLE_CLASS_BOX";
case MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX: return "NULLABLE_CLASS_UNBOX";
+ case MONO_RGCTX_INFO_VIRT_METHOD_CODE: return "VIRT_METHOD_CODE";
+ case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: return "VIRT_METHOD_BOX_TYPE";
default:
return "<UNKNOWN RGCTX INFO TYPE>";
}
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT:
case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI:
return data1 == data2;
+ case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
+ case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
+ MonoJumpInfoVirtMethod *info1 = data1;
+ MonoJumpInfoVirtMethod *info2 = data2;
+
+ return info1->klass == info2->klass && info1->method == info2->method;
+ }
default:
g_assert_not_reached ();
}
*/
if (t->type == MONO_TYPE_U1 || t->type == MONO_TYPE_U2 || t->type == MONO_TYPE_CHAR || t->type == MONO_TYPE_BOOLEAN)
v = LLVMBuildZExt (ctx->builder, v, LLVMInt32Type (), "");
+ else if (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2)
+ v = LLVMBuildSExt (ctx->builder, v, LLVMInt32Type (), "");
else if (t->type == MONO_TYPE_U8)
v = LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), "");
}
* These symbols are not really used, the clause_index is embedded into the EH tables generated by DwarfMonoException in LLVM.
*/
LLVMSetLinkage (type_info, LLVMInternalLinkage);
-
-#ifdef TARGET_ARM
- // test_0_invalid_unbox_arrays () fails
- LLVM_FAILURE (ctx, "aot+clauses");
-#endif
} else {
/*
* After the cfg mempool is freed, the type info will point to stale memory,
}
emit_handler_start (ctx, bb, builder);
+ CHECK_FAILURE (ctx);
builder = ctx->builder;
}
//memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
break;
}
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info;
+ MonoJumpInfoVirtMethod *oinfo;
+
+ oinfo = patch_info->data.virt_method;
+ info = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
+ res->data.virt_method = info;
+ memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
+ break;
+ }
default:
break;
}
return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->virtual;
case MONO_PATCH_INFO_LDSTR_LIT:
return g_str_hash (ji->data.target);
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info = ji->data.virt_method;
+
+ return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
+ }
default:
printf ("info type: %d\n", ji->type);
mono_print_ji (ji); printf ("\n");
return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->virtual == ji2->data.del_tramp->virtual;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
return ji1->data.index == ji2->data.index;
+ case MONO_PATCH_INFO_VIRT_METHOD:
+ return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
default:
if (ji1->data.target != ji2->data.target)
return 0;
slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
break;
}
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info;
+ MonoJumpInfoVirtMethod *oinfo = entry->data->data.virt_method;
+
+ info = g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
+ memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
+ break;
+ }
default:
g_assert_not_reached ();
break;
else if (!strcmp (arg, "explicit-null-checks"))
debug_options.explicit_null_checks = TRUE;
else if (!strcmp (arg, "gen-seq-points"))
- debug_options.gen_seq_points_debug_data = TRUE;
+ debug_options.gen_sdb_seq_points = TRUE;
else if (!strcmp (arg, "gen-compact-seq-points"))
debug_options.gen_seq_points_compact_data = TRUE;
else if (!strcmp (arg, "init-stacks"))
if (!trampoline) {
gpointer tramp;
- MonoTrampInfo *info;
if (mono_aot_only) {
tramp = mono_aot_get_trampoline ("sdb_single_step_trampoline");
} else {
#ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
+ MonoTrampInfo *info;
tramp = mono_arch_create_sdb_trampoline (TRUE, &info, FALSE);
mono_tramp_info_register (info);
#else
if (!trampoline) {
gpointer tramp;
- MonoTrampInfo *info;
if (mono_aot_only) {
tramp = mono_aot_get_trampoline ("sdb_breakpoint_trampoline");
} else {
#ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
+ MonoTrampInfo *info;
tramp = mono_arch_create_sdb_trampoline (FALSE, &info, FALSE);
mono_tramp_info_register (info);
#else
if (cfg->opt & MONO_OPT_PEEPHOLE)
mono_arch_peephole_pass_2 (cfg, bb);
- if (cfg->gen_seq_points && !cfg->gen_seq_points_debug_data)
+ if (cfg->gen_seq_points && !cfg->gen_sdb_seq_points)
bb_deduplicate_op_il_seq_points (cfg, bb);
}
#endif
/* Allocate the code into a separate memory pool so it can be freed */
cfg->dynamic_info = g_new0 (MonoJitDynamicMethodInfo, 1);
- cfg->dynamic_info->code_mp = mono_code_manager_new_dynamic ();
+ cfg->dynamic_info->code_mp = mono_code_manager_new_dynamic (cfg->thunk_area);
mono_domain_lock (cfg->domain);
mono_dynamic_code_hash_insert (cfg->domain, cfg->method, cfg->dynamic_info);
mono_domain_unlock (cfg->domain);
cfg->full_aot = full_aot;
cfg->skip_visibility = method->skip_visibility;
cfg->orig_method = method;
- cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_seq_points_debug_data;
- cfg->gen_seq_points_debug_data = debug_options.gen_seq_points_debug_data;
+ cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_sdb_seq_points;
+ cfg->gen_sdb_seq_points = debug_options.gen_sdb_seq_points;
+
+#ifdef PLATFORM_ANDROID
+ if (cfg->method->wrapper_type != MONO_WRAPPER_NONE) {
+ /* FIXME: Why is this needed */
+ cfg->gen_seq_points = FALSE;
+ cfg->gen_sdb_seq_points = FALSE;
+ }
+#endif
cfg->explicit_null_checks = debug_options.explicit_null_checks;
cfg->soft_breakpoints = debug_options.soft_breakpoints;
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 110
+#define MONO_AOT_FILE_VERSION 112
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
/* The address of Nullable<T>.Box () */
MONO_RGCTX_INFO_NULLABLE_CLASS_BOX,
MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX,
+ /* MONO_PATCH_INFO_VCALL_METHOD */
+ MONO_RGCTX_INFO_VIRT_METHOD_CODE,
+ /*
+ * MONO_PATCH_INFO_VCALL_METHOD
+ * Same as MONO_RGCTX_INFO_CLASS_BOX_TYPE, but for the class
+ * which implements the method.
+ */
+ MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE
} MonoRgctxInfoType;
typedef struct _MonoRuntimeGenericContextInfoTemplate {
typedef struct MonoJumpInfoGSharedVtCall MonoJumpInfoGSharedVtCall;
+/*
+ * Represents the method which is called when a virtual call is made to METHOD
+ * on a receiver of type KLASS.
+ */
+typedef struct {
+ /* Receiver class */
+ MonoClass *klass;
+ /* Virtual method */
+ MonoMethod *method;
+} MonoJumpInfoVirtMethod;
+
typedef struct MonoJumpInfo MonoJumpInfo;
struct MonoJumpInfo {
MonoJumpInfo *next;
MonoGSharedVtMethodInfo *gsharedvt_method;
MonoMethodSignature *sig;
MonoDelegateClassMethodPair *del_tramp;
+ /* MONO_PATCH_INFO_VIRT_METHOD */
+ MonoJumpInfoVirtMethod *virt_method;
} data;
};
-/* Contains information describing an rgctx entry */
+/*
+ * Contains information for computing the
+ * property given by INFO_TYPE of the runtime
+ * object described by DATA.
+ */
struct MonoJumpInfoRgctxEntry {
MonoMethod *method;
gboolean in_mrgctx;
guint keep_cil_nops : 1;
guint gen_seq_points : 1;
/* Generate seq points for use by the debugger */
- guint gen_seq_points_debug_data : 1;
+ guint gen_sdb_seq_points : 1;
guint explicit_null_checks : 1;
guint compute_gc_maps : 1;
guint soft_breakpoints : 1;
GHashTable *token_info_hash;
MonoCompileArch arch;
guint32 inline_depth;
+ /* Size of memory reserved for thunks */
+ int thunk_area;
guint32 exception_type; /* MONO_EXCEPTION_* */
guint32 exception_data;
char* exception_message;
* Whenever data such as next sequence points and flags is required.
* Next sequence points and flags are required by the debugger agent.
*/
- gboolean gen_seq_points_debug_data;
+ gboolean gen_sdb_seq_points;
gboolean gen_seq_points_compact_data;
gboolean explicit_null_checks;
/*
+++ /dev/null
-;; -*- Prcs -*-
-(Created-By-Prcs-Version 1 3 2)
-(Project-Description "The mono SSA-based JIT.")
-(Project-Version mini 0 3)
-(Parent-Version mini 0 2)
-(Version-Log "")
-(New-Version-Log "")
-(Checkin-Time "Sat, 21 Sep 2002 12:11:29 +0200")
-(Checkin-Login lupus)
-(Populate-Ignore ())
-(Project-Keywords)
-(Files
-;; This is a comment. Fill in files here.
-;; For example: (prcs/checkout.cc ())
-
-;; Files added by populate at Sat, 08 Jun 2002 17:27:56 +0200,
-;; to version 0.0(w), by lupus:
-
- (regalloc.c (mini/0_regalloc.c 1.1 664))
- (cfold.c (mini/1_cfold.c 1.1 664))
- (mini-x86.c (mini/2_mini-x86.c 1.2 664))
- (mini.h (mini/3_mini.h 1.3 664))
- (makefile (mini/4_makefile 1.3 664))
- (test.cs (mini/5_test.cs 1.1 664))
- (mini.c (mini/6_mini.c 1.3 664))
-)
-(Merge-Parents)
-(New-Merge-Parents)
PATCH_INFO(METHOD_CODE_SLOT, "method_code_slot")
PATCH_INFO(LDSTR_LIT, "ldstr_lit")
PATCH_INFO(GC_NURSERY_START, "gc_nursery_start")
+PATCH_INFO(VIRT_METHOD, "virt_method")
PATCH_INFO(NONE, "none")
GSList **next = NULL;
SeqPoint* seq_points;
GByteArray* array;
- gboolean has_debug_data = cfg->gen_seq_points_debug_data;
+ gboolean has_debug_data = cfg->gen_sdb_seq_points;
if (!cfg->seq_points)
return;
without a OP_LDADDR.
*/
-#ifdef MONO_ARCH_SIMD_INTRINSICS
+#if defined (MONO_ARCH_SIMD_INTRINSICS)
+
+#if defined (DISABLE_JIT)
+
+void
+mono_simd_intrinsics_init (void)
+{
+}
+
+#else
//#define IS_DEBUG_ON(cfg) (0)
return NULL;
}
-#endif
+#endif /* DISABLE_JIT */
+#endif /* MONO_ARCH_SIMD_INTRINSICS */
72, 73, 74, 75, 76, 77, 78, 79,
};
#elif defined (TARGET_X86)
-#ifdef __APPLE__
/*
- * LLVM seems to generate unwind info where esp is encoded as 5, and ebp as 4, ie see this line:
- * def ESP : RegisterWithSubRegs<"esp", [SP]>, DwarfRegNum<[-2, 5, 4]>;
- * in lib/Target/X86/X86RegisterInfo.td in the llvm sources.
+ * ebp and esp are swapped:
+ * http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-January/003101.html
*/
static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 5, 4, 6, 7, 8 };
-#else
-static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
-#endif
/* + 1 is for IP */
#define NUM_REGS X86_NREG + 1
#define DWARF_DATA_ALIGN (-4)
vtune_lib = libmono-profiler-vtune.la
endif
-lib_LTLIBRARIES = libmono-profiler-cov.la libmono-profiler-aot.la libmono-profiler-iomap.la libmono-profiler-log.la $(vtune_lib)
+lib_LTLIBRARIES = libmono-profiler-aot.la libmono-profiler-iomap.la libmono-profiler-log.la $(vtune_lib)
if PLATFORM_DARWIN
libmono_profiler_log_la_LDFLAGS = -Wl,-undefined -Wl,suppress -Wl,-flat_namespace
-libmono_profiler_cov_la_LDFLAGS = -Wl,-undefined -Wl,suppress -Wl,-flat_namespace
endif
if PLATFORM_ANDROID
libmono_profiler_log_la_LDFLAGS = -avoid-version
LIBMONO=$(top_builddir)/mono/mini/libmonosgen-$(API_VER).la
endif
-libmono_profiler_cov_la_SOURCES = mono-cov.c
-libmono_profiler_cov_la_LIBADD = $(LIBMONO) $(GLIB_LIBS) $(LIBICONV)
libmono_profiler_aot_la_SOURCES = mono-profiler-aot.c
libmono_profiler_aot_la_LIBADD = $(LIBMONO) $(GLIB_LIBS) $(LIBICONV)
-#libmono_profiler_logging_la_SOURCES = mono-profiler-logging.c
-#libmono_profiler_logging_la_LIBADD = $(LIBMONO) $(GLIB_LIBS) $(LIBICONV)
libmono_profiler_iomap_la_SOURCES = mono-profiler-iomap.c
libmono_profiler_iomap_la_LIBADD = $(LIBMONO) $(GLIB_LIBS) $(LIBICONV)
libmono_profiler_log_la_SOURCES = proflog.c
check-local: testlog
endif
-EXTRA_DIST=utils.c utils.h proflog.h log-profiler.txt perf_event.h \
+EXTRA_DIST=utils.c utils.h proflog.h perf_event.h \
$(PLOG_TESTS_SRC) ptestrunner.pl
+++ /dev/null
-# The Mono log profiler
-
-The Mono *log* profiler can be used to collect a lot of information about
-a program running in the Mono runtime. This data can be used (both while the process
-is running and later) to do analyses of the program behaviour, determine
-resource usage, performance issues or even look for particular execution patterns.
-
-This is accomplished by logging the events provided by the Mono runtime through the
-profiling interface and periodically writing them to a file which can be later
-inspected with the command line *mprof-report* program or with a GUI (not developed yet).
-
-The events collected include (among others):
-
-* method enter and leave
-* object allocation
-* garbage collection
-* JIT compilation
-* metadata loading
-* lock contention
-* exceptions
-
-In addition, the profiler can periodically collect info about all the objects
-present in the heap at the end of a garbage collection (this is called heap shot
-and currently implemented only for the sgen garbage collector).
-Another available profiler mode is the *sampling* or *statistical* mode:
-periodically the program is sampled and the information about what the program was
-busy with is saved. This allows to get information about the program behaviour
-without degrading its performance too much (usually less than 10%).
-
-## Basic profiler usage
-
-The simpler way to use the profiler is the following:
-
-`mono --profile=log program.exe`
-
-At the end of the execution the file *output.mlpd* will be found in the current
-directory. A summary report of the data can be printed by running:
-
-`mprof-report output.mlpd`
-
-With this invocation a huge amount of data is collected about the program execution
-and collecting and saving this data can significantly slow down program execution.
-If saving the profiling data is not needed, a report can be generated directly with:
-
-`mono --profile=log:report program.exe`
-
-If the information about allocations is not of interest, it can be excluded:
-
-`mono --profile=log:noalloc program.exe`
-
-On the other hand, if method call timing is not important, while allocations are,
-the needed info can be gathered with:
-
-`mono --profile=log:nocalls program.exe`
-
-You will still be able to inspect information about the sequence of calls that lead
-to each allocation because at each object allocation a stack trace is collected if
-full enter/leave information is not available.
-
-To periodically collect heap shots (and exclude method and allocation events) use the
-following options (making sure you run with the sgen garbage collector):
-
-`mono --gc=sgen --profile=log:heapshot program.exe`
-
-To perform a sampling profiler run, use the *sample* option:
-
-`mono --profile=log:sample program.exe`
-
-## Profiler option documentation
-
-By default the *log* profiler will gather all the events provided by the Mono runtime
-and write them to a file named *output.mlpd*. When no option is specified, it
-is equivalent to using:
-
-`--profile=log:calls,alloc,output=output.mlpd,maxframes=8,calldepth=100`
-
-The following options can be used to modify this default behaviour. Each option
-is separated from the next by a `,` character, with no spaces and all the options
-are included after the *log:* profile module specifier.
-
-* *help*: display concise help info about each available option
-
-* *[no]alloc*: *noalloc* disables collecting object allocation info, *alloc* enables
-it if it was disabled by another option like *heapshot*.
-
-* *[no]calls*: *nocalls* disables collecting method enter and leave events. When this
-option is used at each object allocation and at some other events (like lock contentions
-and exception throws) a stack trace is collected by default. See the *maxframes* option to
-control this behaviour. *calls* enables method enter/leave events if they were disabled
-by another option like *heapshot*.
-
-* *heapshot[=MODE]*: collect heap shot data at each major collection. The frequency of the
-heap shots can be changed with the *MODE* parameter. When this option is used
-allocation events and method enter/leave events are not recorded by default: if they
-are needed, they need to be enabled explicitly.
-The optional parameter *MODE* can modify the default heap shot frequency.
-heapshot can be used multiple times with different modes: in that case a heap shot is
-taken if either of the conditions are met.
-MODE can be one of:
- * *NUM*ms: perform a heap shot if at least *NUM* milliseconds passed since
- the last one.
- * *NUM*gc: perform a heap shot every *NUM* major garbage collections
- * *ondemand*: perform a heap shot when such a command is sent to the
- control port
-
-* *sample[=TYPE[/FREQ]]*: collect statistical samples of the program behaviour. The
-default is to collect a 1000 times per second the instruction pointer. This is
-equivalent to the value "cycles/1000" for *TYPE*. On some systems, like with recent
-Linux kernels, it is possible to cause the sampling to happen for other events
-provided by the performance counters of the cpu. In this case, *TYPE* can be one of:
- * *cycles*: processor cycles
- * *instr*: executed instructions
- * *cacherefs*: cache references
- * *cachemiss*: cache misses
- * *branches*: executed branches
- * *branchmiss*: mispredicted branches
-
-* *time=TIMER*: use the TIMER timestamp mode. TIMER can have the following values:
- * *fast*: a usually faster but possibly more inaccurate timer
-
-* *maxframes=NUM*: when a stack trace needs to be performed, collect *NUM* frames
-at the most. The default is 8.
-
-* *calldepth=NUM*: ignore method enter/leave events when the call chain depth is
-bigger than NUM.
-
-* *zip*: automatically compress the output data in gzip format.
-
-* *output=OUTSPEC*: instead of writing the profiling data to the output.mlpd file,
-substitute *%p* in *OUTSPEC* with the current process id and *%t* with the current
-date and time, then do according to *OUTSPEC*:
- * if *OUTSPEC* begins with a *|* character, execute the rest as a program
- and feed the data to its standard input
- * if *OUTSPEC* begins with a *-* character, use the rest of OUTSPEC as
- the filename, but force overwrite any existing file by that name
- * if *OUTSPEC* begins with a *#* character, use the rest of OUTSPEC as a
- file descriptor and feed the data to it.
- * otherwise write the data the the named file: note that is a file by that
- name already exists, a warning is issued and profiling is disabled.
-
-* *report*: the profiling data is sent to mprof-report, which will print a summary
-report. This is equivalent to the option: `output=mprof-report -`. If the *output*
-option is specified as well, the report will be written to the output file instead of
-the console.
-
-* *port=PORT*: specify the tcp/ip port to use for the listening command server.
-Currently not available for windows.
-This server is started for example when heapshot=ondemand is used: it will read
-commands line by line. The following commands are available:
- * *heapshot*: perform a heapshot as soon as possible
-
-## Analyzing the profile data
-
-Currently there is a command line program (*mprof-report*) to analyze the
-data produced by the profiler. This is ran automatically when the *report*
-profiler option is used.
-Simply run:
-
-`mprof-report output.mlpd`
-
-to see a summary report of the data included in the file.
-
-### Trace information for events
-
-Often it is important for some events, like allocations, lock contention
-and exception throws to know where they happened. Or we may want to see
-what sequence of calls leads to a particular method invocation. To see this
-info invoke mprof-report as follows:
-
-`mprof-report --traces output.mlpd`
-
-The maximum number of methods in each stack trace can be specified with the
-*--maxframes=NUM* option:
-
-`mprof-report --traces --maxframes=4 output.mlpd`
-
-The stack trace info will be available if method enter/leave events have been
-recorded or if stack trace collection wasn't explicitly disabled with the
-*maxframes=0* profiler option. Note that the profiler will collect up to 8
-frames by default at specific events when the *nocalls* option is used, so
-in that case, if more stack frames are required in mprof-report, a bigger
-value for maxframes when profiling must be used, too.
-
-The *--traces* option also controls the reverse reference feature in the heapshot
-report: for each class it reports how many references to objects of that class
-come from other classes.
-
-### Sort order for methods and allocations
-
-When a list of methods is printed the default sort order is based on the total time
-spent in the method. This time is wall clock time (that is, it includes the time
-spent, for example, in a sleep call, even if actual cpu time would be basically 0).
-Also, if the method has been ran on different threads, the time will be a sum
-of the time used in each thread.
-
-To change the sort order, use the option:
-
-`--method-sort=MODE`
-
-where *MODE* can be:
-
-* *self*: amount of time spent in the method itself and not in its callees
-* *calls*: the number of method invocations
-* *total*: the total time spent in the method.
-
-Object allocation lists are sorted by default depending on the total amount
-of bytes used by each type.
-
-To change the sort order of object allocations, use the option:
-
-`--alloc-sort=MODE`
-
-where *MODE* can be:
-
-* *count*: the number of allocated objects of the given type
-* *bytes*: the total number of bytes used by objects of the given type
-
-### Selecting what data to report
-
-The profiler by default collects data about many runtime subsystems and mprof-report
-prints a summary of all the subsystems that are found in the data file. It is possible
-to tell mprof-report to only show information about some of them with the following
-option:
-
-`--reports=R1[,R2...]`
-
-where the report names R1, R2 etc. can be:
-
-* *header*: information about program startup and profiler version
-* *jit*: JIT compiler information
-* *sample*: statistical sampling information
-* *gc*: garbage collection information
-* *alloc*: object allocation information
-* *call*: method profiling information
-* *metadata*: metadata events like image loads
-* *exception*: exception throw and handling information
-* *monitor*: lock contention information
-* *thread*: thread information
-* *heapshot*: live heap usage at heap shots
-
-It is possible to limit some of the data displayed to a timeframe of the
-program execution with the option:
-
-`--time=FROM-TO`
-
-where *FROM* and *TO* are seconds since application startup (they can be
-floating point numbers).
-
-Another interesting option is to consider only events happening on a particular
-thread with the following option:
-
-`--thread=THREADID`
-
-where *THREADID* is one of the numbers listed in the thread summary report
-(or a thread name when present).
-
-By default long lists of methods or other information like object allocations
-are limited to the most important data. To increase the amount of information
-printed you can use the option:
-
-`--verbose`
-
-### Track individual objects
-
-Instead of printing the usual reports from the profiler data, it is possible
-to track some interesting information about some specific object addresses.
-The objects are selected based on their address with the *--track* option as follows:
-
-`--track=0xaddr1[,0xaddr2,...]`
-
-The reported info (if available in the data file), will be class name, size,
-creation time, stack trace of creation (with the *--traces* option), etc.
-If heapshot data is available it will be possible to also track what other objects
-reference one of the listed addresses.
-
-The object addresses can be gathered either from the profiler report in some
-cases (like in the monitor lock report), from the live application or they can
-be selected with the *--find=FINDSPEC* option. FINDSPEC can be one of the
-following:
-
-* *S:SIZE*: where the object is selected if it's size is at least *SIZE*
-* *T:NAME*: where the object is selected if *NAME* partially matches its class name
-
-This option can be specified multiple times with one of the different kinds
-of FINDSPEC. For example, the following:
-
-`--find=S:10000 --find=T:Byte[]`
-
-will find all the byte arrays that are at least 10000 bytes in size.
-
-Note that with a moving garbage collector the object address can change, so
-you may need to track the changed address manually. It can also happen that
-multiple objects are allocated at the same address, so the output from this
-option can become large.
-
-### Saving a profiler report
-
-By default mprof-report will print the summary data to the console.
-To print it to a file, instead, use the option:
-
-`--out=FILENAME`
-
-## Dealing with profiler slowness
-
-If the profiler needs to collect lots of data, the execution of the program will
-slow down significantly, usually 10 to 20 times slower. There are several
-ways to reduce the impact of the profiler on the program execution.
-
-### Use the statistical sampling mode
-
-Statistical sampling allows executing a program under the profiler with minimal
-performance overhead (usually less than 10%). This mode allows checking where
-the program is spending most of it's execution time without significantly
-perturbing its behaviour.
-
-### Collect less data
-
-Collecting method enter/leave events can be very expensive, especially in programs
-that perform many millions of tiny calls. The profiler option *nocalls* can be
-used to avoid collecting this data or it can be limited to only a few call levels
-with the *calldepth* option.
-
-Object allocation information is expensive as well, though much less than
-method enter/leave events. If it's not needed, it can be skipped with the
-*noalloc* profiler option. Note that when method enter/leave events are
-discarded, by default stack traces are collected at each allocation and this
-can be expensive as well. The impact of stack trace information can be reduced
-by setting a low value with the *maxframes* option or by eliminating them
-completely, by setting it to 0.
-
-The other major source of data is the heapshot profiler option: especially
-if the managed heap is big, since every object needs to be inspected. The *MODE*
-parameter of the *heapshot* option can be used to reduce the frequency of the heap
-shots.
-
-### Reduce the timestamp overhead
-
-On many operating systems or architectures what actually slows down profiling
-is the function provided by the system to get timestamp information.
-The *time=fast* profiler option can be usually used to speed up this operation,
-but, depending on the system, time accounting may have some level of approximation
-(though statistically the data should be still fairly valuable).
-
-## Dealing with the size of the data files
-
-When collecting a lot of information about a profiled program, huge data
-files can be generated. There are a few ways to minimize the amount of data,
-for example by not collecting some of the more space-consuming information
-or by compressing the information on the fly or by just generating a summary
-report.
-
-### Reducing the amount of data
-
-Method enter/leave events can be excluded completely with the *nocalls* option
-or they can be limited to just a few levels of calls with the *calldepth* option.
-For example, the option:
-
-`calldepth=10`
-
-will ignore the method events when there are more than 10 managed stack frames.
-This is very useful for programs that have deep recursion or for programs that
-perform many millions of tiny calls deep enough in the call stack. The optimal
-number for the calldepth option depends on the program and it needs to be balanced
-between providing enough profiling information and allowing fast execution speed.
-
-Note that by default, if method events are not recorded at all, the profiler will
-collect stack trace information at events like allocations. To avoid gathering this
-data, use the *maxframes=0* profiler option.
-
-Allocation events can be eliminated with the *noalloc* option.
-
-Heap shot data can also be huge: by default it is collected at each major collection.
-To reduce the frequency, you can specify a heapshot mode: for example to collect
-every 5 collections (including major and minor):
-
-`heapshot=5gc`
-
-or when at least 5 seconds passed since the last heap shot:
-
-`heapshot=5000ms`
-
-### Compressing the data
-
-To reduce the amout of disk space used by the data, the data can be compressed
-either after it has been generated with the gzip command:
-
-`gzip -9 output.mlpd`
-
-or it can be compressed automatically by using the *zip* profiler option. Note
-that in this case there could be a significant slowdown of the profiled program.
-
-The mprof-report program will tranparently deal with either compressed or
-uncompressed data files.
-
-### Generating only a summary report
-
-Often it's enough to look at the profiler summary report to diagnose an issue and in this
-case it's possible to avoid saving the profiler data file to disk. This can be
-accomplished with the *report* profiler option, which will basically send the data
-to the mprof-report program for display.
-
-To have more control of what summary information is reported (or to use a completely
-different program to decode the profiler data), the *output* profiler option can be
-used, with `|` as the first character: the rest of the output name will be
-executed as a program with the data fed in on the standard input.
-
-For example, to print only the Monitor summary with stack trace information, you
-could use it like this:
-
-`output=|mprof-report --reports=monitor --traces -`
-
+++ /dev/null
-/*
- * mono-co.c: Coverage profiler
- *
-
- * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
- */
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/assembly.h>
-#include <string.h>
-#include <glib.h>
-
-/*
- * Coverage profiler. Compile with:
- * gcc -Wall -shared -o mono-profiler-cov.so mono-cov.c `pkg-config --cflags --libs mono`
- * Install the binary where the dynamic loader can find it (/usr/local/lib, for example,
- * or set the env var LD_LIBRARY_PATH to the directory where the file is).
- * Then run mono with:
- * mono --profile=cov:yourassembly test_suite.exe
- * mono --profile=cov:yourassembly/namespace test_suite.exe
- */
-
-struct _MonoProfiler {
- GHashTable *hash;
- char* assembly_name;
- char* class_name;
- MonoAssembly *assembly;
- GList *bb_coverage;
-};
-
-static void
-get_assembly (MonoAssembly* ass, MonoProfiler *prof)
-{
- if (strcmp (prof->assembly_name, mono_image_get_name (mono_assembly_get_image (ass))) == 0)
- prof->assembly = ass;
-}
-
-static void
-coverage_callback (MonoProfiler *prof, const MonoProfileCoverageEntry *entry)
-{
- char* cmsg;
-
- if (entry->counter)
- return;
-
- if (entry->filename) {
- cmsg = g_strdup_printf ("offset 0x%04x (%s: line: %d, col: %d)",
- entry->iloffset, entry->filename, entry->line, entry->col);
- } else {
- cmsg = g_strdup_printf ("offset 0x%04x", entry->iloffset);
- }
- prof->bb_coverage = g_list_append (prof->bb_coverage, cmsg);
-}
-
-static void
-check_partial_coverage (MonoProfiler *prof, MonoMethod *method)
-{
- GList *tmp;
-
- mono_profiler_coverage_get (prof, method, coverage_callback);
- if (prof->bb_coverage) {
- char *name = mono_method_full_name (method, TRUE);
- g_print ("Partial coverage: %s\n", name);
- g_free (name);
- for (tmp = prof->bb_coverage; tmp; tmp = tmp->next) {
- g_print ("\t%s\n", (char*)tmp->data);
- g_free (tmp->data);
- }
- g_list_free (prof->bb_coverage);
- prof->bb_coverage = NULL;
- }
-}
-
-/* called at the end of the program */
-static void
-cov_shutdown (MonoProfiler *prof)
-{
- MonoImage *image;
- MonoMethod *method;
- int i;
- char *name;
-
- mono_assembly_foreach ((GFunc)get_assembly, prof);
- if (!prof->assembly) {
- g_print ("Assembly '%s' was not loaded\n", prof->assembly_name);
- return;
- }
- image = mono_assembly_get_image (prof->assembly);
- for (i = 1; i <= mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
- MonoClass *klass;
- method = mono_get_method (image, i | MONO_TOKEN_METHOD_DEF, NULL);
- if (!method)
- continue;
- if ((mono_method_get_flags (method, NULL) & METHOD_ATTRIBUTE_ABSTRACT))
- continue;
- /* FIXME: handle icalls, runtime calls and synchronized methods */
- if (prof->class_name && *prof->class_name) {
- klass = mono_method_get_class (method);
- if (!strstr (mono_class_get_name (klass), prof->class_name) && !strstr (mono_class_get_namespace (klass), prof->class_name))
- continue;
- }
- /*g_print ("check %s::%s, %p\n", method->klass->name, method->name, method);*/
- if (g_hash_table_lookup (prof->hash, method)) {
- /* the method was executed: check it was fully covered */
- check_partial_coverage (prof, method);
- continue;
- }
- name = mono_method_full_name (method, TRUE);
- g_print ("Not covered: %s\n", name);
- g_free (name);
- }
-}
-
-static void
-cov_method_enter (MonoProfiler *prof, MonoMethod *method)
-{
- /*g_print ("enter %s::%s, %p\n", method->klass->name, method->name, method);*/
- g_hash_table_insert (prof->hash, method, GINT_TO_POINTER (1));
-}
-
-static void
-cov_method_leave (MonoProfiler *prof, MonoMethod *method)
-{
-}
-
-static gboolean
-cov_coverage_filter(MonoProfiler *prof, MonoMethod *method)
-{
- return TRUE;
-}
-
-void
-mono_profiler_startup (const char *desc);
-
-/* the entry point */
-void
-mono_profiler_startup (const char *desc)
-{
- MonoProfiler *prof;
-
- prof = g_new0 (MonoProfiler, 1);
- prof->hash = g_hash_table_new (NULL, NULL);
- if (strncmp ("cov:", desc, 4) == 0 && desc [4]) {
- char *cname;
- prof->assembly_name = g_strdup (desc + 4);
- cname = strchr (prof->assembly_name, '/');
- if (cname) {
- *cname = 0;
- prof->class_name = cname + 1;
- }
- } else {
- prof->assembly_name = g_strdup ("mscorlib");
- }
-
- mono_profiler_install (prof, cov_shutdown);
-
- mono_profiler_install_enter_leave (cov_method_enter, cov_method_leave);
- mono_profiler_install_coverage_filter (cov_coverage_filter);
- mono_profiler_set_events (MONO_PROFILE_ENTER_LEAVE | MONO_PROFILE_COVERAGE);
-}
-
-
+++ /dev/null
-/*
- * mono-profiler-logging.c: Logging profiler for Mono.
- *
- * Author:
- * Massimiliano Mantione (massi@ximian.com)
- *
- * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
- */
-#include <config.h>
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/class.h>
-#include <mono/metadata/metadata-internals.h>
-#include <mono/metadata/class-internals.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/loader.h>
-#include <mono/metadata/threads.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/mono-gc.h>
-#include <mono/utils/mono-tls.h>
-#include <mono/io-layer/atomic.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <glib.h>
-
-#include <dlfcn.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#define HAS_OPROFILE 0
-
-#if (HAS_OPROFILE)
-#include <libopagent.h>
-#endif
-
-// Needed for heap analysis
-extern gboolean mono_object_is_alive (MonoObject* obj);
-
-typedef enum {
- MONO_PROFILER_FILE_BLOCK_KIND_INTRO = 1,
- MONO_PROFILER_FILE_BLOCK_KIND_END = 2,
- MONO_PROFILER_FILE_BLOCK_KIND_MAPPING = 3,
- MONO_PROFILER_FILE_BLOCK_KIND_LOADED = 4,
- MONO_PROFILER_FILE_BLOCK_KIND_UNLOADED = 5,
- MONO_PROFILER_FILE_BLOCK_KIND_EVENTS = 6,
- MONO_PROFILER_FILE_BLOCK_KIND_STATISTICAL = 7,
- MONO_PROFILER_FILE_BLOCK_KIND_HEAP_DATA = 8,
- MONO_PROFILER_FILE_BLOCK_KIND_HEAP_SUMMARY = 9,
- MONO_PROFILER_FILE_BLOCK_KIND_DIRECTIVES = 10
-} MonoProfilerFileBlockKind;
-
-typedef enum {
- MONO_PROFILER_DIRECTIVE_END = 0,
- MONO_PROFILER_DIRECTIVE_ALLOCATIONS_CARRY_CALLER = 1,
- MONO_PROFILER_DIRECTIVE_ALLOCATIONS_HAVE_STACK = 2,
- MONO_PROFILER_DIRECTIVE_ALLOCATIONS_CARRY_ID = 3,
- MONO_PROFILER_DIRECTIVE_LOADED_ELEMENTS_CARRY_ID = 4,
- MONO_PROFILER_DIRECTIVE_CLASSES_CARRY_ASSEMBLY_ID = 5,
- MONO_PROFILER_DIRECTIVE_METHODS_CARRY_WRAPPER_FLAG = 6,
- MONO_PROFILER_DIRECTIVE_LAST
-} MonoProfilerDirectives;
-
-
-#define MONO_PROFILER_LOADED_EVENT_MODULE 1
-#define MONO_PROFILER_LOADED_EVENT_ASSEMBLY 2
-#define MONO_PROFILER_LOADED_EVENT_APPDOMAIN 4
-#define MONO_PROFILER_LOADED_EVENT_SUCCESS 8
-#define MONO_PROFILER_LOADED_EVENT_FAILURE 16
-
-typedef enum {
- MONO_PROFILER_EVENT_DATA_TYPE_OTHER = 0,
- MONO_PROFILER_EVENT_DATA_TYPE_METHOD = 1,
- MONO_PROFILER_EVENT_DATA_TYPE_CLASS = 2
-} MonoProfilerEventDataType;
-
-typedef struct _ProfilerEventData {
- union {
- gpointer address;
- gsize number;
- } data;
- unsigned int data_type:2;
- unsigned int code:4;
- unsigned int kind:1;
- unsigned int value:25;
-} ProfilerEventData;
-
-#define EVENT_VALUE_BITS (25)
-#define MAX_EVENT_VALUE ((1<<EVENT_VALUE_BITS)-1)
-
-typedef enum {
- MONO_PROFILER_EVENT_METHOD_JIT = 0,
- MONO_PROFILER_EVENT_METHOD_FREED = 1,
- MONO_PROFILER_EVENT_METHOD_CALL = 2,
- MONO_PROFILER_EVENT_METHOD_ALLOCATION_CALLER = 3,
- MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER = 4
-} MonoProfilerMethodEvents;
-typedef enum {
- MONO_PROFILER_EVENT_CLASS_LOAD = 0,
- MONO_PROFILER_EVENT_CLASS_UNLOAD = 1,
- MONO_PROFILER_EVENT_CLASS_EXCEPTION = 2,
- MONO_PROFILER_EVENT_CLASS_MONITOR = 3,
- MONO_PROFILER_EVENT_CLASS_ALLOCATION = 4
-} MonoProfilerClassEvents;
-typedef enum {
- MONO_PROFILER_EVENT_RESULT_SUCCESS = 0,
- MONO_PROFILER_EVENT_RESULT_FAILURE = 4
-} MonoProfilerEventResult;
-#define MONO_PROFILER_EVENT_RESULT_MASK MONO_PROFILER_EVENT_RESULT_FAILURE
-typedef enum {
- MONO_PROFILER_EVENT_THREAD = 1,
- MONO_PROFILER_EVENT_GC_COLLECTION = 2,
- MONO_PROFILER_EVENT_GC_MARK = 3,
- MONO_PROFILER_EVENT_GC_SWEEP = 4,
- MONO_PROFILER_EVENT_GC_RESIZE = 5,
- MONO_PROFILER_EVENT_GC_STOP_WORLD = 6,
- MONO_PROFILER_EVENT_GC_START_WORLD = 7,
- MONO_PROFILER_EVENT_JIT_TIME_ALLOCATION = 8,
- MONO_PROFILER_EVENT_STACK_SECTION = 9,
- MONO_PROFILER_EVENT_ALLOCATION_OBJECT_ID = 10,
- MONO_PROFILER_EVENT_OBJECT_MONITOR = 11
-} MonoProfilerEvents;
-typedef enum {
- MONO_PROFILER_EVENT_KIND_START = 0,
- MONO_PROFILER_EVENT_KIND_END = 1
-} MonoProfilerEventKind;
-
-#define MONO_PROFILER_GET_CURRENT_TIME(t) {\
- struct timeval current_time;\
- gettimeofday (¤t_time, NULL);\
- (t) = (((guint64)current_time.tv_sec) * 1000000) + current_time.tv_usec;\
-} while (0)
-
-static gboolean use_fast_timer = FALSE;
-
-#if (defined(__i386__) || defined(__x86_64__)) && ! defined(HOST_WIN32)
-
-#if defined(__i386__)
-static const guchar cpuid_impl [] = {
- 0x55, /* push %ebp */
- 0x89, 0xe5, /* mov %esp,%ebp */
- 0x53, /* push %ebx */
- 0x8b, 0x45, 0x08, /* mov 0x8(%ebp),%eax */
- 0x0f, 0xa2, /* cpuid */
- 0x50, /* push %eax */
- 0x8b, 0x45, 0x10, /* mov 0x10(%ebp),%eax */
- 0x89, 0x18, /* mov %ebx,(%eax) */
- 0x8b, 0x45, 0x14, /* mov 0x14(%ebp),%eax */
- 0x89, 0x08, /* mov %ecx,(%eax) */
- 0x8b, 0x45, 0x18, /* mov 0x18(%ebp),%eax */
- 0x89, 0x10, /* mov %edx,(%eax) */
- 0x58, /* pop %eax */
- 0x8b, 0x55, 0x0c, /* mov 0xc(%ebp),%edx */
- 0x89, 0x02, /* mov %eax,(%edx) */
- 0x5b, /* pop %ebx */
- 0xc9, /* leave */
- 0xc3, /* ret */
-};
-
-typedef void (*CpuidFunc) (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx);
-
-static int
-cpuid (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx) {
- int have_cpuid = 0;
-#ifndef _MSC_VER
- __asm__ __volatile__ (
- "pushfl\n"
- "popl %%eax\n"
- "movl %%eax, %%edx\n"
- "xorl $0x200000, %%eax\n"
- "pushl %%eax\n"
- "popfl\n"
- "pushfl\n"
- "popl %%eax\n"
- "xorl %%edx, %%eax\n"
- "andl $0x200000, %%eax\n"
- "movl %%eax, %0"
- : "=r" (have_cpuid)
- :
- : "%eax", "%edx"
- );
-#else
- __asm {
- pushfd
- pop eax
- mov edx, eax
- xor eax, 0x200000
- push eax
- popfd
- pushfd
- pop eax
- xor eax, edx
- and eax, 0x200000
- mov have_cpuid, eax
- }
-#endif
- if (have_cpuid) {
- CpuidFunc func = (CpuidFunc) cpuid_impl;
- func (id, p_eax, p_ebx, p_ecx, p_edx);
- /*
- * We use this approach because of issues with gcc and pic code, see:
- * http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7329
- __asm__ __volatile__ ("cpuid"
- : "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
- : "a" (id));
- */
- return 1;
- }
- return 0;
-}
-
-static void detect_fast_timer (void) {
- int p_eax, p_ebx, p_ecx, p_edx;
-
- if (cpuid (0x1, &p_eax, &p_ebx, &p_ecx, &p_edx)) {
- if (p_edx & 0x10) {
- use_fast_timer = TRUE;
- } else {
- use_fast_timer = FALSE;
- }
- } else {
- use_fast_timer = FALSE;
- }
-}
-#endif
-
-#if defined(__x86_64__)
-static void detect_fast_timer (void) {
- guint32 op = 0x1;
- guint32 eax,ebx,ecx,edx;
- __asm__ __volatile__ ("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(op));
- if (edx & 0x10) {
- use_fast_timer = TRUE;
- } else {
- use_fast_timer = FALSE;
- }
-}
-#endif
-
-static __inline__ guint64 rdtsc(void) {
- guint32 hi, lo;
- __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
- return ((guint64) lo) | (((guint64) hi) << 32);
-}
-#define MONO_PROFILER_GET_CURRENT_COUNTER(c) {\
- if (use_fast_timer) {\
- (c) = rdtsc ();\
- } else {\
- MONO_PROFILER_GET_CURRENT_TIME ((c));\
- }\
-} while (0)
-#else
-static void detect_fast_timer (void) {
- use_fast_timer = FALSE;
-}
-#define MONO_PROFILER_GET_CURRENT_COUNTER(c) MONO_PROFILER_GET_CURRENT_TIME ((c))
-#endif
-
-
-#define CLASS_LAYOUT_PACKED_BITMAP_SIZE 64
-#define CLASS_LAYOUT_NOT_INITIALIZED (0xFFFF)
-typedef enum {
- HEAP_CODE_NONE = 0,
- HEAP_CODE_OBJECT = 1,
- HEAP_CODE_FREE_OBJECT_CLASS = 2,
- HEAP_CODE_MASK = 3
-} HeapProfilerJobValueCode;
-typedef struct _MonoProfilerClassData {
- union {
- guint64 compact;
- guint8 *extended;
- } bitmap;
- struct {
- guint16 slots;
- guint16 references;
- } layout;
-} MonoProfilerClassData;
-
-typedef struct _MonoProfilerMethodData {
- gpointer code_start;
- guint32 code_size;
-} MonoProfilerMethodData;
-
-typedef struct _ClassIdMappingElement {
- char *name;
- guint32 id;
- MonoClass *klass;
- struct _ClassIdMappingElement *next_unwritten;
- MonoProfilerClassData data;
-} ClassIdMappingElement;
-
-typedef struct _MethodIdMappingElement {
- char *name;
- guint32 id;
- MonoMethod *method;
- struct _MethodIdMappingElement *next_unwritten;
- MonoProfilerMethodData data;
-} MethodIdMappingElement;
-
-typedef struct _ClassIdMapping {
- GHashTable *table;
- ClassIdMappingElement *unwritten;
- guint32 next_id;
-} ClassIdMapping;
-
-typedef struct _MethodIdMapping {
- GHashTable *table;
- MethodIdMappingElement *unwritten;
- guint32 next_id;
-} MethodIdMapping;
-
-typedef struct _LoadedElement {
- char *name;
- guint64 load_start_counter;
- guint64 load_end_counter;
- guint64 unload_start_counter;
- guint64 unload_end_counter;
- guint32 id;
- guint8 loaded;
- guint8 load_written;
- guint8 unloaded;
- guint8 unload_written;
-} LoadedElement;
-struct _ProfilerCodeBufferArray;
-typedef struct _ProfilerCodeBuffer {
- gpointer start;
- gpointer end;
- struct {
- union {
- MonoMethod *method;
- MonoClass *klass;
- void *data;
- struct _ProfilerCodeBufferArray *sub_buffers;
- } data;
- guint16 value;
- guint16 type;
- } info;
-} ProfilerCodeBuffer;
-
-#define PROFILER_CODE_BUFFER_ARRAY_SIZE 64
-typedef struct _ProfilerCodeBufferArray {
- int level;
- int number_of_buffers;
- ProfilerCodeBuffer buffers [PROFILER_CODE_BUFFER_ARRAY_SIZE];
-} ProfilerCodeBufferArray;
-
-typedef struct _ProfilerCodeChunk {
- gpointer start;
- gpointer end;
- gboolean destroyed;
- ProfilerCodeBufferArray *buffers;
-} ProfilerCodeChunk;
-
-typedef struct _ProfilerCodeChunks {
- int capacity;
- int number_of_chunks;;
- ProfilerCodeChunk *chunks;
-} ProfilerCodeChunks;
-
-
-#define PROFILER_HEAP_SHOT_OBJECT_BUFFER_SIZE 1024
-#define PROFILER_HEAP_SHOT_HEAP_BUFFER_SIZE 4096
-#define PROFILER_HEAP_SHOT_WRITE_BUFFER_SIZE 4096
-
-typedef struct _ProfilerHeapShotObjectBuffer {
- struct _ProfilerHeapShotObjectBuffer *next;
- MonoObject **next_free_slot;
- MonoObject **end;
- MonoObject **first_unprocessed_slot;
- MonoObject *buffer [PROFILER_HEAP_SHOT_OBJECT_BUFFER_SIZE];
-} ProfilerHeapShotObjectBuffer;
-
-typedef struct _ProfilerHeapShotHeapBuffer {
- struct _ProfilerHeapShotHeapBuffer *next;
- struct _ProfilerHeapShotHeapBuffer *previous;
- MonoObject **start_slot;
- MonoObject **end_slot;
- MonoObject *buffer [PROFILER_HEAP_SHOT_HEAP_BUFFER_SIZE];
-} ProfilerHeapShotHeapBuffer;
-
-typedef struct _ProfilerHeapShotHeapBuffers {
- ProfilerHeapShotHeapBuffer *buffers;
- ProfilerHeapShotHeapBuffer *last;
- ProfilerHeapShotHeapBuffer *current;
- MonoObject **first_free_slot;
-} ProfilerHeapShotHeapBuffers;
-
-
-typedef struct _ProfilerHeapShotWriteBuffer {
- struct _ProfilerHeapShotWriteBuffer *next;
- gpointer buffer [PROFILER_HEAP_SHOT_WRITE_BUFFER_SIZE];
-} ProfilerHeapShotWriteBuffer;
-
-typedef struct _ProfilerHeapShotClassSummary {
- struct {
- guint32 instances;
- guint32 bytes;
- } reachable;
- struct {
- guint32 instances;
- guint32 bytes;
- } unreachable;
-} ProfilerHeapShotClassSummary;
-
-typedef struct _ProfilerHeapShotCollectionSummary {
- ProfilerHeapShotClassSummary *per_class_data;
- guint32 capacity;
-} ProfilerHeapShotCollectionSummary;
-
-typedef struct _ProfilerHeapShotWriteJob {
- struct _ProfilerHeapShotWriteJob *next;
- struct _ProfilerHeapShotWriteJob *next_unwritten;
- gpointer *start;
- gpointer *cursor;
- gpointer *end;
- ProfilerHeapShotWriteBuffer *buffers;
- ProfilerHeapShotWriteBuffer **last_next;
- guint32 full_buffers;
- gboolean heap_shot_was_requested;
- guint64 start_counter;
- guint64 start_time;
- guint64 end_counter;
- guint64 end_time;
- guint32 collection;
- ProfilerHeapShotCollectionSummary summary;
- gboolean dump_heap_data;
-} ProfilerHeapShotWriteJob;
-
-typedef struct _ProfilerThreadStack {
- guint32 capacity;
- guint32 top;
- guint32 last_saved_top;
- guint32 last_written_frame;
- MonoMethod **stack;
- guint8 *method_is_jitted;
- guint32 *written_frames;
-} ProfilerThreadStack;
-
-typedef struct _ProfilerPerThreadData {
- ProfilerEventData *events;
- ProfilerEventData *next_free_event;
- ProfilerEventData *next_unreserved_event;
- ProfilerEventData *end_event;
- ProfilerEventData *first_unwritten_event;
- ProfilerEventData *first_unmapped_event;
- guint64 start_event_counter;
- guint64 last_event_counter;
- gsize thread_id;
- ProfilerHeapShotObjectBuffer *heap_shot_object_buffers;
- ProfilerThreadStack stack;
- struct _ProfilerPerThreadData* next;
-} ProfilerPerThreadData;
-
-typedef struct _ProfilerStatisticalHit {
- gpointer *address;
- MonoDomain *domain;
-} ProfilerStatisticalHit;
-
-typedef struct _ProfilerStatisticalData {
- ProfilerStatisticalHit *hits;
- unsigned int next_free_index;
- unsigned int end_index;
- unsigned int first_unwritten_index;
-} ProfilerStatisticalData;
-
-typedef struct _ProfilerUnmanagedSymbol {
- guint32 offset;
- guint32 size;
- guint32 id;
- guint32 index;
-} ProfilerUnmanagedSymbol;
-
-struct _ProfilerExecutableFile;
-struct _ProfilerExecutableFileSectionRegion;
-
-typedef struct _ProfilerExecutableMemoryRegionData {
- gpointer start;
- gpointer end;
- guint32 file_offset;
- char *file_name;
- guint32 id;
- gboolean is_new;
-
- struct _ProfilerExecutableFile *file;
- struct _ProfilerExecutableFileSectionRegion *file_region_reference;
- guint32 symbols_count;
- guint32 symbols_capacity;
- ProfilerUnmanagedSymbol *symbols;
-} ProfilerExecutableMemoryRegionData;
-
-typedef struct _ProfilerExecutableMemoryRegions {
- ProfilerExecutableMemoryRegionData **regions;
- guint32 regions_capacity;
- guint32 regions_count;
- guint32 next_id;
- guint32 next_unmanaged_function_id;
-} ProfilerExecutableMemoryRegions;
-
-/* Start of ELF definitions */
-#define EI_NIDENT 16
-typedef guint16 ElfHalf;
-typedef guint32 ElfWord;
-typedef gsize ElfAddr;
-typedef gsize ElfOff;
-
-typedef struct {
- unsigned char e_ident[EI_NIDENT];
- ElfHalf e_type;
- ElfHalf e_machine;
- ElfWord e_version;
- ElfAddr e_entry;
- ElfOff e_phoff;
- ElfOff e_shoff; // Section header table
- ElfWord e_flags;
- ElfHalf e_ehsize; // Header size
- ElfHalf e_phentsize;
- ElfHalf e_phnum;
- ElfHalf e_shentsize; // Section header entry size
- ElfHalf e_shnum; // Section header entries number
- ElfHalf e_shstrndx; // String table index
-} ElfHeader;
-
-#if (SIZEOF_VOID_P == 4)
-typedef struct {
- ElfWord sh_name;
- ElfWord sh_type;
- ElfWord sh_flags;
- ElfAddr sh_addr; // Address in memory
- ElfOff sh_offset; // Offset in file
- ElfWord sh_size;
- ElfWord sh_link;
- ElfWord sh_info;
- ElfWord sh_addralign;
- ElfWord sh_entsize;
-} ElfSection;
-typedef struct {
- ElfWord st_name;
- ElfAddr st_value;
- ElfWord st_size;
- unsigned char st_info; // Use ELF32_ST_TYPE to get symbol type
- unsigned char st_other;
- ElfHalf st_shndx; // Or one of SHN_ABS, SHN_COMMON or SHN_UNDEF.
-} ElfSymbol;
-#elif (SIZEOF_VOID_P == 8)
-typedef struct {
- ElfWord sh_name;
- ElfWord sh_type;
- ElfOff sh_flags;
- ElfAddr sh_addr; // Address in memory
- ElfOff sh_offset; // Offset in file
- ElfOff sh_size;
- ElfWord sh_link;
- ElfWord sh_info;
- ElfOff sh_addralign;
- ElfOff sh_entsize;
-} ElfSection;
-typedef struct {
- ElfWord st_name;
- unsigned char st_info; // Use ELF_ST_TYPE to get symbol type
- unsigned char st_other;
- ElfHalf st_shndx; // Or one of SHN_ABS, SHN_COMMON or SHN_UNDEF.
- ElfAddr st_value;
- ElfAddr st_size;
-} ElfSymbol;
-#else
-#error Bad size of void pointer
-#endif
-
-
-#define ELF_ST_BIND(i) ((i)>>4)
-#define ELF_ST_TYPE(i) ((i)&0xf)
-
-
-typedef enum {
- EI_MAG0 = 0,
- EI_MAG1 = 1,
- EI_MAG2 = 2,
- EI_MAG3 = 3,
- EI_CLASS = 4,
- EI_DATA = 5
-} ElfIdentFields;
-
-typedef enum {
- ELF_FILE_TYPE_NONE = 0,
- ELF_FILE_TYPE_REL = 1,
- ELF_FILE_TYPE_EXEC = 2,
- ELF_FILE_TYPE_DYN = 3,
- ELF_FILE_TYPE_CORE = 4
-} ElfFileType;
-
-typedef enum {
- ELF_CLASS_NONE = 0,
- ELF_CLASS_32 = 1,
- ELF_CLASS_64 = 2
-} ElfIdentClass;
-
-typedef enum {
- ELF_DATA_NONE = 0,
- ELF_DATA_LSB = 1,
- ELF_DATA_MSB = 2
-} ElfIdentData;
-
-typedef enum {
- ELF_SHT_NULL = 0,
- ELF_SHT_PROGBITS = 1,
- ELF_SHT_SYMTAB = 2,
- ELF_SHT_STRTAB = 3,
- ELF_SHT_RELA = 4,
- ELF_SHT_HASH = 5,
- ELF_SHT_DYNAMIC = 6,
- ELF_SHT_NOTE = 7,
- ELF_SHT_NOBITS = 8,
- ELF_SHT_REL = 9,
- ELF_SHT_SHLIB = 10,
- ELF_SHT_DYNSYM = 11
-} ElfSectionType;
-
-typedef enum {
- ELF_STT_NOTYPE = 0,
- ELF_STT_OBJECT = 1,
- ELF_STT_FUNC = 2,
- ELF_STT_SECTION = 3,
- ELF_STT_FILE = 4
-} ElfSymbolType;
-
-typedef enum {
- ELF_SHF_WRITE = 1,
- ELF_SHF_ALLOC = 2,
- ELF_SHF_EXECINSTR = 4,
-} ElfSectionFlags;
-
-#define ELF_SHN_UNDEF 0
-#define ELF_SHN_LORESERVE 0xff00
-#define ELF_SHN_LOPROC 0xff00
-#define ELF_SHN_HIPROC 0xff1f
-#define ELF_SHN_ABS 0xfff1
-#define ELF_SHN_COMMON 0xfff2
-#define ELF_SHN_HIRESERVE 0xffff
-/* End of ELF definitions */
-
-typedef struct _ProfilerExecutableFileSectionRegion {
- ProfilerExecutableMemoryRegionData *region;
- guint8 *section_address;
- gsize section_offset;
-} ProfilerExecutableFileSectionRegion;
-
-typedef struct _ProfilerExecutableFile {
- guint32 reference_count;
-
- /* Used for mmap and munmap */
- int fd;
- guint8 *data;
- size_t length;
-
- /* File data */
- ElfHeader *header;
- guint8 *symbols_start;
- guint32 symbols_count;
- guint32 symbol_size;
- const char *symbols_string_table;
- const char *main_string_table;
-
- ProfilerExecutableFileSectionRegion *section_regions;
-
- struct _ProfilerExecutableFile *next_new_file;
-} ProfilerExecutableFile;
-
-typedef struct _ProfilerExecutableFiles {
- GHashTable *table;
- ProfilerExecutableFile *new_files;
-} ProfilerExecutableFiles;
-
-
-#define CLEANUP_WRITER_THREAD() do {profiler->writer_thread_terminated = TRUE;} while (0)
-#define CHECK_WRITER_THREAD() (! profiler->writer_thread_terminated)
-
-#ifndef HOST_WIN32
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <semaphore.h>
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define MUTEX_TYPE pthread_mutex_t
-#define INITIALIZE_PROFILER_MUTEX() pthread_mutex_init (&(profiler->mutex), NULL)
-#define DELETE_PROFILER_MUTEX() pthread_mutex_destroy (&(profiler->mutex))
-#define LOCK_PROFILER() do {/*LOG_WRITER_THREAD ("LOCK_PROFILER");*/ pthread_mutex_lock (&(profiler->mutex));} while (0)
-#define UNLOCK_PROFILER() do {/*LOG_WRITER_THREAD ("UNLOCK_PROFILER");*/ pthread_mutex_unlock (&(profiler->mutex));} while (0)
-
-#define THREAD_TYPE pthread_t
-#define CREATE_WRITER_THREAD(f) pthread_create (&(profiler->data_writer_thread), NULL, ((void*(*)(void*))f), NULL)
-#define CREATE_USER_THREAD(f) pthread_create (&(profiler->user_thread), NULL, ((void*(*)(void*))f), NULL)
-#define EXIT_THREAD() pthread_exit (NULL);
-#define WAIT_WRITER_THREAD() do {\
- if (CHECK_WRITER_THREAD ()) {\
- pthread_join (profiler->data_writer_thread, NULL);\
- }\
-} while (0)
-#define CURRENT_THREAD_ID() (gsize) pthread_self ()
-
-#ifndef HAVE_KW_THREAD
-static pthread_key_t pthread_profiler_key;
-static pthread_once_t profiler_pthread_once = PTHREAD_ONCE_INIT;
-static void
-make_pthread_profiler_key (void) {
- (void) pthread_key_create (&pthread_profiler_key, NULL);
-}
-#define LOOKUP_PROFILER_THREAD_DATA() ((ProfilerPerThreadData*) pthread_getspecific (pthread_profiler_key))
-#define SET_PROFILER_THREAD_DATA(x) (void) pthread_setspecific (pthread_profiler_key, (x))
-#define ALLOCATE_PROFILER_THREAD_DATA() (void) pthread_once (&profiler_pthread_once, make_pthread_profiler_key)
-#define FREE_PROFILER_THREAD_DATA() (void) pthread_key_delete (pthread_profiler_key)
-#endif
-
-#define EVENT_TYPE sem_t
-#define WRITER_EVENT_INIT() do {\
- sem_init (&(profiler->enable_data_writer_event), 0, 0);\
- sem_init (&(profiler->wake_data_writer_event), 0, 0);\
- sem_init (&(profiler->done_data_writer_event), 0, 0);\
-} while (0)
-#define WRITER_EVENT_DESTROY() do {\
- sem_destroy (&(profiler->enable_data_writer_event));\
- sem_destroy (&(profiler->wake_data_writer_event));\
- sem_destroy (&(profiler->done_data_writer_event));\
-} while (0)
-#define WRITER_EVENT_WAIT() (void) sem_wait (&(profiler->wake_data_writer_event))
-#define WRITER_EVENT_RAISE() (void) sem_post (&(profiler->wake_data_writer_event))
-#define WRITER_EVENT_ENABLE_WAIT() (void) sem_wait (&(profiler->enable_data_writer_event))
-#define WRITER_EVENT_ENABLE_RAISE() (void) sem_post (&(profiler->enable_data_writer_event))
-#define WRITER_EVENT_DONE_WAIT() do {\
- if (CHECK_WRITER_THREAD ()) {\
- (void) sem_wait (&(profiler->done_data_writer_event));\
- }\
-} while (0)
-#define WRITER_EVENT_DONE_RAISE() (void) sem_post (&(profiler->done_data_writer_event))
-
-#if 0
-#define FILE_HANDLE_TYPE FILE*
-#define OPEN_FILE() profiler->file = fopen (profiler->file_name, "wb");
-#define WRITE_BUFFER(b,s) fwrite ((b), 1, (s), profiler->file)
-#define FLUSH_FILE() fflush (profiler->file)
-#define CLOSE_FILE() fclose (profiler->file)
-#else
-#define FILE_HANDLE_TYPE int
-#define OPEN_FILE() profiler->file = open (profiler->file_name, O_WRONLY|O_CREAT|O_TRUNC, 0664);
-#define WRITE_BUFFER(b,s) write (profiler->file, (b), (s))
-#define FLUSH_FILE() fsync (profiler->file)
-#define CLOSE_FILE() close (profiler->file)
-#endif
-
-#else
-
-#include <windows.h>
-
-#define MUTEX_TYPE CRITICAL_SECTION
-#define INITIALIZE_PROFILER_MUTEX() InitializeCriticalSection (&(profiler->mutex))
-#define DELETE_PROFILER_MUTEX() DeleteCriticalSection (&(profiler->mutex))
-#define LOCK_PROFILER() EnterCriticalSection (&(profiler->mutex))
-#define UNLOCK_PROFILER() LeaveCriticalSection (&(profiler->mutex))
-
-#define THREAD_TYPE HANDLE
-#define CREATE_WRITER_THREAD(f) CreateThread (NULL, (1*1024*1024), (f), NULL, 0, NULL);
-#define EXIT_THREAD() ExitThread (0);
-#define WAIT_WRITER_THREAD() do {\
- if (CHECK_WRITER_THREAD ()) {\
- WaitForSingleObject (profiler->data_writer_thread, INFINITE);\
- }\
-} while (0)
-#define CURRENT_THREAD_ID() (gsize) GetCurrentThreadId ()
-
-#ifndef HAVE_KW_THREAD
-static MonoNativeTlsKey profiler_thread_id;
-#define LOOKUP_PROFILER_THREAD_DATA() ((ProfilerPerThreadData*)mono_native_tls_get_value (profiler_thread_id))
-#define SET_PROFILER_THREAD_DATA(x) mono_native_tls_set_value (profiler_thread_id, (x));
-#define ALLOCATE_PROFILER_THREAD_DATA() mono_native_tls_alloc (profiler_thread_id, NULL)
-#define FREE_PROFILER_THREAD_DATA() mono_native_tls_free (profiler_thread_id)
-#endif
-
-#define EVENT_TYPE HANDLE
-#define WRITER_EVENT_INIT() (void) do {\
- profiler->enable_data_writer_event = CreateEvent (NULL, FALSE, FALSE, NULL);\
- profiler->wake_data_writer_event = CreateEvent (NULL, FALSE, FALSE, NULL);\
- profiler->done_data_writer_event = CreateEvent (NULL, FALSE, FALSE, NULL);\
-} while (0)
-#define WRITER_EVENT_DESTROY() CloseHandle (profiler->statistical_data_writer_event)
-#define WRITER_EVENT_INIT() (void) do {\
- CloseHandle (profiler->enable_data_writer_event);\
- CloseHandle (profiler->wake_data_writer_event);\
- CloseHandle (profiler->done_data_writer_event);\
-} while (0)
-#define WRITER_EVENT_WAIT() WaitForSingleObject (profiler->wake_data_writer_event, INFINITE)
-#define WRITER_EVENT_RAISE() SetEvent (profiler->wake_data_writer_event)
-#define WRITER_EVENT_ENABLE_WAIT() WaitForSingleObject (profiler->enable_data_writer_event, INFINITE)
-#define WRITER_EVENT_ENABLE_RAISE() SetEvent (profiler->enable_data_writer_event)
-#define WRITER_EVENT_DONE_WAIT() do {\
- if (CHECK_WRITER_THREAD ()) {\
- WaitForSingleObject (profiler->done_data_writer_event, INFINITE);\
- }\
-} while (0)
-#define WRITER_EVENT_DONE_RAISE() SetEvent (profiler->done_data_writer_event)
-
-#define FILE_HANDLE_TYPE FILE*
-#define OPEN_FILE() profiler->file = fopen (profiler->file_name, "wb");
-#define WRITE_BUFFER(b,s) fwrite ((b), 1, (s), profiler->file)
-#define FLUSH_FILE() fflush (profiler->file)
-#define CLOSE_FILE() fclose (profiler->file);
-
-#endif
-
-#ifdef HAVE_KW_THREAD
-static __thread ProfilerPerThreadData * tls_profiler_per_thread_data;
-#define LOOKUP_PROFILER_THREAD_DATA() ((ProfilerPerThreadData*) tls_profiler_per_thread_data)
-#define SET_PROFILER_THREAD_DATA(x) tls_profiler_per_thread_data = (x)
-#define ALLOCATE_PROFILER_THREAD_DATA() /* nop */
-#define FREE_PROFILER_THREAD_DATA() /* nop */
-#endif
-
-#define GET_PROFILER_THREAD_DATA(data) do {\
- ProfilerPerThreadData *_result = LOOKUP_PROFILER_THREAD_DATA ();\
- if (!_result) {\
- _result = profiler_per_thread_data_new (profiler->per_thread_buffer_size);\
- LOCK_PROFILER ();\
- _result->next = profiler->per_thread_data;\
- profiler->per_thread_data = _result;\
- UNLOCK_PROFILER ();\
- SET_PROFILER_THREAD_DATA (_result);\
- }\
- (data) = _result;\
-} while (0)
-
-#define PROFILER_FILE_WRITE_BUFFER_SIZE (profiler->write_buffer_size)
-typedef struct _ProfilerFileWriteBuffer {
- struct _ProfilerFileWriteBuffer *next;
- guint8 buffer [MONO_ZERO_LEN_ARRAY];
-} ProfilerFileWriteBuffer;
-
-#define CHECK_PROFILER_ENABLED() do {\
- if (! profiler->profiler_enabled)\
- return;\
-} while (0)
-struct _MonoProfiler {
- MUTEX_TYPE mutex;
-
- MonoProfileFlags flags;
- gboolean profiler_enabled;
- char *file_name;
- char *file_name_suffix;
- FILE_HANDLE_TYPE file;
-
- guint64 start_time;
- guint64 start_counter;
- guint64 end_time;
- guint64 end_counter;
-
- guint64 last_header_counter;
-
- MethodIdMapping *methods;
- ClassIdMapping *classes;
-
- guint32 loaded_element_next_free_id;
- GHashTable *loaded_assemblies;
- GHashTable *loaded_modules;
- GHashTable *loaded_appdomains;
-
- guint32 per_thread_buffer_size;
- guint32 statistical_buffer_size;
- ProfilerPerThreadData* per_thread_data;
- ProfilerStatisticalData *statistical_data;
- ProfilerStatisticalData *statistical_data_ready;
- ProfilerStatisticalData *statistical_data_second_buffer;
- int statistical_call_chain_depth;
- MonoProfilerCallChainStrategy statistical_call_chain_strategy;
-
- ProfilerCodeChunks code_chunks;
-
- THREAD_TYPE data_writer_thread;
- THREAD_TYPE user_thread;
- EVENT_TYPE enable_data_writer_event;
- EVENT_TYPE wake_data_writer_event;
- EVENT_TYPE done_data_writer_event;
- gboolean terminate_writer_thread;
- gboolean writer_thread_terminated;
-
- ProfilerFileWriteBuffer *write_buffers;
- ProfilerFileWriteBuffer *current_write_buffer;
- int write_buffer_size;
- int current_write_position;
- int full_write_buffers;
-
- ProfilerHeapShotWriteJob *heap_shot_write_jobs;
- ProfilerHeapShotHeapBuffers heap;
-
- int command_port;
-
- int dump_next_heap_snapshots;
- gboolean heap_shot_was_requested;
- guint32 garbage_collection_counter;
-
- ProfilerExecutableMemoryRegions *executable_regions;
- ProfilerExecutableFiles executable_files;
-
- struct {
-#if (HAS_OPROFILE)
- gboolean oprofile;
-#endif
- gboolean jit_time;
- gboolean unreachable_objects;
- gboolean collection_summary;
- gboolean report_gc_events;
- gboolean heap_shot;
- gboolean track_stack;
- gboolean track_calls;
- gboolean save_allocation_caller;
- gboolean save_allocation_stack;
- gboolean allocations_carry_id;
- } action_flags;
-};
-static MonoProfiler *profiler;
-
-static void
-enable_profiler (void) {
- profiler->profiler_enabled = TRUE;
-}
-
-static void flush_everything (void);
-
-static void
-disable_profiler (void) {
- profiler->profiler_enabled = FALSE;
- flush_everything ();
-}
-
-static void
-request_heap_snapshot (void) {
- profiler->heap_shot_was_requested = TRUE;
- mono_gc_collect (mono_gc_max_generation ());
-}
-
-#define DEBUG_LOAD_EVENTS 0
-#define DEBUG_MAPPING_EVENTS 0
-#define DEBUG_LOGGING_PROFILER 0
-#define DEBUG_HEAP_PROFILER 0
-#define DEBUG_CLASS_BITMAPS 0
-#define DEBUG_STATISTICAL_PROFILER 0
-#define DEBUG_WRITER_THREAD 0
-#define DEBUG_USER_THREAD 0
-#define DEBUG_FILE_WRITES 0
-#if (DEBUG_LOGGING_PROFILER || DEBUG_STATISTICAL_PROFILER || DEBUG_HEAP_PROFILER || DEBUG_WRITER_THREAD || DEBUG_FILE_WRITES)
-#define LOG_WRITER_THREAD(m) printf ("WRITER-THREAD-LOG %s\n", m)
-#else
-#define LOG_WRITER_THREAD(m)
-#endif
-#if (DEBUG_LOGGING_PROFILER || DEBUG_STATISTICAL_PROFILER || DEBUG_HEAP_PROFILER || DEBUG_USER_THREAD || DEBUG_FILE_WRITES)
-#define LOG_USER_THREAD(m) printf ("USER-THREAD-LOG %s\n", m)
-#else
-#define LOG_USER_THREAD(m)
-#endif
-
-#if DEBUG_LOGGING_PROFILER
-static int event_counter = 0;
-#define EVENT_MARK() printf ("[EVENT:%d]", ++ event_counter)
-#endif
-
-static void
-thread_stack_initialize_empty (ProfilerThreadStack *stack) {
- stack->capacity = 0;
- stack->top = 0;
- stack->last_saved_top = 0;
- stack->last_written_frame = 0;
- stack->stack = NULL;
- stack->method_is_jitted = NULL;
- stack->written_frames = NULL;
-}
-
-static void
-thread_stack_free (ProfilerThreadStack *stack) {
- stack->capacity = 0;
- stack->top = 0;
- stack->last_saved_top = 0;
- stack->last_written_frame = 0;
- if (stack->stack != NULL) {
- g_free (stack->stack);
- stack->stack = NULL;
- }
- if (stack->method_is_jitted != NULL) {
- g_free (stack->method_is_jitted);
- stack->method_is_jitted = NULL;
- }
- if (stack->written_frames != NULL) {
- g_free (stack->written_frames);
- stack->written_frames = NULL;
- }
-}
-
-static void
-thread_stack_initialize (ProfilerThreadStack *stack, guint32 capacity) {
- stack->capacity = capacity;
- stack->top = 0;
- stack->last_saved_top = 0;
- stack->last_written_frame = 0;
- stack->stack = g_new0 (MonoMethod*, capacity);
- stack->method_is_jitted = g_new0 (guint8, capacity);
- stack->written_frames = g_new0 (guint32, capacity);
-}
-
-static void
-thread_stack_push_jitted (ProfilerThreadStack *stack, MonoMethod* method, gboolean method_is_jitted) {
- if (stack->top >= stack->capacity) {
- MonoMethod **old_stack = stack->stack;
- guint8 *old_method_is_jitted = stack->method_is_jitted;
- guint32 *old_written_frames = stack->written_frames;
- guint32 top = stack->top;
- guint32 last_saved_top = stack->last_saved_top;
- guint32 last_written_frame = stack->last_written_frame;
- thread_stack_initialize (stack, stack->capacity * 2);
- memcpy (stack->stack, old_stack, top * sizeof (MonoMethod*));
- memcpy (stack->method_is_jitted, old_method_is_jitted, top * sizeof (guint8));
- memcpy (stack->written_frames, old_written_frames, top * sizeof (guint32));
- g_free (old_stack);
- g_free (old_method_is_jitted);
- g_free (old_written_frames);
- stack->top = top;
- stack->last_saved_top = last_saved_top;
- stack->last_written_frame = last_written_frame;
- }
- stack->stack [stack->top] = method;
- stack->method_is_jitted [stack->top] = method_is_jitted;
- stack->top ++;
-}
-
-static inline void
-thread_stack_push (ProfilerThreadStack *stack, MonoMethod* method) {
- thread_stack_push_jitted (stack, method, FALSE);
-}
-
-static MonoMethod*
-thread_stack_pop (ProfilerThreadStack *stack) {
- if (stack->top > 0) {
- stack->top --;
- if (stack->last_saved_top > stack->top) {
- stack->last_saved_top = stack->top;
- }
- return stack->stack [stack->top];
- } else {
- return NULL;
- }
-}
-
-static MonoMethod*
-thread_stack_top (ProfilerThreadStack *stack) {
- if (stack->top > 0) {
- return stack->stack [stack->top - 1];
- } else {
- return NULL;
- }
-}
-
-static gboolean
-thread_stack_top_is_jitted (ProfilerThreadStack *stack) {
- if (stack->top > 0) {
- return stack->method_is_jitted [stack->top - 1];
- } else {
- return FALSE;
- }
-}
-
-static MonoMethod*
-thread_stack_index_from_top (ProfilerThreadStack *stack, int index) {
- if (stack->top > index) {
- return stack->stack [stack->top - (index + 1)];
- } else {
- return NULL;
- }
-}
-
-static gboolean
-thread_stack_index_from_top_is_jitted (ProfilerThreadStack *stack, int index) {
- if (stack->top > index) {
- return stack->method_is_jitted [stack->top - (index + 1)];
- } else {
- return FALSE;
- }
-}
-
-static inline void
-thread_stack_push_safely (ProfilerThreadStack *stack, MonoMethod* method) {
- if (stack->stack != NULL) {
- thread_stack_push (stack, method);
- }
-}
-
-static inline void
-thread_stack_push_jitted_safely (ProfilerThreadStack *stack, MonoMethod* method, gboolean method_is_jitted) {
- if (stack->stack != NULL) {
- thread_stack_push_jitted (stack, method, method_is_jitted);
- }
-}
-
-static inline int
-thread_stack_count_unsaved_frames (ProfilerThreadStack *stack) {
- int result = stack->top - stack->last_saved_top;
- return (result > 0) ? result : 0;
-}
-
-static inline int
-thread_stack_get_last_written_frame (ProfilerThreadStack *stack) {
- return stack->last_written_frame;
-}
-
-static inline void
-thread_stack_set_last_written_frame (ProfilerThreadStack *stack, int last_written_frame) {
- stack->last_written_frame = last_written_frame;
-}
-
-static inline guint32
-thread_stack_written_frame_at_index (ProfilerThreadStack *stack, int index) {
- return stack->written_frames [index];
-}
-
-static inline void
-thread_stack_write_frame_at_index (ProfilerThreadStack *stack, int index, guint32 method_id_and_is_jitted) {
- stack->written_frames [index] = method_id_and_is_jitted;
-}
-
-static ClassIdMappingElement*
-class_id_mapping_element_get (MonoClass *klass) {
- return g_hash_table_lookup (profiler->classes->table, (gconstpointer) klass);
-}
-
-static MethodIdMappingElement*
-method_id_mapping_element_get (MonoMethod *method) {
- return g_hash_table_lookup (profiler->methods->table, (gconstpointer) method);
-}
-
-#define BITS_TO_BYTES(v) do {\
- (v) += 7;\
- (v) &= ~7;\
- (v) >>= 3;\
-} while (0)
-
-static ClassIdMappingElement*
-class_id_mapping_element_new (MonoClass *klass) {
- ClassIdMappingElement *result = g_new (ClassIdMappingElement, 1);
-
- result->name = mono_type_full_name (mono_class_get_type (klass));
- result->klass = klass;
- result->next_unwritten = profiler->classes->unwritten;
- profiler->classes->unwritten = result;
- result->id = profiler->classes->next_id;
- profiler->classes->next_id ++;
-
- result->data.bitmap.compact = 0;
- result->data.layout.slots = CLASS_LAYOUT_NOT_INITIALIZED;
- result->data.layout.references = CLASS_LAYOUT_NOT_INITIALIZED;
-
- g_hash_table_insert (profiler->classes->table, klass, result);
-
-#if (DEBUG_MAPPING_EVENTS)
- printf ("Created new CLASS mapping element \"%s\" (%p)[%d]\n", result->name, klass, result->id);
-#endif
- return result;
-}
-
-static void
-class_id_mapping_element_build_layout_bitmap (MonoClass *klass, ClassIdMappingElement *klass_id) {
- MonoClass *parent_class = mono_class_get_parent (klass);
- int number_of_reference_fields = 0;
- int max_offset_of_reference_fields = 0;
- ClassIdMappingElement *parent_id;
- gpointer iter;
- MonoClassField *field;
-
-#if (DEBUG_CLASS_BITMAPS)
- printf ("class_id_mapping_element_build_layout_bitmap: building layout for class %s.%s: ", mono_class_get_namespace (klass), mono_class_get_name (klass));
-#endif
-
- if (parent_class != NULL) {
- parent_id = class_id_mapping_element_get (parent_class);
- g_assert (parent_id != NULL);
-
- if (parent_id->data.layout.slots == CLASS_LAYOUT_NOT_INITIALIZED) {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[recursively building bitmap for father class]\n");
-#endif
- class_id_mapping_element_build_layout_bitmap (parent_class, parent_id);
- }
- } else {
- parent_id = NULL;
- }
-
- iter = NULL;
- while ((field = mono_class_get_fields (klass, &iter)) != NULL) {
- MonoType* field_type = mono_field_get_type (field);
- // For now, skip static fields
- if (mono_field_get_flags (field) & 0x0010 /*FIELD_ATTRIBUTE_STATIC*/)
- continue;
-
- if (MONO_TYPE_IS_REFERENCE (field_type)) {
- int field_offset = mono_field_get_offset (field) - sizeof (MonoObject);
- if (field_offset > max_offset_of_reference_fields) {
- max_offset_of_reference_fields = field_offset;
- }
- number_of_reference_fields ++;
- } else {
- MonoClass *field_class = mono_class_from_mono_type (field_type);
- if (field_class && mono_class_is_valuetype (field_class)) {
- ClassIdMappingElement *field_id = class_id_mapping_element_get (field_class);
- g_assert (field_id != NULL);
-
- if (field_id->data.layout.slots == CLASS_LAYOUT_NOT_INITIALIZED) {
- if (field_id != klass_id) {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[recursively building bitmap for field %s]\n", mono_field_get_name (field));
-#endif
- class_id_mapping_element_build_layout_bitmap (field_class, field_id);
- } else {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[breaking recursive bitmap build for field %s]", mono_field_get_name (field));
-
-#endif
- klass_id->data.bitmap.compact = 0;
- klass_id->data.layout.slots = 0;
- klass_id->data.layout.references = 0;
- }
- }
-
- if (field_id->data.layout.references > 0) {
- int field_offset = mono_field_get_offset (field) - sizeof (MonoObject);
- int max_offset_reference_in_field = (field_id->data.layout.slots - 1) * sizeof (gpointer);
-
- if ((field_offset + max_offset_reference_in_field) > max_offset_of_reference_fields) {
- max_offset_of_reference_fields = field_offset + max_offset_reference_in_field;
- }
-
- number_of_reference_fields += field_id->data.layout.references;
- }
- }
- }
- }
-
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[allocating bitmap for class %s.%s (references %d, max offset %d, slots %d)]", mono_class_get_namespace (klass), mono_class_get_name (klass), number_of_reference_fields, max_offset_of_reference_fields, (int)(max_offset_of_reference_fields / sizeof (gpointer)) + 1);
-#endif
- if ((number_of_reference_fields == 0) && ((parent_id == NULL) || (parent_id->data.layout.references == 0))) {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[no references at all]");
-#endif
- klass_id->data.bitmap.compact = 0;
- klass_id->data.layout.slots = 0;
- klass_id->data.layout.references = 0;
- } else {
- if ((parent_id != NULL) && (parent_id->data.layout.references > 0)) {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[parent %s.%s has %d references in %d slots]", mono_class_get_namespace (parent_class), mono_class_get_name (parent_class), parent_id->data.layout.references, parent_id->data.layout.slots);
-#endif
- klass_id->data.layout.slots = parent_id->data.layout.slots;
- klass_id->data.layout.references = parent_id->data.layout.references;
- } else {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[no references from parent]");
-#endif
- klass_id->data.layout.slots = 0;
- klass_id->data.layout.references = 0;
- }
-
- if (number_of_reference_fields > 0) {
- klass_id->data.layout.slots += ((max_offset_of_reference_fields / sizeof (gpointer)) + 1);
- klass_id->data.layout.references += number_of_reference_fields;
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[adding data, going to %d references in %d slots]", klass_id->data.layout.references, klass_id->data.layout.slots);
-#endif
- }
-
- if (klass_id->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[zeroing bitmap]");
-#endif
- klass_id->data.bitmap.compact = 0;
- if ((parent_id != NULL) && (parent_id->data.layout.references > 0)) {
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[copying compact father bitmap]");
-#endif
- klass_id->data.bitmap.compact = parent_id->data.bitmap.compact;
- }
- } else {
- int size_of_bitmap = klass_id->data.layout.slots;
- BITS_TO_BYTES (size_of_bitmap);
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[allocating %d bytes for bitmap]", size_of_bitmap);
-#endif
- klass_id->data.bitmap.extended = g_malloc0 (size_of_bitmap);
- if ((parent_id != NULL) && (parent_id->data.layout.references > 0)) {
- int size_of_father_bitmap = parent_id->data.layout.slots;
- if (size_of_father_bitmap <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- int father_slot;
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[copying %d bits from father bitmap]", size_of_father_bitmap);
-#endif
- for (father_slot = 0; father_slot < size_of_father_bitmap; father_slot ++) {
- if (parent_id->data.bitmap.compact & (((guint64)1) << father_slot)) {
- klass_id->data.bitmap.extended [father_slot >> 3] |= (1 << (father_slot & 7));
- }
- }
- } else {
- BITS_TO_BYTES (size_of_father_bitmap);
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[copying %d bytes from father bitmap]", size_of_father_bitmap);
-#endif
- memcpy (klass_id->data.bitmap.extended, parent_id->data.bitmap.extended, size_of_father_bitmap);
- }
- }
- }
- }
-
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[starting filling iteration]\n");
-#endif
- iter = NULL;
- while ((field = mono_class_get_fields (klass, &iter)) != NULL) {
- MonoType* field_type = mono_field_get_type (field);
- // For now, skip static fields
- if (mono_field_get_flags (field) & 0x0010 /*FIELD_ATTRIBUTE_STATIC*/)
- continue;
-
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[Working on field %s]", mono_field_get_name (field));
-#endif
- if (MONO_TYPE_IS_REFERENCE (field_type)) {
- int field_offset = mono_field_get_offset (field) - sizeof (MonoObject);
- int field_slot;
- g_assert ((field_offset % sizeof (gpointer)) == 0);
- field_slot = field_offset / sizeof (gpointer);
- if (klass_id->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- klass_id->data.bitmap.compact |= (((guint64)1) << field_slot);
- } else {
- klass_id->data.bitmap.extended [field_slot >> 3] |= (1 << (field_slot & 7));
- }
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[reference at offset %d, slot %d]", field_offset, field_slot);
-#endif
- } else {
- MonoClass *field_class = mono_class_from_mono_type (field_type);
- if (field_class && mono_class_is_valuetype (field_class)) {
- ClassIdMappingElement *field_id = class_id_mapping_element_get (field_class);
- int field_offset;
- int field_slot;
-
- g_assert (field_id != NULL);
- field_offset = mono_field_get_offset (field) - sizeof (MonoObject);
- g_assert ((field_id->data.layout.references == 0) || ((field_offset % sizeof (gpointer)) == 0));
- field_slot = field_offset / sizeof (gpointer);
-#if (DEBUG_CLASS_BITMAPS)
- printf ("[value type at offset %d, slot %d, with %d references in %d slots]", field_offset, field_slot, field_id->data.layout.references, field_id->data.layout.slots);
-#endif
-
- if (field_id->data.layout.references > 0) {
- int sub_field_slot;
- if (field_id->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- for (sub_field_slot = 0; sub_field_slot < field_id->data.layout.slots; sub_field_slot ++) {
- if (field_id->data.bitmap.compact & (((guint64)1) << sub_field_slot)) {
- int actual_slot = field_slot + sub_field_slot;
- if (klass_id->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- klass_id->data.bitmap.compact |= (((guint64)1) << actual_slot);
- } else {
- klass_id->data.bitmap.extended [actual_slot >> 3] |= (1 << (actual_slot & 7));
- }
- }
- }
- } else {
- for (sub_field_slot = 0; sub_field_slot < field_id->data.layout.slots; sub_field_slot ++) {
- if (field_id->data.bitmap.extended [sub_field_slot >> 3] & (1 << (sub_field_slot & 7))) {
- int actual_slot = field_slot + sub_field_slot;
- if (klass_id->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- klass_id->data.bitmap.compact |= (((guint64)1) << actual_slot);
- } else {
- klass_id->data.bitmap.extended [actual_slot >> 3] |= (1 << (actual_slot & 7));
- }
- }
- }
- }
- }
- }
- }
- }
-#if (DEBUG_CLASS_BITMAPS)
- do {
- int slot;
- printf ("\nLayot of class \"%s.%s\": references %d, slots %d, bitmap {", mono_class_get_namespace (klass), mono_class_get_name (klass), klass_id->data.layout.references, klass_id->data.layout.slots);
- for (slot = 0; slot < klass_id->data.layout.slots; slot ++) {
- if (klass_id->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- if (klass_id->data.bitmap.compact & (((guint64)1) << slot)) {
- printf (" 1");
- } else {
- printf (" 0");
- }
- } else {
- if (klass_id->data.bitmap.extended [slot >> 3] & (1 << (slot & 7))) {
- printf (" 1");
- } else {
- printf (" 0");
- }
-; }
-
- }
- printf (" }\n");
-
- } while (0);
-#endif
-}
-
-static MethodIdMappingElement*
-method_id_mapping_element_new (MonoMethod *method) {
- MethodIdMappingElement *result = g_new (MethodIdMappingElement, 1);
- char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
-
- result->name = g_strdup_printf ("%s (%s)", mono_method_get_name (method), signature);
- g_free (signature);
- result->method = method;
- result->next_unwritten = profiler->methods->unwritten;
- profiler->methods->unwritten = result;
- result->id = profiler->methods->next_id;
- profiler->methods->next_id ++;
- g_hash_table_insert (profiler->methods->table, method, result);
-
- result->data.code_start = NULL;
- result->data.code_size = 0;
-
-#if (DEBUG_MAPPING_EVENTS)
- printf ("Created new METHOD mapping element \"%s\" (%p)[%d]\n", result->name, method, result->id);
-#endif
- return result;
-}
-
-
-static void
-method_id_mapping_element_destroy (gpointer element) {
- MethodIdMappingElement *e = (MethodIdMappingElement*) element;
- if (e->name)
- g_free (e->name);
- g_free (element);
-}
-
-static void
-class_id_mapping_element_destroy (gpointer element) {
- ClassIdMappingElement *e = (ClassIdMappingElement*) element;
- if (e->name)
- g_free (e->name);
- if ((e->data.layout.slots != CLASS_LAYOUT_NOT_INITIALIZED) && (e->data.layout.slots > CLASS_LAYOUT_PACKED_BITMAP_SIZE))
- g_free (e->data.bitmap.extended);
- g_free (element);
-}
-
-static MethodIdMapping*
-method_id_mapping_new (void) {
- MethodIdMapping *result = g_new (MethodIdMapping, 1);
- //result->table = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, method_id_mapping_element_destroy);
- result->table = g_hash_table_new_full (g_direct_hash, NULL, NULL, method_id_mapping_element_destroy);
- result->unwritten = NULL;
- result->next_id = 1;
- return result;
-}
-
-static ClassIdMapping*
-class_id_mapping_new (void) {
- ClassIdMapping *result = g_new (ClassIdMapping, 1);
- //result->table = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, class_id_mapping_element_destroy);
- result->table = g_hash_table_new_full (g_direct_hash, NULL, NULL, class_id_mapping_element_destroy);
- result->unwritten = NULL;
- result->next_id = 1;
- return result;
-}
-
-static void
-method_id_mapping_destroy (MethodIdMapping *map) {
- g_hash_table_destroy (map->table);
- g_free (map);
-}
-
-static void
-class_id_mapping_destroy (ClassIdMapping *map) {
- g_hash_table_destroy (map->table);
- g_free (map);
-}
-
-#if (DEBUG_LOAD_EVENTS)
-static void
-print_load_event (const char *event_name, GHashTable *table, gpointer item, LoadedElement *element);
-#endif
-
-static LoadedElement*
-loaded_element_load_start (GHashTable *table, gpointer item) {
- LoadedElement *element = g_new0 (LoadedElement, 1);
- element->id = profiler->loaded_element_next_free_id;
- profiler->loaded_element_next_free_id ++;
-#if (DEBUG_LOAD_EVENTS)
- print_load_event ("LOAD START", table, item, element);
-#endif
- MONO_PROFILER_GET_CURRENT_COUNTER (element->load_start_counter);
- g_hash_table_insert (table, item, element);
- return element;
-}
-
-static LoadedElement*
-loaded_element_load_end (GHashTable *table, gpointer item, char *name) {
- LoadedElement *element = g_hash_table_lookup (table, item);
-#if (DEBUG_LOAD_EVENTS)
- print_load_event ("LOAD END", table, item, element);
-#endif
- g_assert (element != NULL);
- MONO_PROFILER_GET_CURRENT_COUNTER (element->load_end_counter);
- element->name = name;
- element->loaded = TRUE;
- return element;
-}
-
-static LoadedElement*
-loaded_element_unload_start (GHashTable *table, gpointer item) {
- LoadedElement *element = g_hash_table_lookup (table, item);
-#if (DEBUG_LOAD_EVENTS)
- print_load_event ("UNLOAD START", table, item, element);
-#endif
- g_assert (element != NULL);
- MONO_PROFILER_GET_CURRENT_COUNTER (element->unload_start_counter);
- return element;
-}
-
-static LoadedElement*
-loaded_element_unload_end (GHashTable *table, gpointer item) {
- LoadedElement *element = g_hash_table_lookup (table, item);
-#if (DEBUG_LOAD_EVENTS)
- print_load_event ("UNLOAD END", table, item, element);
-#endif
- g_assert (element != NULL);
- MONO_PROFILER_GET_CURRENT_COUNTER (element->unload_end_counter);
- element->unloaded = TRUE;
- return element;
-}
-
-static LoadedElement*
-loaded_element_find (GHashTable *table, gpointer item) {
- LoadedElement *element = g_hash_table_lookup (table, item);
- return element;
-}
-
-static guint32
-loaded_element_get_id (GHashTable *table, gpointer item) {
- LoadedElement *element = loaded_element_find (table, item);
- if (element != NULL) {
- return element->id;
- } else {
- return 0;
- }
-}
-
-static void
-loaded_element_destroy (gpointer element) {
- if (((LoadedElement*)element)->name)
- g_free (((LoadedElement*)element)->name);
- g_free (element);
-}
-
-#if (DEBUG_LOAD_EVENTS)
-static void
-print_load_event (const char *event_name, GHashTable *table, gpointer item, LoadedElement *element) {
- const char* item_name;
- char* item_info;
-
- if (table == profiler->loaded_assemblies) {
- //item_info = g_strdup_printf("ASSEMBLY %p (dynamic %d)", item, mono_image_is_dynamic (mono_assembly_get_image((MonoAssembly*)item)));
- item_info = g_strdup_printf("ASSEMBLY %p", item);
- } else if (table == profiler->loaded_modules) {
- //item_info = g_strdup_printf("MODULE %p (dynamic %d)", item, mono_image_is_dynamic ((MonoImage*)item));
- item_info = g_strdup_printf("MODULE %p", item);
- } else if (table == profiler->loaded_appdomains) {
- item_info = g_strdup_printf("APPDOMAIN %p (id %d)", item, mono_domain_get_id ((MonoDomain*)item));
- } else {
- item_info = NULL;
- g_assert_not_reached ();
- }
-
- if (element != NULL) {
- item_name = element->name;
- } else {
- item_name = "<NULL>";
- }
-
- printf ("%s EVENT for %s (%s [id %d])\n", event_name, item_info, item_name, element->id);
- g_free (item_info);
-}
-#endif
-
-static void
-profiler_heap_shot_object_buffers_destroy (ProfilerHeapShotObjectBuffer *buffer) {
- while (buffer != NULL) {
- ProfilerHeapShotObjectBuffer *next = buffer->next;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_object_buffers_destroy: destroyed buffer %p (%p-%p)\n", buffer, & (buffer->buffer [0]), buffer->end);
-#endif
- g_free (buffer);
- buffer = next;
- }
-}
-
-static ProfilerHeapShotObjectBuffer*
-profiler_heap_shot_object_buffer_new (ProfilerPerThreadData *data) {
- ProfilerHeapShotObjectBuffer *buffer;
- ProfilerHeapShotObjectBuffer *result = g_new (ProfilerHeapShotObjectBuffer, 1);
- result->next_free_slot = & (result->buffer [0]);
- result->end = & (result->buffer [PROFILER_HEAP_SHOT_OBJECT_BUFFER_SIZE]);
- result->first_unprocessed_slot = & (result->buffer [0]);
- result->next = data->heap_shot_object_buffers;
- data->heap_shot_object_buffers = result;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_object_buffer_new: created buffer %p (%p-%p)\n", result, result->next_free_slot, result->end);
-#endif
- for (buffer = result; buffer != NULL; buffer = buffer->next) {
- ProfilerHeapShotObjectBuffer *last = buffer->next;
- if ((last != NULL) && (last->first_unprocessed_slot == last->end)) {
- buffer->next = NULL;
- profiler_heap_shot_object_buffers_destroy (last);
- }
- }
-
- return result;
-}
-
-static ProfilerHeapShotWriteJob*
-profiler_heap_shot_write_job_new (gboolean heap_shot_was_requested, gboolean dump_heap_data, guint32 collection) {
- ProfilerHeapShotWriteJob *job = g_new (ProfilerHeapShotWriteJob, 1);
- job->next = NULL;
- job->next_unwritten = NULL;
-
- if (profiler->action_flags.unreachable_objects || dump_heap_data) {
- job->buffers = g_new (ProfilerHeapShotWriteBuffer, 1);
- job->buffers->next = NULL;
- job->last_next = & (job->buffers->next);
- job->start = & (job->buffers->buffer [0]);
- job->cursor = job->start;
- job->end = & (job->buffers->buffer [PROFILER_HEAP_SHOT_WRITE_BUFFER_SIZE]);
- } else {
- job->buffers = NULL;
- job->last_next = NULL;
- job->start = NULL;
- job->cursor = NULL;
- job->end = NULL;
- }
- job->full_buffers = 0;
-
- if (profiler->action_flags.collection_summary) {
- job->summary.capacity = profiler->classes->next_id;
- job->summary.per_class_data = g_new0 (ProfilerHeapShotClassSummary, job->summary.capacity);
- } else {
- job->summary.capacity = 0;
- job->summary.per_class_data = NULL;
- }
-
- job->heap_shot_was_requested = heap_shot_was_requested;
- job->collection = collection;
- job->dump_heap_data = dump_heap_data;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_job_new: created job %p with buffer %p(%p-%p) (collection %d, dump %d)\n", job, job->buffers, job->start, job->end, collection, dump_heap_data);
-#endif
- return job;
-}
-
-static gboolean
-profiler_heap_shot_write_job_has_data (ProfilerHeapShotWriteJob *job) {
- return ((job->buffers != NULL) || (job->summary.capacity > 0));
-}
-
-static void
-profiler_heap_shot_write_job_add_buffer (ProfilerHeapShotWriteJob *job, gpointer value) {
- ProfilerHeapShotWriteBuffer *buffer = g_new (ProfilerHeapShotWriteBuffer, 1);
- buffer->next = NULL;
- *(job->last_next) = buffer;
- job->last_next = & (buffer->next);
- job->full_buffers ++;
- buffer->buffer [0] = value;
- job->start = & (buffer->buffer [0]);
- job->cursor = & (buffer->buffer [1]);
- job->end = & (buffer->buffer [PROFILER_HEAP_SHOT_WRITE_BUFFER_SIZE]);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_job_add_buffer: in job %p, added buffer %p(%p-%p) with value %p at address %p (cursor now %p)\n", job, buffer, job->start, job->end, value, &(buffer->buffer [0]), job->cursor);
- do {
- ProfilerHeapShotWriteBuffer *current_buffer;
- for (current_buffer = job->buffers; current_buffer != NULL; current_buffer = current_buffer->next) {
- printf ("profiler_heap_shot_write_job_add_buffer: now job %p has buffer %p\n", job, current_buffer);
- }
- } while (0);
-#endif
-}
-
-static void
-profiler_heap_shot_write_job_free_buffers (ProfilerHeapShotWriteJob *job) {
- ProfilerHeapShotWriteBuffer *buffer = job->buffers;
-
- while (buffer != NULL) {
- ProfilerHeapShotWriteBuffer *next = buffer->next;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_job_free_buffers: in job %p, freeing buffer %p\n", job, buffer);
-#endif
- g_free (buffer);
- buffer = next;
- }
-
- job->buffers = NULL;
-
- if (job->summary.per_class_data != NULL) {
- g_free (job->summary.per_class_data);
- job->summary.per_class_data = NULL;
- }
- job->summary.capacity = 0;
-}
-
-static void
-profiler_heap_shot_write_block (ProfilerHeapShotWriteJob *job);
-
-static void
-profiler_process_heap_shot_write_jobs (void) {
- gboolean done = FALSE;
-
- while (!done) {
- ProfilerHeapShotWriteJob *current_job = profiler->heap_shot_write_jobs;
- ProfilerHeapShotWriteJob *previous_job = NULL;
- ProfilerHeapShotWriteJob *next_job;
-
- done = TRUE;
- while (current_job != NULL) {
- next_job = current_job->next_unwritten;
-
- if (next_job != NULL) {
- if (profiler_heap_shot_write_job_has_data (current_job)) {
- done = FALSE;
- }
- if (! profiler_heap_shot_write_job_has_data (next_job)) {
- current_job->next_unwritten = NULL;
- next_job = NULL;
- }
- } else {
- if (profiler_heap_shot_write_job_has_data (current_job)) {
- LOG_WRITER_THREAD ("profiler_process_heap_shot_write_jobs: writing...");
- profiler_heap_shot_write_block (current_job);
- LOG_WRITER_THREAD ("profiler_process_heap_shot_write_jobs: done");
- if (previous_job != NULL) {
- previous_job->next_unwritten = NULL;
- }
- }
- }
-
- previous_job = current_job;
- current_job = next_job;
- }
- }
-}
-
-static void
-profiler_free_heap_shot_write_jobs (void) {
- ProfilerHeapShotWriteJob *current_job = profiler->heap_shot_write_jobs;
- ProfilerHeapShotWriteJob *next_job;
-
- if (current_job != NULL) {
- while (current_job->next_unwritten != NULL) {
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_free_heap_shot_write_jobs: job %p must not be freed\n", current_job);
-#endif
- current_job = current_job->next_unwritten;
- }
-
- next_job = current_job->next;
- current_job->next = NULL;
- current_job = next_job;
-
- while (current_job != NULL) {
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_free_heap_shot_write_jobs: job %p will be freed\n", current_job);
-#endif
- next_job = current_job->next;
- profiler_heap_shot_write_job_free_buffers (current_job);
- g_free (current_job);
- current_job = next_job;
- }
- }
-}
-
-static void
-profiler_destroy_heap_shot_write_jobs (void) {
- ProfilerHeapShotWriteJob *current_job = profiler->heap_shot_write_jobs;
- ProfilerHeapShotWriteJob *next_job;
-
- while (current_job != NULL) {
- next_job = current_job->next;
- profiler_heap_shot_write_job_free_buffers (current_job);
- g_free (current_job);
- current_job = next_job;
- }
-}
-
-static void
-profiler_add_heap_shot_write_job (ProfilerHeapShotWriteJob *job) {
- job->next = profiler->heap_shot_write_jobs;
- job->next_unwritten = job->next;
- profiler->heap_shot_write_jobs = job;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_add_heap_shot_write_job: added job %p\n", job);
-#endif
-}
-
-#if DEBUG_HEAP_PROFILER
-#define STORE_ALLOCATED_OBJECT_MESSAGE1(d,o) printf ("STORE_ALLOCATED_OBJECT[TID %ld]: storing object %p at address %p\n", (d)->thread_id, (o), (d)->heap_shot_object_buffers->next_free_slot)
-#define STORE_ALLOCATED_OBJECT_MESSAGE2(d,o) printf ("STORE_ALLOCATED_OBJECT[TID %ld]: storing object %p at address %p in new buffer %p\n", (d)->thread_id, (o), buffer->next_free_slot, buffer)
-#else
-#define STORE_ALLOCATED_OBJECT_MESSAGE1(d,o)
-#define STORE_ALLOCATED_OBJECT_MESSAGE2(d,o)
-#endif
-#define STORE_ALLOCATED_OBJECT(d,o) do {\
- if ((d)->heap_shot_object_buffers->next_free_slot < (d)->heap_shot_object_buffers->end) {\
- STORE_ALLOCATED_OBJECT_MESSAGE1 ((d), (o));\
- *((d)->heap_shot_object_buffers->next_free_slot) = (o);\
- (d)->heap_shot_object_buffers->next_free_slot ++;\
- } else {\
- ProfilerHeapShotObjectBuffer *buffer = profiler_heap_shot_object_buffer_new (d);\
- STORE_ALLOCATED_OBJECT_MESSAGE2 ((d), (o));\
- *((buffer)->next_free_slot) = (o);\
- (buffer)->next_free_slot ++;\
- }\
-} while (0)
-
-static ProfilerPerThreadData*
-profiler_per_thread_data_new (guint32 buffer_size)
-{
- ProfilerPerThreadData *data = g_new (ProfilerPerThreadData, 1);
-
- data->events = g_new0 (ProfilerEventData, buffer_size);
- data->next_free_event = data->events;
- data->next_unreserved_event = data->events;
- data->end_event = data->events + (buffer_size - 1);
- data->first_unwritten_event = data->events;
- data->first_unmapped_event = data->events;
- MONO_PROFILER_GET_CURRENT_COUNTER (data->start_event_counter);
- data->last_event_counter = data->start_event_counter;
- data->thread_id = CURRENT_THREAD_ID ();
- data->heap_shot_object_buffers = NULL;
- if ((profiler->action_flags.unreachable_objects == TRUE) ||
- (profiler->action_flags.heap_shot == TRUE) ||
- (profiler->action_flags.collection_summary == TRUE)) {
- profiler_heap_shot_object_buffer_new (data);
- }
- if (profiler->action_flags.track_stack) {
- thread_stack_initialize (&(data->stack), 64);
- } else {
- thread_stack_initialize_empty (&(data->stack));
- }
- return data;
-}
-
-static void
-profiler_per_thread_data_destroy (ProfilerPerThreadData *data) {
- g_free (data->events);
- profiler_heap_shot_object_buffers_destroy (data->heap_shot_object_buffers);
- thread_stack_free (&(data->stack));
- g_free (data);
-}
-
-static ProfilerStatisticalData*
-profiler_statistical_data_new (MonoProfiler *profiler) {
- int buffer_size = profiler->statistical_buffer_size * (profiler->statistical_call_chain_depth + 1);
- ProfilerStatisticalData *data = g_new (ProfilerStatisticalData, 1);
-
- data->hits = g_new0 (ProfilerStatisticalHit, buffer_size);
- data->next_free_index = 0;
- data->end_index = profiler->statistical_buffer_size;
- data->first_unwritten_index = 0;
-
- return data;
-}
-
-static void
-profiler_statistical_data_destroy (ProfilerStatisticalData *data) {
- g_free (data->hits);
- g_free (data);
-}
-
-static ProfilerCodeBufferArray*
-profiler_code_buffer_array_new (ProfilerCodeBufferArray *child) {
- ProfilerCodeBufferArray *result = g_new0 (ProfilerCodeBufferArray, 1);
- if (child == NULL) {
- result->level = 0;
- } else {
- result->level = child->level + 1;
- result->number_of_buffers = 1;
- result->buffers [0].info.data.sub_buffers = child;
- result->buffers [0].start = child->buffers [0].start;
- result->buffers [0].end = child->buffers [child->number_of_buffers - 1].end;
- }
- return result;
-}
-
-static void
-profiler_code_buffer_array_destroy (ProfilerCodeBufferArray *buffers) {
- if (buffers->level > 0) {
- int i;
- for (i = 0; i < buffers->number_of_buffers; i++) {
- ProfilerCodeBufferArray *sub_buffers = buffers->buffers [i].info.data.sub_buffers;
- profiler_code_buffer_array_destroy (sub_buffers);
- }
- }
- g_free (buffers);
-}
-
-static gboolean
-profiler_code_buffer_array_is_full (ProfilerCodeBufferArray *buffers) {
- while (buffers->level > 0) {
- ProfilerCodeBufferArray *next;
- if (buffers->number_of_buffers < PROFILER_CODE_BUFFER_ARRAY_SIZE) {
- return FALSE;
- }
- next = buffers->buffers [PROFILER_CODE_BUFFER_ARRAY_SIZE - 1].info.data.sub_buffers;
- if (next->level < (buffers->level - 1)) {
- return FALSE;
- }
- buffers = next;
- }
- return (buffers->number_of_buffers == PROFILER_CODE_BUFFER_ARRAY_SIZE);
-}
-
-static ProfilerCodeBufferArray*
-profiler_code_buffer_add (ProfilerCodeBufferArray *buffers, gpointer *buffer, int size, MonoProfilerCodeBufferType type, void *data) {
- if (buffers == NULL) {
- buffers = profiler_code_buffer_array_new (NULL);
- }
-
- if (profiler_code_buffer_array_is_full (buffers)) {
- ProfilerCodeBufferArray *new_slot = profiler_code_buffer_add (NULL, buffer, size, type, data);
- buffers = profiler_code_buffer_array_new (buffers);
- buffers->buffers [buffers->number_of_buffers].info.data.sub_buffers = new_slot;
- buffers->buffers [buffers->number_of_buffers].start = new_slot->buffers [0].start;
- buffers->buffers [buffers->number_of_buffers].end = new_slot->buffers [new_slot->number_of_buffers - 1].end;
- buffers->number_of_buffers ++;
- } else if (buffers->level > 0) {
- ProfilerCodeBufferArray *new_slot = profiler_code_buffer_add (buffers->buffers [buffers->number_of_buffers - 1].info.data.sub_buffers, buffer, size, type, data);
- buffers->buffers [buffers->number_of_buffers - 1].info.data.sub_buffers = new_slot;
- buffers->buffers [buffers->number_of_buffers - 1].start = new_slot->buffers [0].start;
- buffers->buffers [buffers->number_of_buffers - 1].end = new_slot->buffers [new_slot->number_of_buffers - 1].end;
- } else {
- buffers->buffers [buffers->number_of_buffers].start = buffer;
- buffers->buffers [buffers->number_of_buffers].end = (((guint8*) buffer) + size);
- buffers->buffers [buffers->number_of_buffers].info.type = type;
- switch (type) {
- case MONO_PROFILER_CODE_BUFFER_UNKNOWN:
- buffers->buffers [buffers->number_of_buffers].info.data.data = NULL;
- break;
- case MONO_PROFILER_CODE_BUFFER_METHOD:
- buffers->buffers [buffers->number_of_buffers].info.data.method = data;
- break;
- default:
- buffers->buffers [buffers->number_of_buffers].info.type = MONO_PROFILER_CODE_BUFFER_UNKNOWN;
- buffers->buffers [buffers->number_of_buffers].info.data.data = NULL;
- }
- buffers->number_of_buffers ++;
- }
- return buffers;
-}
-
-static ProfilerCodeBuffer*
-profiler_code_buffer_find (ProfilerCodeBufferArray *buffers, gpointer *address) {
- if (buffers != NULL) {
- ProfilerCodeBuffer *result = NULL;
- do {
- int low = 0;
- int high = buffers->number_of_buffers - 1;
-
- while (high != low) {
- int middle = low + ((high - low) >> 1);
-
- if ((guint8*) address < (guint8*) buffers->buffers [low].start) {
- return NULL;
- }
- if ((guint8*) address >= (guint8*) buffers->buffers [high].end) {
- return NULL;
- }
-
- if ((guint8*) address < (guint8*) buffers->buffers [middle].start) {
- high = middle - 1;
- if (high < low) {
- high = low;
- }
- } else if ((guint8*) address >= (guint8*) buffers->buffers [middle].end) {
- low = middle + 1;
- if (low > high) {
- low = high;
- }
- } else {
- high = middle;
- low = middle;
- }
- }
-
- if (((guint8*) address >= (guint8*) buffers->buffers [low].start) && ((guint8*) address < (guint8*) buffers->buffers [low].end)) {
- if (buffers->level == 0) {
- result = & (buffers->buffers [low]);
- } else {
- buffers = buffers->buffers [low].info.data.sub_buffers;
- }
- } else {
- return NULL;
- }
- } while (result == NULL);
- return result;
- } else {
- return NULL;
- }
-}
-
-static void
-profiler_code_chunk_initialize (ProfilerCodeChunk *chunk, gpointer memory, gsize size) {
- chunk->buffers = profiler_code_buffer_array_new (NULL);
- chunk->destroyed = FALSE;
- chunk->start = memory;
- chunk->end = ((guint8*)memory) + size;
-}
-
-static void
-profiler_code_chunk_cleanup (ProfilerCodeChunk *chunk) {
- if (chunk->buffers != NULL) {
- profiler_code_buffer_array_destroy (chunk->buffers);
- chunk->buffers = NULL;
- }
- chunk->start = NULL;
- chunk->end = NULL;
-}
-
-static void
-profiler_code_chunks_initialize (ProfilerCodeChunks *chunks) {
- chunks->capacity = 32;
- chunks->chunks = g_new0 (ProfilerCodeChunk, 32);
- chunks->number_of_chunks = 0;
-}
-
-static void
-profiler_code_chunks_cleanup (ProfilerCodeChunks *chunks) {
- int i;
- for (i = 0; i < chunks->number_of_chunks; i++) {
- profiler_code_chunk_cleanup (& (chunks->chunks [i]));
- }
- chunks->capacity = 0;
- chunks->number_of_chunks = 0;
- g_free (chunks->chunks);
- chunks->chunks = NULL;
-}
-
-static int
-compare_code_chunks (const void* c1, const void* c2) {
- ProfilerCodeChunk *chunk1 = (ProfilerCodeChunk*) c1;
- ProfilerCodeChunk *chunk2 = (ProfilerCodeChunk*) c2;
- return ((guint8*) chunk1->end < (guint8*) chunk2->start) ? -1 : (((guint8*) chunk1->start >= (guint8*) chunk2->end) ? 1 : 0);
-}
-
-static int
-compare_address_and_code_chunk (const void* a, const void* c) {
- gpointer address = (gpointer) a;
- ProfilerCodeChunk *chunk = (ProfilerCodeChunk*) c;
- return ((guint8*) address < (guint8*) chunk->start) ? -1 : (((guint8*) address >= (guint8*) chunk->end) ? 1 : 0);
-}
-
-static void
-profiler_code_chunks_sort (ProfilerCodeChunks *chunks) {
- qsort (chunks->chunks, chunks->number_of_chunks, sizeof (ProfilerCodeChunk), compare_code_chunks);
-}
-
-static ProfilerCodeChunk*
-profiler_code_chunk_find (ProfilerCodeChunks *chunks, gpointer address) {
- return bsearch (address, chunks->chunks, chunks->number_of_chunks, sizeof (ProfilerCodeChunk), compare_address_and_code_chunk);
-}
-
-static ProfilerCodeChunk*
-profiler_code_chunk_new (ProfilerCodeChunks *chunks, gpointer memory, gsize size) {
- ProfilerCodeChunk *result;
-
- if (chunks->number_of_chunks == chunks->capacity) {
- ProfilerCodeChunk *new_chunks = g_new0 (ProfilerCodeChunk, chunks->capacity * 2);
- memcpy (new_chunks, chunks->chunks, chunks->capacity * sizeof (ProfilerCodeChunk));
- chunks->capacity *= 2;
- g_free (chunks->chunks);
- chunks->chunks = new_chunks;
- }
-
- result = & (chunks->chunks [chunks->number_of_chunks]);
- chunks->number_of_chunks ++;
- profiler_code_chunk_initialize (result, memory, size);
- profiler_code_chunks_sort (chunks);
- return result;
-}
-
-static int
-profiler_code_chunk_to_index (ProfilerCodeChunks *chunks, ProfilerCodeChunk *chunk) {
- return (int) (chunk - chunks->chunks);
-}
-
-static void
-profiler_code_chunk_remove (ProfilerCodeChunks *chunks, ProfilerCodeChunk *chunk) {
- int index = profiler_code_chunk_to_index (chunks, chunk);
-
- profiler_code_chunk_cleanup (chunk);
- if ((index >= 0) && (index < chunks->number_of_chunks)) {
- memmove (chunk, chunk + 1, (chunks->number_of_chunks - index) * sizeof (ProfilerCodeChunk));
- }
-}
-
-/* This assumes the profiler lock is held */
-static ProfilerCodeBuffer*
-profiler_code_buffer_from_address (MonoProfiler *prof, gpointer address) {
- ProfilerCodeChunks *chunks = & (prof->code_chunks);
-
- ProfilerCodeChunk *chunk = profiler_code_chunk_find (chunks, address);
- if (chunk != NULL) {
- return profiler_code_buffer_find (chunk->buffers, address);
- } else {
- return NULL;
- }
-}
-
-static void
-profiler_code_chunk_new_callback (MonoProfiler *prof, gpointer address, int size) {
- ProfilerCodeChunks *chunks = & (prof->code_chunks);
-
- if (prof->code_chunks.chunks != NULL) {
- LOCK_PROFILER ();
- profiler_code_chunk_new (chunks, address, size);
- UNLOCK_PROFILER ();
- }
-}
-
-static void
-profiler_code_chunk_destroy_callback (MonoProfiler *prof, gpointer address) {
- ProfilerCodeChunks *chunks = & (prof->code_chunks);
- ProfilerCodeChunk *chunk;
-
- if (prof->code_chunks.chunks != NULL) {
- LOCK_PROFILER ();
- chunk = profiler_code_chunk_find (chunks, address);
- if (chunk != NULL) {
- profiler_code_chunk_remove (chunks, chunk);
- }
- UNLOCK_PROFILER ();
- }
-}
-
-static void
-profiler_code_buffer_new_callback (MonoProfiler *prof, gpointer address, int size, MonoProfilerCodeBufferType type, void *data) {
- ProfilerCodeChunks *chunks = & (prof->code_chunks);
- ProfilerCodeChunk *chunk;
-
- if (prof->code_chunks.chunks != NULL) {
- LOCK_PROFILER ();
- chunk = profiler_code_chunk_find (chunks, address);
- if (chunk != NULL) {
- chunk->buffers = profiler_code_buffer_add (chunk->buffers, address, size, type, data);
- }
- UNLOCK_PROFILER ();
- }
-}
-
-static void
-profiler_add_write_buffer (void) {
- if (profiler->current_write_buffer->next == NULL) {
- profiler->current_write_buffer->next = g_malloc (sizeof (ProfilerFileWriteBuffer) + PROFILER_FILE_WRITE_BUFFER_SIZE);
- profiler->current_write_buffer->next->next = NULL;
-
- //printf ("Added next buffer %p, to buffer %p\n", profiler->current_write_buffer->next, profiler->current_write_buffer);
-
- }
- profiler->current_write_buffer = profiler->current_write_buffer->next;
- profiler->current_write_position = 0;
- profiler->full_write_buffers ++;
-}
-
-static void
-profiler_free_write_buffers (void) {
- ProfilerFileWriteBuffer *current_buffer = profiler->write_buffers;
- while (current_buffer != NULL) {
- ProfilerFileWriteBuffer *next_buffer = current_buffer->next;
-
- //printf ("Freeing write buffer %p, next is %p\n", current_buffer, next_buffer);
-
- g_free (current_buffer);
- current_buffer = next_buffer;
- }
-}
-
-#define WRITE_BYTE(b) do {\
- if (profiler->current_write_position >= PROFILER_FILE_WRITE_BUFFER_SIZE) {\
- profiler_add_write_buffer ();\
- }\
- profiler->current_write_buffer->buffer [profiler->current_write_position] = (b);\
- profiler->current_write_position ++;\
-} while (0)
-
-#if (DEBUG_FILE_WRITES)
-static int bytes_written = 0;
-#endif
-
-static void
-write_current_block (guint16 code) {
- guint32 size = (profiler->full_write_buffers * PROFILER_FILE_WRITE_BUFFER_SIZE) + profiler->current_write_position;
- ProfilerFileWriteBuffer *current_buffer = profiler->write_buffers;
- guint64 current_counter;
- guint32 counter_delta;
- guint8 header [10];
-
- MONO_PROFILER_GET_CURRENT_COUNTER (current_counter);
- if (profiler->last_header_counter != 0) {
- counter_delta = current_counter - profiler->last_header_counter;
- } else {
- counter_delta = 0;
- }
- profiler->last_header_counter = current_counter;
-
- header [0] = code & 0xff;
- header [1] = (code >> 8) & 0xff;
- header [2] = size & 0xff;
- header [3] = (size >> 8) & 0xff;
- header [4] = (size >> 16) & 0xff;
- header [5] = (size >> 24) & 0xff;
- header [6] = counter_delta & 0xff;
- header [7] = (counter_delta >> 8) & 0xff;
- header [8] = (counter_delta >> 16) & 0xff;
- header [9] = (counter_delta >> 24) & 0xff;
-
-#if (DEBUG_FILE_WRITES)
- printf ("write_current_block: writing header (code %d) at offset %d\n", code, bytes_written);
- bytes_written += 10;
-#endif
- WRITE_BUFFER (& (header [0]), 10);
-
- while ((current_buffer != NULL) && (profiler->full_write_buffers > 0)) {
-#if (DEBUG_FILE_WRITES)
- printf ("write_current_block: writing buffer (size %d)\n", PROFILER_FILE_WRITE_BUFFER_SIZE);
- bytes_written += PROFILER_FILE_WRITE_BUFFER_SIZE;
-#endif
- WRITE_BUFFER (& (current_buffer->buffer [0]), PROFILER_FILE_WRITE_BUFFER_SIZE);
- profiler->full_write_buffers --;
- current_buffer = current_buffer->next;
- }
- if (profiler->current_write_position > 0) {
-#if (DEBUG_FILE_WRITES)
- printf ("write_current_block: writing last buffer (size %d)\n", profiler->current_write_position);
- bytes_written += profiler->current_write_position;
-#endif
- WRITE_BUFFER (& (current_buffer->buffer [0]), profiler->current_write_position);
- }
- FLUSH_FILE ();
-#if (DEBUG_FILE_WRITES)
- printf ("write_current_block: buffers flushed (file size %d)\n", bytes_written);
-#endif
-
- profiler->current_write_buffer = profiler->write_buffers;
- profiler->current_write_position = 0;
- profiler->full_write_buffers = 0;
-}
-
-
-#define SEVEN_BITS_MASK (0x7f)
-#define EIGHT_BIT_MASK (0x80)
-
-static void
-write_uint32 (guint32 value) {
- while (value > SEVEN_BITS_MASK) {
- WRITE_BYTE (value & SEVEN_BITS_MASK);
- value >>= 7;
- }
- WRITE_BYTE (value | EIGHT_BIT_MASK);
-}
-static void
-write_uint64 (guint64 value) {
- while (value > SEVEN_BITS_MASK) {
- WRITE_BYTE (value & SEVEN_BITS_MASK);
- value >>= 7;
- }
- WRITE_BYTE (value | EIGHT_BIT_MASK);
-}
-static void
-write_string (const char *string) {
- while (*string != 0) {
- WRITE_BYTE (*string);
- string ++;
- }
- WRITE_BYTE (0);
-}
-
-static void write_clock_data (void);
-static void
-write_directives_block (gboolean start) {
- write_clock_data ();
-
- if (start) {
- if (profiler->action_flags.save_allocation_caller) {
- write_uint32 (MONO_PROFILER_DIRECTIVE_ALLOCATIONS_CARRY_CALLER);
- }
- if (profiler->action_flags.save_allocation_stack || profiler->action_flags.track_calls) {
- write_uint32 (MONO_PROFILER_DIRECTIVE_ALLOCATIONS_HAVE_STACK);
- }
- if (profiler->action_flags.allocations_carry_id) {
- write_uint32 (MONO_PROFILER_DIRECTIVE_ALLOCATIONS_CARRY_ID);
- }
- write_uint32 (MONO_PROFILER_DIRECTIVE_LOADED_ELEMENTS_CARRY_ID);
- write_uint32 (MONO_PROFILER_DIRECTIVE_CLASSES_CARRY_ASSEMBLY_ID);
- write_uint32 (MONO_PROFILER_DIRECTIVE_METHODS_CARRY_WRAPPER_FLAG);
- }
- write_uint32 (MONO_PROFILER_DIRECTIVE_END);
-
- write_clock_data ();
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_DIRECTIVES);
-}
-
-#if DEBUG_HEAP_PROFILER
-#define WRITE_HEAP_SHOT_JOB_VALUE_MESSAGE(v,c) printf ("WRITE_HEAP_SHOT_JOB_VALUE: writing value %p at cursor %p\n", (v), (c))
-#else
-#define WRITE_HEAP_SHOT_JOB_VALUE_MESSAGE(v,c)
-#endif
-#define WRITE_HEAP_SHOT_JOB_VALUE(j,v) do {\
- if ((j)->cursor < (j)->end) {\
- WRITE_HEAP_SHOT_JOB_VALUE_MESSAGE ((v), ((j)->cursor));\
- *((j)->cursor) = (v);\
- (j)->cursor ++;\
- } else {\
- profiler_heap_shot_write_job_add_buffer (j, v);\
- }\
-} while (0)
-
-
-#undef GUINT_TO_POINTER
-#undef GPOINTER_TO_UINT
-#if (SIZEOF_VOID_P == 4)
-#define GUINT_TO_POINTER(u) ((void*)(guint32)(u))
-#define GPOINTER_TO_UINT(p) ((guint32)(void*)(p))
-#elif (SIZEOF_VOID_P == 8)
-#define GUINT_TO_POINTER(u) ((void*)(guint64)(u))
-#define GPOINTER_TO_UINT(p) ((guint64)(void*)(p))
-#else
-#error Bad size of void pointer
-#endif
-
-#define WRITE_HEAP_SHOT_JOB_VALUE_WITH_CODE(j,v,c) WRITE_HEAP_SHOT_JOB_VALUE (j, GUINT_TO_POINTER (GPOINTER_TO_UINT (v)|(c)))
-
-#if DEBUG_HEAP_PROFILER
-#define UPDATE_JOB_BUFFER_CURSOR_MESSAGE() printf ("profiler_heap_shot_write_block[UPDATE_JOB_BUFFER_CURSOR]: in job %p, moving to buffer %p and cursor %p\n", job, buffer, cursor)
-#else
-#define UPDATE_JOB_BUFFER_CURSOR_MESSAGE()
-#endif
-#define UPDATE_JOB_BUFFER_CURSOR() do {\
- cursor++;\
- if (cursor >= end) {\
- buffer = buffer->next;\
- if (buffer != NULL) {\
- cursor = & (buffer->buffer [0]);\
- if (buffer->next != NULL) {\
- end = & (buffer->buffer [PROFILER_HEAP_SHOT_WRITE_BUFFER_SIZE]);\
- } else {\
- end = job->cursor;\
- }\
- } else {\
- cursor = NULL;\
- }\
- }\
- UPDATE_JOB_BUFFER_CURSOR_MESSAGE ();\
-} while (0)
-
-static void
-profiler_heap_shot_write_data_block (ProfilerHeapShotWriteJob *job) {
- ProfilerHeapShotWriteBuffer *buffer;
- gpointer* cursor;
- gpointer* end;
- guint64 start_counter;
- guint64 start_time;
- guint64 end_counter;
- guint64 end_time;
-
- write_uint64 (job->start_counter);
- write_uint64 (job->start_time);
- write_uint64 (job->end_counter);
- write_uint64 (job->end_time);
- write_uint32 (job->collection);
- MONO_PROFILER_GET_CURRENT_COUNTER (start_counter);
- MONO_PROFILER_GET_CURRENT_TIME (start_time);
- write_uint64 (start_counter);
- write_uint64 (start_time);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: start writing job %p (start %p, end %p)...\n", job, & (job->buffers->buffer [0]), job->cursor);
-#endif
- buffer = job->buffers;
- cursor = & (buffer->buffer [0]);
- if (buffer->next != NULL) {
- end = & (buffer->buffer [PROFILER_HEAP_SHOT_WRITE_BUFFER_SIZE]);
- } else {
- end = job->cursor;
- }
- if (cursor >= end) {
- cursor = NULL;
- }
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: in job %p, starting at buffer %p and cursor %p\n", job, buffer, cursor);
-#endif
- while (cursor != NULL) {
- gpointer value = *cursor;
- HeapProfilerJobValueCode code = GPOINTER_TO_UINT (value) & HEAP_CODE_MASK;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: got value %p and code %d\n", value, code);
-#endif
-
- UPDATE_JOB_BUFFER_CURSOR ();
- if (code == HEAP_CODE_FREE_OBJECT_CLASS) {
- MonoClass *klass = GUINT_TO_POINTER (GPOINTER_TO_UINT (value) & (~ (guint64) HEAP_CODE_MASK));
- //MonoClass *klass = GUINT_TO_POINTER (GPOINTER_TO_UINT (value) % 4);
- ClassIdMappingElement *class_id;
- guint32 size;
-
- class_id = class_id_mapping_element_get (klass);
- if (class_id == NULL) {
- printf ("profiler_heap_shot_write_data_block: unknown class %p", klass);
- }
- g_assert (class_id != NULL);
- write_uint32 ((class_id->id << 2) | HEAP_CODE_FREE_OBJECT_CLASS);
-
- size = GPOINTER_TO_UINT (*cursor);
- UPDATE_JOB_BUFFER_CURSOR ();
- write_uint32 (size);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: wrote unreachable object of class %p (id %d, size %d)\n", klass, class_id->id, size);
-#endif
- } else if (code == HEAP_CODE_OBJECT) {
- MonoObject *object = GUINT_TO_POINTER (GPOINTER_TO_UINT (value) & (~ (guint64) HEAP_CODE_MASK));
- MonoClass *klass = mono_object_get_class (object);
- ClassIdMappingElement *class_id = class_id_mapping_element_get (klass);
- guint32 size = mono_object_get_size (object);
- guint32 references = GPOINTER_TO_UINT (*cursor);
- UPDATE_JOB_BUFFER_CURSOR ();
-
- if (class_id == NULL) {
- printf ("profiler_heap_shot_write_data_block: unknown class %p", klass);
- }
- g_assert (class_id != NULL);
-
- write_uint64 (GPOINTER_TO_UINT (value));
- write_uint32 (class_id->id);
- write_uint32 (size);
- write_uint32 (references);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: writing object %p (references %d)\n", value, references);
-#endif
-
- while (references > 0) {
- gpointer reference = *cursor;
- write_uint64 (GPOINTER_TO_UINT (reference));
- UPDATE_JOB_BUFFER_CURSOR ();
- references --;
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: inside object %p, wrote reference %p)\n", value, reference);
-#endif
- }
- } else {
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: unknown code %d in value %p\n", code, value);
-#endif
- g_assert_not_reached ();
- }
- }
- write_uint32 (0);
-
- MONO_PROFILER_GET_CURRENT_COUNTER (end_counter);
- MONO_PROFILER_GET_CURRENT_TIME (end_time);
- write_uint64 (end_counter);
- write_uint64 (end_time);
-
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_HEAP_DATA);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_data_block: writing job %p done.\n", job);
-#endif
-}
-static void
-profiler_heap_shot_write_summary_block (ProfilerHeapShotWriteJob *job) {
- guint64 start_counter;
- guint64 start_time;
- guint64 end_counter;
- guint64 end_time;
- int id;
-
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_summary_block: start writing job %p...\n", job);
-#endif
- MONO_PROFILER_GET_CURRENT_COUNTER (start_counter);
- MONO_PROFILER_GET_CURRENT_TIME (start_time);
- write_uint64 (start_counter);
- write_uint64 (start_time);
-
- write_uint32 (job->collection);
-
- for (id = 0; id < job->summary.capacity; id ++) {
- if ((job->summary.per_class_data [id].reachable.instances > 0) || (job->summary.per_class_data [id].unreachable.instances > 0)) {
- write_uint32 (id);
- write_uint32 (job->summary.per_class_data [id].reachable.instances);
- write_uint32 (job->summary.per_class_data [id].reachable.bytes);
- write_uint32 (job->summary.per_class_data [id].unreachable.instances);
- write_uint32 (job->summary.per_class_data [id].unreachable.bytes);
- }
- }
- write_uint32 (0);
-
- MONO_PROFILER_GET_CURRENT_COUNTER (end_counter);
- MONO_PROFILER_GET_CURRENT_TIME (end_time);
- write_uint64 (end_counter);
- write_uint64 (end_time);
-
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_HEAP_SUMMARY);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_summary_block: writing job %p done.\n", job);
-#endif
-}
-
-static void
-profiler_heap_shot_write_block (ProfilerHeapShotWriteJob *job) {
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_block: working on job %p...\n", job);
-#endif
-
- if (profiler->action_flags.collection_summary == TRUE) {
- profiler_heap_shot_write_summary_block (job);
- }
-
- if ((profiler->action_flags.unreachable_objects == TRUE) || (profiler->action_flags.heap_shot == TRUE)) {
- profiler_heap_shot_write_data_block (job);
- }
-
- profiler_heap_shot_write_job_free_buffers (job);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_shot_write_block: work on job %p done.\n", job);
-#endif
-}
-
-static void
-write_element_load_block (LoadedElement *element, guint8 kind, gsize thread_id, gpointer item) {
- WRITE_BYTE (kind);
- write_uint64 (element->load_start_counter);
- write_uint64 (element->load_end_counter);
- write_uint64 (thread_id);
- write_uint32 (element->id);
- write_string (element->name);
- if (kind & MONO_PROFILER_LOADED_EVENT_ASSEMBLY) {
- MonoImage *image = mono_assembly_get_image ((MonoAssembly*) item);
- MonoAssemblyName aname;
- if (mono_assembly_fill_assembly_name (image, &aname)) {
- write_string (aname.name);
- write_uint32 (aname.major);
- write_uint32 (aname.minor);
- write_uint32 (aname.build);
- write_uint32 (aname.revision);
- write_string (aname.culture && *aname.culture? aname.culture: "neutral");
- write_string (aname.public_key_token [0] ? (char *)aname.public_key_token : "null");
- /* Retargetable flag */
- write_uint32 ((aname.flags & 0x00000100) ? 1 : 0);
- } else {
- write_string ("UNKNOWN");
- write_uint32 (0);
- write_uint32 (0);
- write_uint32 (0);
- write_uint32 (0);
- write_string ("neutral");
- write_string ("null");
- write_uint32 (0);
- }
- }
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_LOADED);
- element->load_written = TRUE;
-}
-
-static void
-write_element_unload_block (LoadedElement *element, guint8 kind, gsize thread_id) {
- WRITE_BYTE (kind);
- write_uint64 (element->unload_start_counter);
- write_uint64 (element->unload_end_counter);
- write_uint64 (thread_id);
- write_uint32 (element->id);
- write_string (element->name);
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_UNLOADED);
- element->unload_written = TRUE;
-}
-
-static void
-write_clock_data (void) {
- guint64 counter;
- guint64 time;
-
- MONO_PROFILER_GET_CURRENT_COUNTER (counter);
- MONO_PROFILER_GET_CURRENT_TIME (time);
-
- write_uint64 (counter);
- write_uint64 (time);
-}
-
-static void
-write_mapping_block (gsize thread_id) {
- ClassIdMappingElement *current_class;
- MethodIdMappingElement *current_method;
-
- if ((profiler->classes->unwritten == NULL) && (profiler->methods->unwritten == NULL))
- return;
-
-#if (DEBUG_MAPPING_EVENTS || DEBUG_FILE_WRITES)
- printf ("[write_mapping_block][TID %ld] START\n", thread_id);
-#endif
-
- write_clock_data ();
- write_uint64 (thread_id);
-
- for (current_class = profiler->classes->unwritten; current_class != NULL; current_class = current_class->next_unwritten) {
- MonoImage *image = mono_class_get_image (current_class->klass);
- MonoAssembly *assembly = mono_image_get_assembly (image);
- guint32 assembly_id = loaded_element_get_id (profiler->loaded_assemblies, assembly);
- write_uint32 (current_class->id);
- write_uint32 (assembly_id);
- write_string (current_class->name);
-#if (DEBUG_MAPPING_EVENTS)
- printf ("mapping CLASS (%d => %s)\n", current_class->id, current_class->name);
-#endif
- g_free (current_class->name);
- current_class->name = NULL;
- }
- write_uint32 (0);
- profiler->classes->unwritten = NULL;
-
- for (current_method = profiler->methods->unwritten; current_method != NULL; current_method = current_method->next_unwritten) {
- MonoMethod *method = current_method->method;
- MonoClass *klass = mono_method_get_class (method);
- ClassIdMappingElement *class_element = class_id_mapping_element_get (klass);
- g_assert (class_element != NULL);
- write_uint32 (current_method->id);
- write_uint32 (class_element->id);
- if (method->wrapper_type != 0) {
- write_uint32 (1);
- } else {
- write_uint32 (0);
- }
- write_string (current_method->name);
-#if (DEBUG_MAPPING_EVENTS)
- printf ("mapping METHOD ([%d]%d => %s)\n", class_element?class_element->id:1, current_method->id, current_method->name);
-#endif
- g_free (current_method->name);
- current_method->name = NULL;
- }
- write_uint32 (0);
- profiler->methods->unwritten = NULL;
-
- write_clock_data ();
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_MAPPING);
-
-#if (DEBUG_MAPPING_EVENTS || DEBUG_FILE_WRITES)
- printf ("[write_mapping_block][TID %ld] END\n", thread_id);
-#endif
-}
-
-typedef enum {
- MONO_PROFILER_PACKED_EVENT_CODE_METHOD_ENTER = 1,
- MONO_PROFILER_PACKED_EVENT_CODE_METHOD_EXIT_IMPLICIT = 2,
- MONO_PROFILER_PACKED_EVENT_CODE_METHOD_EXIT_EXPLICIT = 3,
- MONO_PROFILER_PACKED_EVENT_CODE_CLASS_ALLOCATION = 4,
- MONO_PROFILER_PACKED_EVENT_CODE_METHOD_EVENT = 5,
- MONO_PROFILER_PACKED_EVENT_CODE_CLASS_EVENT = 6,
- MONO_PROFILER_PACKED_EVENT_CODE_OTHER_EVENT = 7
-} MonoProfilerPackedEventCode;
-#define MONO_PROFILER_PACKED_EVENT_CODE_BITS 3
-#define MONO_PROFILER_PACKED_EVENT_DATA_BITS (8-MONO_PROFILER_PACKED_EVENT_CODE_BITS)
-#define MONO_PROFILER_PACKED_EVENT_DATA_MASK ((1<<MONO_PROFILER_PACKED_EVENT_DATA_BITS)-1)
-
-#define MONO_PROFILER_EVENT_MAKE_PACKED_CODE(result,data,base) do {\
- result = ((base)|((data & MONO_PROFILER_PACKED_EVENT_DATA_MASK) << MONO_PROFILER_PACKED_EVENT_CODE_BITS));\
- data >>= MONO_PROFILER_PACKED_EVENT_DATA_BITS;\
-} while (0)
-#define MONO_PROFILER_EVENT_MAKE_FULL_CODE(result,code,kind,base) do {\
- result = ((base)|((((kind)<<4) | (code)) << MONO_PROFILER_PACKED_EVENT_CODE_BITS));\
-} while (0)
-
-static void
-rewrite_last_written_stack (ProfilerThreadStack *stack) {
- guint8 event_code;
- int i = thread_stack_get_last_written_frame (stack);
-
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, MONO_PROFILER_EVENT_STACK_SECTION, 0, MONO_PROFILER_PACKED_EVENT_CODE_OTHER_EVENT);
- WRITE_BYTE (event_code);
- write_uint32 (0);
- write_uint32 (i);
-
- while (i > 0) {
- i--;
- write_uint32 (thread_stack_written_frame_at_index (stack, i));
- }
-}
-
-
-static ProfilerEventData*
-write_stack_section_event (ProfilerEventData *events, ProfilerPerThreadData *data) {
- int last_saved_frame = events->data.number;
- int saved_frames = events->value;
- guint8 event_code;
- int i;
-
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, MONO_PROFILER_EVENT_STACK_SECTION, 0, MONO_PROFILER_PACKED_EVENT_CODE_OTHER_EVENT);
- WRITE_BYTE (event_code);
- write_uint32 (last_saved_frame);
- write_uint32 (saved_frames);
- thread_stack_set_last_written_frame (&(data->stack), last_saved_frame + saved_frames);
- events++;
-
- for (i = 0; i < saved_frames; i++) {
- guint8 code = events->code;
- guint32 jit_flag;
- MethodIdMappingElement *method;
- guint32 frame_value;
-
- if (code == MONO_PROFILER_EVENT_METHOD_ALLOCATION_CALLER) {
- jit_flag = 0;
- } else if (code == MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER) {
- jit_flag = 1;
- } else {
- g_assert_not_reached ();
- jit_flag = 0;
- }
-
- method = method_id_mapping_element_get (events->data.address);
- g_assert (method != NULL);
- frame_value = (method->id << 1) | jit_flag;
- write_uint32 (frame_value);
- thread_stack_write_frame_at_index (&(data->stack), last_saved_frame + saved_frames - (1 + i), frame_value);
- events ++;
- }
-
- return events;
-}
-
-static ProfilerEventData*
-write_event (ProfilerEventData *event, ProfilerPerThreadData *data) {
- ProfilerEventData *next = event + 1;
- gboolean write_event_value = TRUE;
- guint8 event_code;
- guint64 event_data;
- guint64 event_value;
- gboolean write_event_value_extension_1 = FALSE;
- guint64 event_value_extension_1 = 0;
- gboolean write_event_value_extension_2 = FALSE;
- guint64 event_value_extension_2 = 0;
-
- event_value = event->value;
- if (event_value == MAX_EVENT_VALUE) {
- event_value = *((guint64*)next);
- next ++;
- }
-
- if (event->data_type == MONO_PROFILER_EVENT_DATA_TYPE_METHOD) {
- MethodIdMappingElement *element = method_id_mapping_element_get (event->data.address);
- g_assert (element != NULL);
- event_data = element->id;
-
- if (event->code == MONO_PROFILER_EVENT_METHOD_CALL) {
- if (event->kind == MONO_PROFILER_EVENT_KIND_START) {
- MONO_PROFILER_EVENT_MAKE_PACKED_CODE (event_code, event_data, MONO_PROFILER_PACKED_EVENT_CODE_METHOD_ENTER);
- } else {
- MONO_PROFILER_EVENT_MAKE_PACKED_CODE (event_code, event_data, MONO_PROFILER_PACKED_EVENT_CODE_METHOD_EXIT_EXPLICIT);
- }
- } else {
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, event->code, event->kind, MONO_PROFILER_PACKED_EVENT_CODE_METHOD_EVENT);
- }
- } else if (event->data_type == MONO_PROFILER_EVENT_DATA_TYPE_CLASS) {
- ClassIdMappingElement *element = class_id_mapping_element_get (event->data.address);
- g_assert (element != NULL);
- event_data = element->id;
-
- if (event->code == MONO_PROFILER_EVENT_CLASS_ALLOCATION) {
- if ((! profiler->action_flags.save_allocation_caller) || (! (next->code == MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER))) {
- MONO_PROFILER_EVENT_MAKE_PACKED_CODE (event_code, event_data, MONO_PROFILER_PACKED_EVENT_CODE_CLASS_ALLOCATION);
- } else {
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, MONO_PROFILER_EVENT_JIT_TIME_ALLOCATION, event->kind, MONO_PROFILER_PACKED_EVENT_CODE_OTHER_EVENT);
- }
-
- if (profiler->action_flags.save_allocation_caller) {
- MonoMethod *caller_method = next->data.address;
-
- if ((next->code != MONO_PROFILER_EVENT_METHOD_ALLOCATION_CALLER) && (next->code != MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER)) {
- g_assert_not_reached ();
- }
-
- if (caller_method != NULL) {
- MethodIdMappingElement *caller = method_id_mapping_element_get (caller_method);
- g_assert (caller != NULL);
- event_value_extension_1 = caller->id;
- }
-
- write_event_value_extension_1 = TRUE;
- next ++;
- }
-
- if (profiler->action_flags.allocations_carry_id) {
- event_value_extension_2 = GPOINTER_TO_UINT (next->data.address);
-
- if (next->code != MONO_PROFILER_EVENT_ALLOCATION_OBJECT_ID) {
- g_assert_not_reached ();
- }
-
- write_event_value_extension_2 = TRUE;
- next ++;
- }
- } else if (event->code == MONO_PROFILER_EVENT_CLASS_MONITOR) {
- g_assert (next->code == MONO_PROFILER_EVENT_OBJECT_MONITOR);
-
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, event->code, event->kind, MONO_PROFILER_PACKED_EVENT_CODE_CLASS_EVENT);
- event_value_extension_1 = next->value;
- write_event_value_extension_1 = TRUE;
- event_value_extension_2 = GPOINTER_TO_UINT (next->data.address);
- write_event_value_extension_2 = TRUE;
- next ++;
- } else {
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, event->code, event->kind, MONO_PROFILER_PACKED_EVENT_CODE_CLASS_EVENT);
- }
- } else {
- if (event->code == MONO_PROFILER_EVENT_STACK_SECTION) {
- return write_stack_section_event (event, data);
- } else {
- event_data = event->data.number;
- MONO_PROFILER_EVENT_MAKE_FULL_CODE (event_code, event->code, event->kind, MONO_PROFILER_PACKED_EVENT_CODE_OTHER_EVENT);
- }
- }
-
- /* Skip writing JIT events if the user did not ask for them */
- if ((event->code == MONO_PROFILER_EVENT_METHOD_JIT) && ! profiler->action_flags.jit_time) {
- return next;
- }
-
-#if (DEBUG_LOGGING_PROFILER)
- EVENT_MARK ();
- printf ("writing EVENT[%p] data_type:%d, kind:%d, code:%d (%d:%ld:%ld)\n", event,
- event->data_type, event->kind, event->code,
- event_code, event_data, event_value);
-#endif
-
- WRITE_BYTE (event_code);
- write_uint64 (event_data);
- if (write_event_value) {
- write_uint64 (event_value);
- if (write_event_value_extension_1) {
- write_uint64 (event_value_extension_1);
- }
- if (write_event_value_extension_2) {
- write_uint64 (event_value_extension_2);
- }
- }
-
- return next;
-}
-
-static void
-write_thread_data_block (ProfilerPerThreadData *data) {
- ProfilerEventData *start = data->first_unwritten_event;
- ProfilerEventData *end = data->first_unmapped_event;
-
- if (start == end)
- return;
-#if (DEBUG_FILE_WRITES)
- printf ("write_thread_data_block: preparing buffer for thread %ld\n", (guint64) data->thread_id);
-#endif
- write_clock_data ();
- write_uint64 (data->thread_id);
-
- write_uint64 (data->start_event_counter);
-
- /* If we are tracking the stack, make sure that stack sections */
- /* can be fully reconstructed even reading only one block */
- if (profiler->action_flags.track_stack) {
- rewrite_last_written_stack (&(data->stack));
- }
-
- while (start < end) {
- start = write_event (start, data);
- }
- WRITE_BYTE (0);
- data->first_unwritten_event = end;
-
- write_clock_data ();
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_EVENTS);
-#if (DEBUG_FILE_WRITES)
- printf ("write_thread_data_block: buffer for thread %ld written\n", (guint64) data->thread_id);
-#endif
-}
-
-static ProfilerExecutableMemoryRegionData*
-profiler_executable_memory_region_new (gpointer *start, gpointer *end, guint32 file_offset, char *file_name, guint32 id) {
- ProfilerExecutableMemoryRegionData *result = g_new (ProfilerExecutableMemoryRegionData, 1);
- result->start = start;
- result->end = end;
- result->file_offset = file_offset;
- result->file_name = g_strdup (file_name);
- result->id = id;
- result->is_new = TRUE;
-
- result->file = NULL;
- result->file_region_reference = NULL;
- result->symbols_capacity = id;
- result->symbols_count = id;
- result->symbols = NULL;
-
- return result;
-}
-
-static void
-executable_file_close (ProfilerExecutableMemoryRegionData *region);
-
-static void
-profiler_executable_memory_region_destroy (ProfilerExecutableMemoryRegionData *data) {
- if (data->file != NULL) {
- executable_file_close (data);
- data->file = NULL;
- }
- if (data->symbols != NULL) {
- g_free (data->symbols);
- data->symbols = NULL;
- }
- if (data->file_name != NULL) {
- g_free (data->file_name);
- data->file_name = NULL;
- }
- g_free (data);
-}
-
-static ProfilerExecutableMemoryRegions*
-profiler_executable_memory_regions_new (int next_id, int next_unmanaged_function_id) {
- ProfilerExecutableMemoryRegions *result = g_new (ProfilerExecutableMemoryRegions, 1);
- result->regions = g_new0 (ProfilerExecutableMemoryRegionData*, 32);
- result->regions_capacity = 32;
- result->regions_count = 0;
- result->next_id = next_id;
- result->next_unmanaged_function_id = next_unmanaged_function_id;
- return result;
-}
-
-static void
-profiler_executable_memory_regions_destroy (ProfilerExecutableMemoryRegions *regions) {
- int i;
-
- for (i = 0; i < regions->regions_count; i++) {
- profiler_executable_memory_region_destroy (regions->regions [i]);
- }
- g_free (regions->regions);
- g_free (regions);
-}
-
-static ProfilerExecutableMemoryRegionData*
-find_address_region (ProfilerExecutableMemoryRegions *regions, gpointer address) {
- int low_index = 0;
- int high_index = regions->regions_count;
- int middle_index = 0;
- ProfilerExecutableMemoryRegionData *middle_region = regions->regions [0];
-
- if ((regions->regions_count == 0) || (regions->regions [low_index]->start > address) || (regions->regions [high_index - 1]->end < address)) {
- return NULL;
- }
-
- //printf ("find_address_region: Looking for address %p in %d regions (from %p to %p)\n", address, regions->regions_count, regions->regions [low_index]->start, regions->regions [high_index - 1]->end);
-
- while (low_index != high_index) {
- middle_index = low_index + ((high_index - low_index) / 2);
- middle_region = regions->regions [middle_index];
-
- //printf ("find_address_region: Looking for address %p, considering index %d[%p-%p] (%d-%d)\n", address, middle_index, middle_region->start, middle_region->end, low_index, high_index);
-
- if (middle_region->start > address) {
- if (middle_index > 0) {
- high_index = middle_index;
- } else {
- return NULL;
- }
- } else if (middle_region->end < address) {
- if (middle_index < regions->regions_count - 1) {
- low_index = middle_index + 1;
- } else {
- return NULL;
- }
- } else {
- return middle_region;
- }
- }
-
- if ((middle_region == NULL) || (middle_region->start > address) || (middle_region->end < address)) {
- return NULL;
- } else {
- return middle_region;
- }
-}
-
-static void
-append_region (ProfilerExecutableMemoryRegions *regions, gpointer *start, gpointer *end, guint32 file_offset, char *file_name) {
- if (regions->regions_count >= regions->regions_capacity) {
- ProfilerExecutableMemoryRegionData **new_regions = g_new0 (ProfilerExecutableMemoryRegionData*, regions->regions_capacity * 2);
- memcpy (new_regions, regions->regions, regions->regions_capacity * sizeof (ProfilerExecutableMemoryRegionData*));
- g_free (regions->regions);
- regions->regions = new_regions;
- regions->regions_capacity = regions->regions_capacity * 2;
- }
- regions->regions [regions->regions_count] = profiler_executable_memory_region_new (start, end, file_offset, file_name, regions->next_id);
- regions->regions_count ++;
- regions->next_id ++;
-}
-
-static gboolean
-regions_are_equivalent (ProfilerExecutableMemoryRegionData *region1, ProfilerExecutableMemoryRegionData *region2) {
- if ((region1->start == region2->start) &&
- (region1->end == region2->end) &&
- (region1->file_offset == region2->file_offset) &&
- ! strcmp (region1->file_name, region2->file_name)) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static int
-compare_regions (const void *a1, const void *a2) {
- ProfilerExecutableMemoryRegionData *r1 = * (ProfilerExecutableMemoryRegionData**) a1;
- ProfilerExecutableMemoryRegionData *r2 = * (ProfilerExecutableMemoryRegionData**) a2;
- return (r1->start < r2->start)? -1 : ((r1->start > r2->start)? 1 : 0);
-}
-
-static void
-restore_old_regions (ProfilerExecutableMemoryRegions *old_regions, ProfilerExecutableMemoryRegions *new_regions) {
- int old_i;
- int new_i;
-
- for (new_i = 0; new_i < new_regions->regions_count; new_i++) {
- ProfilerExecutableMemoryRegionData *new_region = new_regions->regions [new_i];
- for (old_i = 0; old_i < old_regions->regions_count; old_i++) {
- ProfilerExecutableMemoryRegionData *old_region = old_regions->regions [old_i];
- if ( regions_are_equivalent (old_region, new_region)) {
- new_regions->regions [new_i] = old_region;
- old_regions->regions [old_i] = new_region;
-
- // FIXME (sanity check)
- g_assert (new_region->is_new && ! old_region->is_new);
- }
- }
- }
-}
-
-static void
-sort_regions (ProfilerExecutableMemoryRegions *regions) {
- if (regions->regions_count > 1) {
- int i;
-
- qsort (regions->regions, regions->regions_count, sizeof (ProfilerExecutableMemoryRegionData *), compare_regions);
-
- i = 1;
- while (i < regions->regions_count) {
- ProfilerExecutableMemoryRegionData *current_region = regions->regions [i];
- ProfilerExecutableMemoryRegionData *previous_region = regions->regions [i - 1];
-
- if (regions_are_equivalent (previous_region, current_region)) {
- int j;
-
- if (! current_region->is_new) {
- profiler_executable_memory_region_destroy (previous_region);
- regions->regions [i - 1] = current_region;
- } else {
- profiler_executable_memory_region_destroy (current_region);
- }
-
- for (j = i + 1; j < regions->regions_count; j++) {
- regions->regions [j - 1] = regions->regions [j];
- }
-
- regions->regions_count --;
- } else {
- i++;
- }
- }
- }
-}
-
-static void
-fix_region_references (ProfilerExecutableMemoryRegions *regions) {
- int i;
- for (i = 0; i < regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = regions->regions [i];
- if (region->file_region_reference != NULL) {
- region->file_region_reference->region = region;
- }
- }
-}
-
-static void
-executable_file_add_region_reference (ProfilerExecutableFile *file, ProfilerExecutableMemoryRegionData *region) {
- guint8 *section_headers = file->data + file->header->e_shoff;
- int section_index;
-
- for (section_index = 1; section_index < file->header->e_shnum; section_index ++) {
- ElfSection *section_header = (ElfSection*) (section_headers + (file->header->e_shentsize * section_index));
-
- if ((section_header->sh_addr != 0) && (section_header->sh_flags & ELF_SHF_EXECINSTR) &&
- (region->file_offset <= section_header->sh_offset) && (region->file_offset + (((guint8*)region->end)-((guint8*)region->start)) >= (section_header->sh_offset + section_header->sh_size))) {
- ProfilerExecutableFileSectionRegion *section_region = & (file->section_regions [section_index]);
- section_region->region = region;
- section_region->section_address = (gpointer) section_header->sh_addr;
- section_region->section_offset = section_header->sh_offset;
- region->file_region_reference = section_region;
- }
- }
-}
-
-static gboolean check_elf_header (ElfHeader* header) {
- guint16 test = 0x0102;
-
- if ((header->e_ident [EI_MAG0] != 0x7f) || (header->e_ident [EI_MAG1] != 'E') ||
- (header->e_ident [EI_MAG2] != 'L') || (header->e_ident [EI_MAG3] != 'F')) {
- return FALSE;
- }
-
- if (sizeof (gsize) == 4) {
- if (header->e_ident [EI_CLASS] != ELF_CLASS_32) {
- g_warning ("Class is not ELF_CLASS_32 with gsize size %d", (int) sizeof (gsize));
- return FALSE;
- }
- } else if (sizeof (gsize) == 8) {
- if (header->e_ident [EI_CLASS] != ELF_CLASS_64) {
- g_warning ("Class is not ELF_CLASS_64 with gsize size %d", (int) sizeof (gsize));
- return FALSE;
- }
- } else {
- g_warning ("Absurd gsize size %d", (int) sizeof (gsize));
- return FALSE;
- }
-
- if ((*(guint8*)(&test)) == 0x01) {
- if (header->e_ident [EI_DATA] != ELF_DATA_MSB) {
- g_warning ("Data is not ELF_DATA_MSB with first test byte 0x01");
- return FALSE;
- }
- } else if ((*(guint8*)(&test)) == 0x02) {
- if (header->e_ident [EI_DATA] != ELF_DATA_LSB) {
- g_warning ("Data is not ELF_DATA_LSB with first test byte 0x02");
- return FALSE;
- }
- } else {
- g_warning ("Absurd test byte value");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean check_elf_file (int fd) {
- void *header = malloc (sizeof (ElfHeader));
- ssize_t read_result = read (fd, header, sizeof (ElfHeader));
- gboolean result;
-
- if (read_result != sizeof (ElfHeader)) {
- result = FALSE;
- } else {
- result = check_elf_header ((ElfHeader*) header);
- }
-
- free (header);
- return result;
-}
-
-static ProfilerExecutableFile*
-executable_file_open (ProfilerExecutableMemoryRegionData *region) {
- ProfilerExecutableFiles *files = & (profiler->executable_files);
- ProfilerExecutableFile *file = region->file;
-
- if (file == NULL) {
- file = (ProfilerExecutableFile*) g_hash_table_lookup (files->table, region->file_name);
-
- if (file == NULL) {
- struct stat stat_buffer;
- int symtab_index = 0;
- int strtab_index = 0;
- int dynsym_index = 0;
- int dynstr_index = 0;
- ElfHeader *header;
- guint8 *section_headers;
- int section_index;
- int strings_index;
-
- file = g_new0 (ProfilerExecutableFile, 1);
- region->file = file;
- g_hash_table_insert (files->table, region->file_name, file);
- file->reference_count ++;
- file->next_new_file = files->new_files;
- files->new_files = file;
-
- file->fd = open (region->file_name, O_RDONLY);
- if (file->fd == -1) {
- //g_warning ("Cannot open file '%s': '%s'", region->file_name, strerror (errno));
- return file;
- } else {
- if (fstat (file->fd, &stat_buffer) != 0) {
- //g_warning ("Cannot stat file '%s': '%s'", region->file_name, strerror (errno));
- return file;
- } else if (! check_elf_file (file->fd)) {
- return file;
- } else {
- size_t region_length = ((guint8*)region->end) - ((guint8*)region->start);
- file->length = stat_buffer.st_size;
-
- if (file->length == region_length) {
- file->data = region->start;
- close (file->fd);
- file->fd = -1;
- } else {
- file->data = mmap (NULL, file->length, PROT_READ, MAP_PRIVATE, file->fd, 0);
-
- if (file->data == MAP_FAILED) {
- close (file->fd);
- //g_warning ("Cannot map file '%s': '%s'", region->file_name, strerror (errno));
- file->data = NULL;
- return file;
- }
- }
- }
- }
-
- /* OK, this is a usable elf file, and we mmapped it... */
- header = (ElfHeader*) file->data;
- file->header = header;
- section_headers = file->data + file->header->e_shoff;
- file->main_string_table = ((const char*) file->data) + (((ElfSection*) (section_headers + (header->e_shentsize * header->e_shstrndx)))->sh_offset);
-
- for (section_index = 0; section_index < header->e_shnum; section_index ++) {
- ElfSection *section_header = (ElfSection*) (section_headers + (header->e_shentsize * section_index));
-
- if (section_header->sh_type == ELF_SHT_SYMTAB) {
- symtab_index = section_index;
- } else if (section_header->sh_type == ELF_SHT_DYNSYM) {
- dynsym_index = section_index;
- } else if (section_header->sh_type == ELF_SHT_STRTAB) {
- if (! strcmp (file->main_string_table + section_header->sh_name, ".strtab")) {
- strtab_index = section_index;
- } else if (! strcmp (file->main_string_table + section_header->sh_name, ".dynstr")) {
- dynstr_index = section_index;
- }
- }
- }
-
- if ((symtab_index != 0) && (strtab_index != 0)) {
- section_index = symtab_index;
- strings_index = strtab_index;
- } else if ((dynsym_index != 0) && (dynstr_index != 0)) {
- section_index = dynsym_index;
- strings_index = dynstr_index;
- } else {
- section_index = 0;
- strings_index = 0;
- }
-
- if (section_index != 0) {
- ElfSection *section_header = (ElfSection*) (section_headers + (header->e_shentsize * section_index));
- file->symbol_size = section_header->sh_entsize;
- file->symbols_count = (guint32) (section_header->sh_size / section_header->sh_entsize);
- file->symbols_start = file->data + section_header->sh_offset;
- file->symbols_string_table = ((const char*) file->data) + (((ElfSection*) (section_headers + (header->e_shentsize * strings_index)))->sh_offset);
- }
-
- file->section_regions = g_new0 (ProfilerExecutableFileSectionRegion, file->header->e_shnum);
- } else {
- region->file = file;
- file->reference_count ++;
- }
- }
-
- if (file->header != NULL) {
- executable_file_add_region_reference (file, region);
- }
-
- return file;
-}
-
-static void
-executable_file_free (ProfilerExecutableFile* file) {
- if (file->fd != -1) {
- if (close (file->fd) != 0) {
- g_warning ("Cannot close file: '%s'", strerror (errno));
- }
- if (file->data != NULL) {
- if (munmap (file->data, file->length) != 0) {
- g_warning ("Cannot unmap file: '%s'", strerror (errno));
- }
- }
- }
- if (file->section_regions != NULL) {
- g_free (file->section_regions);
- file->section_regions = NULL;
- }
- g_free (file);
-}
-
-static void
-executable_file_close (ProfilerExecutableMemoryRegionData *region) {
- region->file->reference_count --;
-
- if ((region->file_region_reference != NULL) && (region->file_region_reference->region == region)) {
- region->file_region_reference->region = NULL;
- region->file_region_reference->section_address = 0;
- region->file_region_reference->section_offset = 0;
- }
-
- if (region->file->reference_count <= 0) {
- ProfilerExecutableFiles *files = & (profiler->executable_files);
- g_hash_table_remove (files->table, region->file_name);
- executable_file_free (region->file);
- region->file = NULL;
- }
-}
-
-static void
-executable_file_count_symbols (ProfilerExecutableFile *file) {
- int symbol_index;
-
- for (symbol_index = 0; symbol_index < file->symbols_count; symbol_index ++) {
- ElfSymbol *symbol = (ElfSymbol*) (file->symbols_start + (symbol_index * file->symbol_size));
-
- if ((ELF_ST_TYPE (symbol->st_info) == ELF_STT_FUNC) &&
- (symbol->st_shndx > 0) &&
- (symbol->st_shndx < file->header->e_shnum)) {
- int symbol_section_index = symbol->st_shndx;
- ProfilerExecutableMemoryRegionData *region = file->section_regions [symbol_section_index].region;
- if ((region != NULL) && (region->symbols == NULL)) {
- region->symbols_count ++;
- }
- }
- }
-}
-
-static void
-executable_memory_regions_prepare_symbol_tables (ProfilerExecutableMemoryRegions *regions) {
- int i;
- for (i = 0; i < regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = regions->regions [i];
- if ((region->symbols_count > 0) && (region->symbols == NULL)) {
- region->symbols = g_new (ProfilerUnmanagedSymbol, region->symbols_count);
- region->symbols_capacity = region->symbols_count;
- region->symbols_count = 0;
- }
- }
-}
-
-static const char*
-executable_region_symbol_get_name (ProfilerExecutableMemoryRegionData *region, ProfilerUnmanagedSymbol *symbol) {
- ElfSymbol *elf_symbol = (ElfSymbol*) (region->file->symbols_start + (symbol->index * region->file->symbol_size));
- return region->file->symbols_string_table + elf_symbol->st_name;
-}
-
-static void
-executable_file_build_symbol_tables (ProfilerExecutableFile *file) {
- int symbol_index;
-
- for (symbol_index = 0; symbol_index < file->symbols_count; symbol_index ++) {
- ElfSymbol *symbol = (ElfSymbol*) (file->symbols_start + (symbol_index * file->symbol_size));
-
- if ((ELF_ST_TYPE (symbol->st_info) == ELF_STT_FUNC) &&
- (symbol->st_shndx > 0) &&
- (symbol->st_shndx < file->header->e_shnum)) {
- int symbol_section_index = symbol->st_shndx;
- ProfilerExecutableFileSectionRegion *section_region = & (file->section_regions [symbol_section_index]);
- ProfilerExecutableMemoryRegionData *region = section_region->region;
-
- if (region != NULL) {
- ProfilerUnmanagedSymbol *new_symbol = & (region->symbols [region->symbols_count]);
- region->symbols_count ++;
-
- new_symbol->id = 0;
- new_symbol->index = symbol_index;
- new_symbol->size = symbol->st_size;
- new_symbol->offset = (((guint8*) symbol->st_value) - section_region->section_address) - (region->file_offset - section_region->section_offset);
- }
- }
- }
-}
-
-static int
-compare_region_symbols (const void *p1, const void *p2) {
- const ProfilerUnmanagedSymbol *s1 = p1;
- const ProfilerUnmanagedSymbol *s2 = p2;
- return (s1->offset < s2->offset)? -1 : ((s1->offset > s2->offset)? 1 : 0);
-}
-
-static void
-executable_memory_regions_sort_symbol_tables (ProfilerExecutableMemoryRegions *regions) {
- int i;
- for (i = 0; i < regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = regions->regions [i];
- if ((region->is_new) && (region->symbols != NULL)) {
- qsort (region->symbols, region->symbols_count, sizeof (ProfilerUnmanagedSymbol), compare_region_symbols);
- }
- }
-}
-
-static void
-build_symbol_tables (ProfilerExecutableMemoryRegions *regions, ProfilerExecutableFiles *files) {
- int i;
- ProfilerExecutableFile *file;
-
- for (i = 0; i < regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = regions->regions [i];
- if ((region->is_new) && (region->file == NULL)) {
- executable_file_open (region);
- }
- }
-
- for (file = files->new_files; file != NULL; file = file->next_new_file) {
- executable_file_count_symbols (file);
- }
-
- executable_memory_regions_prepare_symbol_tables (regions);
-
- for (file = files->new_files; file != NULL; file = file->next_new_file) {
- executable_file_build_symbol_tables (file);
- }
-
- executable_memory_regions_sort_symbol_tables (regions);
-
- file = files->new_files;
- while (file != NULL) {
- ProfilerExecutableFile *next_file = file->next_new_file;
- file->next_new_file = NULL;
- file = next_file;
- }
- files->new_files = NULL;
-}
-
-static ProfilerUnmanagedSymbol*
-executable_memory_region_find_symbol (ProfilerExecutableMemoryRegionData *region, guint32 offset) {
- if (region->symbols_count > 0) {
- ProfilerUnmanagedSymbol *low = region->symbols;
- ProfilerUnmanagedSymbol *high = region->symbols + (region->symbols_count - 1);
- int step = region->symbols_count >> 1;
- ProfilerUnmanagedSymbol *current = region->symbols + step;
-
- do {
- step = (high - low) >> 1;
-
- if (offset < current->offset) {
- high = current;
- current = high - step;
- } else if (offset >= current->offset) {
- if (offset >= (current->offset + current->size)) {
- low = current;
- current = low + step;
- } else {
- return current;
- }
- }
- } while (step > 0);
-
- if ((offset >= current->offset) && (offset < (current->offset + current->size))) {
- return current;
- } else {
- return NULL;
- }
- } else {
- return NULL;
- }
-}
-
-//FIXME: make also Win32 and BSD variants
-#define MAPS_BUFFER_SIZE 4096
-#define MAPS_FILENAME_SIZE 2048
-
-static gboolean
-update_regions_buffer (int fd, char *buffer) {
- ssize_t result = read (fd, buffer, MAPS_BUFFER_SIZE);
-
- if (result == MAPS_BUFFER_SIZE) {
- return TRUE;
- } else if (result >= 0) {
- *(buffer + result) = 0;
- return FALSE;
- } else {
- *buffer = 0;
- return FALSE;
- }
-}
-
-#define GOTO_NEXT_CHAR(c,b,fd) do {\
- (c)++;\
- if (((c) - (b) >= MAPS_BUFFER_SIZE) || ((*(c) == 0) && ((c) != (b)))) {\
- update_regions_buffer ((fd), (b));\
- (c) = (b);\
- }\
-} while (0);
-
-static int hex_digit_value (char c) {
- if ((c >= '0') && (c <= '9')) {
- return c - '0';
- } else if ((c >= 'a') && (c <= 'f')) {
- return c - 'a' + 10;
- } else if ((c >= 'A') && (c <= 'F')) {
- return c - 'A' + 10;
- } else {
- return 0;
- }
-}
-
-/*
- * Start address
- * -
- * End address
- * (space)
- * Permissions
- * Offset
- * (space)
- * Device
- * (space)
- * Inode
- * (space)
- * File
- * \n
- */
-typedef enum {
- MAP_LINE_PARSER_STATE_INVALID,
- MAP_LINE_PARSER_STATE_START_ADDRESS,
- MAP_LINE_PARSER_STATE_END_ADDRESS,
- MAP_LINE_PARSER_STATE_PERMISSIONS,
- MAP_LINE_PARSER_STATE_OFFSET,
- MAP_LINE_PARSER_STATE_DEVICE,
- MAP_LINE_PARSER_STATE_INODE,
- MAP_LINE_PARSER_STATE_BLANK_BEFORE_FILENAME,
- MAP_LINE_PARSER_STATE_FILENAME,
- MAP_LINE_PARSER_STATE_DONE
-} MapLineParserState;
-
-const char *map_line_parser_state [] = {
- "INVALID",
- "START_ADDRESS",
- "END_ADDRESS",
- "PERMISSIONS",
- "OFFSET",
- "DEVICE",
- "INODE",
- "BLANK_BEFORE_FILENAME",
- "FILENAME",
- "DONE"
-};
-
-static char*
-parse_map_line (ProfilerExecutableMemoryRegions *regions, int fd, char *buffer, char *filename, char *current) {
- MapLineParserState state = MAP_LINE_PARSER_STATE_START_ADDRESS;
- gsize start_address = 0;
- gsize end_address = 0;
- guint32 offset = 0;
- int filename_index = 0;
- gboolean is_executable = FALSE;
- gboolean done = FALSE;
-
- char c = *current;
-
- while (1) {
- switch (state) {
- case MAP_LINE_PARSER_STATE_START_ADDRESS:
- if (isxdigit (c)) {
- start_address <<= 4;
- start_address |= hex_digit_value (c);
- } else if (c == '-') {
- state = MAP_LINE_PARSER_STATE_END_ADDRESS;
- } else {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_END_ADDRESS:
- if (isxdigit (c)) {
- end_address <<= 4;
- end_address |= hex_digit_value (c);
- } else if (isblank (c)) {
- state = MAP_LINE_PARSER_STATE_PERMISSIONS;
- } else {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_PERMISSIONS:
- if (c == 'x') {
- is_executable = TRUE;
- } else if (isblank (c)) {
- state = MAP_LINE_PARSER_STATE_OFFSET;
- } else if ((c != '-') && ! isalpha (c)) {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_OFFSET:
- if (isxdigit (c)) {
- offset <<= 4;
- offset |= hex_digit_value (c);
- } else if (isblank (c)) {
- state = MAP_LINE_PARSER_STATE_DEVICE;
- } else {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_DEVICE:
- if (isblank (c)) {
- state = MAP_LINE_PARSER_STATE_INODE;
- } else if ((c != ':') && ! isxdigit (c)) {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_INODE:
- if (isblank (c)) {
- state = MAP_LINE_PARSER_STATE_BLANK_BEFORE_FILENAME;
- } else if (! isdigit (c)) {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_BLANK_BEFORE_FILENAME:
- if ((c == '/') || (c == '[')) {
- state = MAP_LINE_PARSER_STATE_FILENAME;
- filename [filename_index] = *current;
- filename_index ++;
- } else if (! isblank (c)) {
- state = MAP_LINE_PARSER_STATE_INVALID;
- }
- break;
- case MAP_LINE_PARSER_STATE_FILENAME:
- if (filename_index < MAPS_FILENAME_SIZE) {
- if (c == '\n') {
- state = MAP_LINE_PARSER_STATE_DONE;
- done = TRUE;
- filename [filename_index] = 0;
- } else {
- filename [filename_index] = *current;
- filename_index ++;
- }
- } else {
- filename [filename_index] = 0;
- g_warning ("ELF filename too long: \"%s\"...\n", filename);
- }
- break;
- case MAP_LINE_PARSER_STATE_DONE:
- if (done && is_executable) {
- filename [filename_index] = 0;
- append_region (regions, (gpointer) start_address, (gpointer) end_address, offset, filename);
- }
- return current;
- case MAP_LINE_PARSER_STATE_INVALID:
- if (c == '\n') {
- state = MAP_LINE_PARSER_STATE_DONE;
- }
- break;
- }
-
- if (c == 0) {
- return NULL;
- } else if (c == '\n') {
- state = MAP_LINE_PARSER_STATE_DONE;
- }
-
- GOTO_NEXT_CHAR(current, buffer, fd);
- c = *current;
- }
-}
-
-static gboolean
-scan_process_regions (ProfilerExecutableMemoryRegions *regions) {
- char *buffer;
- char *filename;
- char *current;
- int fd;
-
- fd = open ("/proc/self/maps", O_RDONLY);
- if (fd == -1) {
- return FALSE;
- }
-
- buffer = malloc (MAPS_BUFFER_SIZE);
- filename = malloc (MAPS_FILENAME_SIZE);
- update_regions_buffer (fd, buffer);
- current = buffer;
- while (current != NULL) {
- current = parse_map_line (regions, fd, buffer, filename, current);
- }
-
- free (buffer);
- free (filename);
-
- close (fd);
- return TRUE;
-}
-//End of Linux code
-
-typedef enum {
- MONO_PROFILER_STATISTICAL_CODE_END = 0,
- MONO_PROFILER_STATISTICAL_CODE_METHOD = 1,
- MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_ID = 2,
- MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_NEW_ID = 3,
- MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_OFFSET_IN_REGION = 4,
- MONO_PROFILER_STATISTICAL_CODE_CALL_CHAIN = 5,
- MONO_PROFILER_STATISTICAL_CODE_REGIONS = 7
-} MonoProfilerStatisticalCode;
-
-static void
-refresh_memory_regions (void) {
- ProfilerExecutableMemoryRegions *old_regions = profiler->executable_regions;
- ProfilerExecutableMemoryRegions *new_regions = profiler_executable_memory_regions_new (old_regions->next_id, old_regions->next_unmanaged_function_id);
- int i;
-
- LOG_WRITER_THREAD ("Refreshing memory regions...");
- scan_process_regions (new_regions);
- sort_regions (new_regions);
- restore_old_regions (old_regions, new_regions);
- fix_region_references (new_regions);
- LOG_WRITER_THREAD ("Refreshed memory regions.");
-
- LOG_WRITER_THREAD ("Building symbol tables...");
- build_symbol_tables (new_regions, & (profiler->executable_files));
-#if 0
- printf ("Symbol tables done!\n");
- printf ("Region summary...\n");
- for (i = 0; i < new_regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = new_regions->regions [i];
- printf ("Region %d[%d][NEW:%d] (%p-%p) at %d in file %s\n", i, region->id, region->is_new,
- region->start, region->end, region->file_offset, region->file_name);
- }
- printf ("New symbol tables dump...\n");
- for (i = 0; i < new_regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = new_regions->regions [i];
-
- if (region->is_new) {
- int symbol_index;
-
- printf ("Region %d[%d][NEW:%d] (%p-%p) at %d in file %s\n", i, region->id, region->is_new,
- region->start, region->end, region->file_offset, region->file_name);
- for (symbol_index = 0; symbol_index < region->symbols_count; symbol_index ++) {
- ProfilerUnmanagedSymbol *symbol = & (region->symbols [symbol_index]);
- printf (" [%d] Symbol %s (offset %d, size %d)\n", symbol_index,
- executable_region_symbol_get_name (region, symbol),
- symbol->offset, symbol->size);
- }
- }
- }
-#endif
- LOG_WRITER_THREAD ("Built symbol tables.");
-
- // This marks the region "sub-block"
- write_uint32 (MONO_PROFILER_STATISTICAL_CODE_REGIONS);
-
- // First write the "removed" regions
- for (i = 0; i < old_regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = old_regions->regions [i];
- if (! region->is_new) {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[refresh_memory_regions] Invalidated region %d\n", region->id);
-#endif
- write_uint32 (region->id);
- }
- }
- write_uint32 (0);
-
- // Then write the new ones
- for (i = 0; i < new_regions->regions_count; i++) {
- ProfilerExecutableMemoryRegionData *region = new_regions->regions [i];
- if (region->is_new) {
- region->is_new = FALSE;
-
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[refresh_memory_regions] Wrote region %d (%p-%p[%d] '%s')\n", region->id, region->start, region->end, region->file_offset, region->file_name);
-#endif
- write_uint32 (region->id);
- write_uint64 (GPOINTER_TO_UINT (region->start));
- write_uint32 (GPOINTER_TO_UINT (region->end) - GPOINTER_TO_UINT (region->start));
- write_uint32 (region->file_offset);
- write_string (region->file_name);
- }
- }
- write_uint32 (0);
-
- // Finally, free the old ones, and replace them
- profiler_executable_memory_regions_destroy (old_regions);
- profiler->executable_regions = new_regions;
-}
-
-static gboolean
-write_statistical_hit (gpointer address, gboolean regions_refreshed) {
- ProfilerCodeBuffer *code_buffer = profiler_code_buffer_from_address (profiler, address);
-
- if ((code_buffer != NULL) && (code_buffer->info.type == MONO_PROFILER_CODE_BUFFER_METHOD)) {
- MonoMethod *method = code_buffer->info.data.method;
- MethodIdMappingElement *element = method_id_mapping_element_get (method);
-
- if (element != NULL) {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Wrote method %d\n", element->id);
-#endif
- write_uint32 ((element->id << 3) | MONO_PROFILER_STATISTICAL_CODE_METHOD);
- } else {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Wrote unknown method %p\n", method);
-#endif
- write_uint32 (MONO_PROFILER_STATISTICAL_CODE_METHOD);
- }
- } else {
- ProfilerExecutableMemoryRegionData *region = find_address_region (profiler->executable_regions, address);
-
- if (region == NULL && ! regions_refreshed) {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Cannot find region for address %p, refreshing...\n", address);
-#endif
- refresh_memory_regions ();
- regions_refreshed = TRUE;
- region = find_address_region (profiler->executable_regions, address);
- }
-
- if (region != NULL) {
- guint32 offset = ((guint8*)address) - ((guint8*)region->start);
- ProfilerUnmanagedSymbol *symbol = executable_memory_region_find_symbol (region, offset);
-
- if (symbol != NULL) {
- if (symbol->id > 0) {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Wrote unmanaged symbol %d\n", symbol->id);
-#endif
- write_uint32 ((symbol->id << 3) | MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_ID);
- } else {
- ProfilerExecutableMemoryRegions *regions = profiler->executable_regions;
- const char *symbol_name = executable_region_symbol_get_name (region, symbol);
- symbol->id = regions->next_unmanaged_function_id;
- regions->next_unmanaged_function_id ++;
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Wrote new unmanaged symbol in region %d[%d]\n", region->id, offset);
-#endif
- write_uint32 ((region->id << 3) | MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_NEW_ID);
- write_uint32 (symbol->id);
- write_string (symbol_name);
- }
- } else {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Wrote unknown unmanaged hit in region %d[%d] (address %p)\n", region->id, offset, address);
-#endif
- write_uint32 ((region->id << 3) | MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_OFFSET_IN_REGION);
- write_uint32 (offset);
- }
- } else {
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_hit] Wrote unknown unmanaged hit %p\n", address);
-#endif
- write_uint32 (MONO_PROFILER_STATISTICAL_CODE_UNMANAGED_FUNCTION_OFFSET_IN_REGION);
- write_uint64 (GPOINTER_TO_UINT (address));
- }
- }
-
- return regions_refreshed;
-}
-
-static void
-flush_all_mappings (void);
-
-static void
-write_statistical_data_block (ProfilerStatisticalData *data) {
- int start_index = data->first_unwritten_index;
- int end_index = data->next_free_index;
- gboolean regions_refreshed = FALSE;
- int call_chain_depth = profiler->statistical_call_chain_depth;
- int index;
-
- if (end_index > data->end_index)
- end_index = data->end_index;
-
- if (start_index == end_index)
- return;
-
- data->first_unwritten_index = end_index;
-
- write_clock_data ();
-
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_data_block] Starting loop at index %d\n", start_index);
-#endif
-
- for (index = start_index; index < end_index; index ++) {
- int base_index = index * (call_chain_depth + 1);
- ProfilerStatisticalHit hit = data->hits [base_index];
- int callers_count;
-
- regions_refreshed = write_statistical_hit (hit.address, regions_refreshed);
- base_index ++;
-
- for (callers_count = 0; callers_count < call_chain_depth; callers_count ++) {
- hit = data->hits [base_index + callers_count];
- if (hit.address == NULL) {
- break;
- }
- }
-
- if (callers_count > 0) {
- write_uint32 ((callers_count << 3) | MONO_PROFILER_STATISTICAL_CODE_CALL_CHAIN);
-
- for (callers_count = 0; callers_count < call_chain_depth; callers_count ++) {
- hit = data->hits [base_index + callers_count];
- if (hit.address != NULL) {
- regions_refreshed = write_statistical_hit (hit.address, regions_refreshed);
- } else {
- break;
- }
- }
- }
- }
- write_uint32 (MONO_PROFILER_STATISTICAL_CODE_END);
-
-#if DEBUG_STATISTICAL_PROFILER
- printf ("[write_statistical_data_block] Ending loop at index %d\n", end_index);
-#endif
- write_clock_data ();
-
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_STATISTICAL);
-}
-
-static void
-write_intro_block (void) {
- write_uint32 (1);
- write_string ("mono");
- write_uint32 (profiler->flags);
- write_uint64 (profiler->start_counter);
- write_uint64 (profiler->start_time);
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_INTRO);
-}
-
-static void
-write_end_block (void) {
- write_uint32 (1);
- write_uint64 (profiler->end_counter);
- write_uint64 (profiler->end_time);
- write_current_block (MONO_PROFILER_FILE_BLOCK_KIND_END);
-}
-
-static void
-update_mapping (ProfilerPerThreadData *data) {
- ProfilerEventData *start = data->first_unmapped_event;
- ProfilerEventData *end = data->next_free_event;
- data->first_unmapped_event = end;
-
-#if (DEBUG_LOGGING_PROFILER)
- printf ("[update_mapping][TID %ld] START\n", data->thread_id);
-#endif
- while (start < end) {
-#if DEBUG_LOGGING_PROFILER
- printf ("Examining event %p[TID %ld] looking for a new mapping...\n", start, data->thread_id);
-#endif
- if (start->data_type == MONO_PROFILER_EVENT_DATA_TYPE_CLASS) {
- ClassIdMappingElement *element = class_id_mapping_element_get (start->data.address);
- if (element == NULL) {
- MonoClass *klass = start->data.address;
- class_id_mapping_element_new (klass);
- }
- } else if (start->data_type == MONO_PROFILER_EVENT_DATA_TYPE_METHOD) {
- MethodIdMappingElement *element = method_id_mapping_element_get (start->data.address);
- if (element == NULL) {
- MonoMethod *method = start->data.address;
- if (method != NULL) {
- method_id_mapping_element_new (method);
- }
- }
- }
-
- if (start->value == MAX_EVENT_VALUE) {
- start ++;
- }
- start ++;
- }
-#if (DEBUG_LOGGING_PROFILER)
- printf ("[update_mapping][TID %ld] END\n", data->thread_id);
-#endif
-}
-
-static void
-flush_all_mappings (void) {
- ProfilerPerThreadData *data;
-
- for (data = profiler->per_thread_data; data != NULL; data = data->next) {
- update_mapping (data);
- }
- for (data = profiler->per_thread_data; data != NULL; data = data->next) {
- write_mapping_block (data->thread_id);
- }
-}
-
-static void
-flush_full_event_data_buffer (ProfilerPerThreadData *data) {
- LOCK_PROFILER ();
-
- // We flush all mappings because some id definitions could come
- // from other threads
- flush_all_mappings ();
- g_assert (data->first_unmapped_event >= data->next_free_event);
-
- write_thread_data_block (data);
-
- data->next_free_event = data->events;
- data->next_unreserved_event = data->events;
- data->first_unwritten_event = data->events;
- data->first_unmapped_event = data->events;
- MONO_PROFILER_GET_CURRENT_COUNTER (data->start_event_counter);
- data->last_event_counter = data->start_event_counter;
-
- UNLOCK_PROFILER ();
-}
-
-/* The ">=" operator is intentional, to leave one spare slot for "extended values" */
-#define RESERVE_EVENTS(d,e,count) do {\
- if ((d)->next_unreserved_event >= ((d)->end_event - (count))) {\
- flush_full_event_data_buffer (d);\
- }\
- (e) = (d)->next_unreserved_event;\
- (d)->next_unreserved_event += (count);\
-} while (0)
-#define GET_NEXT_FREE_EVENT(d,e) RESERVE_EVENTS ((d),(e),1)
-#define COMMIT_RESERVED_EVENTS(d) do {\
- data->next_free_event = data->next_unreserved_event;\
-} while (0)
-
-static void
-flush_everything (void) {
- ProfilerPerThreadData *data;
-
- flush_all_mappings ();
- for (data = profiler->per_thread_data; data != NULL; data = data->next) {
- write_thread_data_block (data);
- }
- write_statistical_data_block (profiler->statistical_data);
-}
-
-#define RESULT_TO_LOAD_CODE(r) (((r)==MONO_PROFILE_OK)?MONO_PROFILER_LOADED_EVENT_SUCCESS:MONO_PROFILER_LOADED_EVENT_FAILURE)
-static void
-appdomain_start_load (MonoProfiler *profiler, MonoDomain *domain) {
- LOCK_PROFILER ();
- loaded_element_load_start (profiler->loaded_appdomains, domain);
- UNLOCK_PROFILER ();
-}
-
-static void
-appdomain_end_load (MonoProfiler *profiler, MonoDomain *domain, int result) {
- char *name;
- LoadedElement *element;
-
- name = g_strdup_printf ("%d", mono_domain_get_id (domain));
- LOCK_PROFILER ();
- element = loaded_element_load_end (profiler->loaded_appdomains, domain, name);
- write_element_load_block (element, MONO_PROFILER_LOADED_EVENT_APPDOMAIN | RESULT_TO_LOAD_CODE (result), CURRENT_THREAD_ID (), domain);
- UNLOCK_PROFILER ();
-}
-
-static void
-appdomain_start_unload (MonoProfiler *profiler, MonoDomain *domain) {
- LOCK_PROFILER ();
- loaded_element_unload_start (profiler->loaded_appdomains, domain);
- flush_everything ();
- UNLOCK_PROFILER ();
-}
-
-static void
-appdomain_end_unload (MonoProfiler *profiler, MonoDomain *domain) {
- LoadedElement *element;
-
- LOCK_PROFILER ();
- element = loaded_element_unload_end (profiler->loaded_appdomains, domain);
- write_element_unload_block (element, MONO_PROFILER_LOADED_EVENT_APPDOMAIN, CURRENT_THREAD_ID ());
- UNLOCK_PROFILER ();
-}
-
-static void
-module_start_load (MonoProfiler *profiler, MonoImage *module) {
- LOCK_PROFILER ();
- loaded_element_load_start (profiler->loaded_modules, module);
- UNLOCK_PROFILER ();
-}
-
-static void
-module_end_load (MonoProfiler *profiler, MonoImage *module, int result) {
- char *name;
- MonoAssemblyName aname;
- LoadedElement *element;
-
- if (mono_assembly_fill_assembly_name (module, &aname)) {
- name = mono_stringify_assembly_name (&aname);
- } else {
- name = g_strdup_printf ("Dynamic module \"%p\"", module);
- }
- LOCK_PROFILER ();
- element = loaded_element_load_end (profiler->loaded_modules, module, name);
- write_element_load_block (element, MONO_PROFILER_LOADED_EVENT_MODULE | RESULT_TO_LOAD_CODE (result), CURRENT_THREAD_ID (), module);
- UNLOCK_PROFILER ();
-}
-
-static void
-module_start_unload (MonoProfiler *profiler, MonoImage *module) {
- LOCK_PROFILER ();
- loaded_element_unload_start (profiler->loaded_modules, module);
- flush_everything ();
- UNLOCK_PROFILER ();
-}
-
-static void
-module_end_unload (MonoProfiler *profiler, MonoImage *module) {
- LoadedElement *element;
-
- LOCK_PROFILER ();
- element = loaded_element_unload_end (profiler->loaded_modules, module);
- write_element_unload_block (element, MONO_PROFILER_LOADED_EVENT_MODULE, CURRENT_THREAD_ID ());
- UNLOCK_PROFILER ();
-}
-
-static void
-assembly_start_load (MonoProfiler *profiler, MonoAssembly *assembly) {
- LOCK_PROFILER ();
- loaded_element_load_start (profiler->loaded_assemblies, assembly);
- UNLOCK_PROFILER ();
-}
-
-static void
-assembly_end_load (MonoProfiler *profiler, MonoAssembly *assembly, int result) {
- char *name;
- MonoAssemblyName aname;
- LoadedElement *element;
-
- if (mono_assembly_fill_assembly_name (mono_assembly_get_image (assembly), &aname)) {
- name = mono_stringify_assembly_name (&aname);
- } else {
- name = g_strdup_printf ("Dynamic assembly \"%p\"", assembly);
- }
- LOCK_PROFILER ();
- element = loaded_element_load_end (profiler->loaded_assemblies, assembly, name);
- write_element_load_block (element, MONO_PROFILER_LOADED_EVENT_ASSEMBLY | RESULT_TO_LOAD_CODE (result), CURRENT_THREAD_ID (), assembly);
- UNLOCK_PROFILER ();
-}
-
-static void
-assembly_start_unload (MonoProfiler *profiler, MonoAssembly *assembly) {
- LOCK_PROFILER ();
- loaded_element_unload_start (profiler->loaded_assemblies, assembly);
- flush_everything ();
- UNLOCK_PROFILER ();
-}
-static void
-assembly_end_unload (MonoProfiler *profiler, MonoAssembly *assembly) {
- LoadedElement *element;
-
- LOCK_PROFILER ();
- element = loaded_element_unload_end (profiler->loaded_assemblies, assembly);
- write_element_unload_block (element, MONO_PROFILER_LOADED_EVENT_ASSEMBLY, CURRENT_THREAD_ID ());
- UNLOCK_PROFILER ();
-}
-
-#if (DEBUG_LOGGING_PROFILER)
-static const char*
-class_event_code_to_string (MonoProfilerClassEvents code) {
- switch (code) {
- case MONO_PROFILER_EVENT_CLASS_LOAD: return "LOAD";
- case MONO_PROFILER_EVENT_CLASS_UNLOAD: return "UNLOAD";
- case MONO_PROFILER_EVENT_CLASS_ALLOCATION: return "ALLOCATION";
- case MONO_PROFILER_EVENT_CLASS_EXCEPTION: return "EXCEPTION";
- default: g_assert_not_reached (); return "";
- }
-}
-static const char*
-method_event_code_to_string (MonoProfilerMethodEvents code) {
- switch (code) {
- case MONO_PROFILER_EVENT_METHOD_CALL: return "CALL";
- case MONO_PROFILER_EVENT_METHOD_JIT: return "JIT";
- case MONO_PROFILER_EVENT_METHOD_FREED: return "FREED";
- case MONO_PROFILER_EVENT_METHOD_ALLOCATION_CALLER: return "ALLOCATION_CALLER";
- case MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER: return "ALLOCATION_JIT_TIME_CALLER";
- case MONO_PROFILER_EVENT_ALLOCATION_OBJECT_ID: return "ALLOCATION_OBJECT_ID";
- default: g_assert_not_reached (); return "";
- }
-}
-static const char*
-number_event_code_to_string (MonoProfilerEvents code) {
- switch (code) {
- case MONO_PROFILER_EVENT_THREAD: return "THREAD";
- case MONO_PROFILER_EVENT_GC_COLLECTION: return "GC_COLLECTION";
- case MONO_PROFILER_EVENT_GC_MARK: return "GC_MARK";
- case MONO_PROFILER_EVENT_GC_SWEEP: return "GC_SWEEP";
- case MONO_PROFILER_EVENT_GC_RESIZE: return "GC_RESIZE";
- case MONO_PROFILER_EVENT_GC_STOP_WORLD: return "GC_STOP_WORLD";
- case MONO_PROFILER_EVENT_GC_START_WORLD: return "GC_START_WORLD";
- case MONO_PROFILER_EVENT_JIT_TIME_ALLOCATION: return "JIT_TIME_ALLOCATION";
- case MONO_PROFILER_EVENT_STACK_SECTION: return "STACK_SECTION";
- case MONO_PROFILER_EVENT_ALLOCATION_OBJECT_ID: return "ALLOCATION_OBJECT_ID";
- default: g_assert_not_reached (); return "";
- }
-}
-static const char*
-event_result_to_string (MonoProfilerEventResult code) {
- switch (code) {
- case MONO_PROFILER_EVENT_RESULT_SUCCESS: return "SUCCESS";
- case MONO_PROFILER_EVENT_RESULT_FAILURE: return "FAILURE";
- default: g_assert_not_reached (); return "";
- }
-}
-static const char*
-event_kind_to_string (MonoProfilerEventKind code) {
- switch (code) {
- case MONO_PROFILER_EVENT_KIND_START: return "START";
- case MONO_PROFILER_EVENT_KIND_END: return "END";
- default: g_assert_not_reached (); return "";
- }
-}
-static void
-print_event_data (ProfilerPerThreadData *data, ProfilerEventData *event, guint64 value) {
- if (event->data_type == MONO_PROFILER_EVENT_DATA_TYPE_CLASS) {
- printf ("STORE EVENT [TID %ld][EVENT %ld] CLASS[%p] %s:%s:%s[%d-%d-%d] %ld (%s.%s)\n",
- data->thread_id,
- event - data->events,
- event->data.address,
- class_event_code_to_string (event->code & ~MONO_PROFILER_EVENT_RESULT_MASK),
- event_result_to_string (event->code & MONO_PROFILER_EVENT_RESULT_MASK),
- event_kind_to_string (event->kind),
- event->data_type,
- event->kind,
- event->code,
- value,
- mono_class_get_namespace ((MonoClass*) event->data.address),
- mono_class_get_name ((MonoClass*) event->data.address));
- } else if (event->data_type == MONO_PROFILER_EVENT_DATA_TYPE_METHOD) {
- printf ("STORE EVENT [TID %ld][EVENT %ld] METHOD[%p] %s:%s:%s[%d-%d-%d] %ld (%s.%s:%s (?))\n",
- data->thread_id,
- event - data->events,
- event->data.address,
- method_event_code_to_string (event->code & ~MONO_PROFILER_EVENT_RESULT_MASK),
- event_result_to_string (event->code & MONO_PROFILER_EVENT_RESULT_MASK),
- event_kind_to_string (event->kind),
- event->data_type,
- event->kind,
- event->code,
- value,
- (event->data.address != NULL) ? mono_class_get_namespace (mono_method_get_class ((MonoMethod*) event->data.address)) : "<NULL>",
- (event->data.address != NULL) ? mono_class_get_name (mono_method_get_class ((MonoMethod*) event->data.address)) : "<NULL>",
- (event->data.address != NULL) ? mono_method_get_name ((MonoMethod*) event->data.address) : "<NULL>");
- } else {
- printf ("STORE EVENT [TID %ld][EVENT %ld] NUMBER[%ld] %s:%s[%d-%d-%d] %ld\n",
- data->thread_id,
- event - data->events,
- (guint64) event->data.number,
- number_event_code_to_string (event->code),
- event_kind_to_string (event->kind),
- event->data_type,
- event->kind,
- event->code,
- value);
- }
-}
-#define LOG_EVENT(data,ev,val) print_event_data ((data),(ev),(val))
-#else
-#define LOG_EVENT(data,ev,val)
-#endif
-
-#define RESULT_TO_EVENT_CODE(r) (((r)==MONO_PROFILE_OK)?MONO_PROFILER_EVENT_RESULT_SUCCESS:MONO_PROFILER_EVENT_RESULT_FAILURE)
-
-#define STORE_EVENT_ITEM_COUNTER(event,p,i,dt,c,k) do {\
- guint64 counter;\
- guint64 delta;\
- MONO_PROFILER_GET_CURRENT_COUNTER (counter);\
- (event)->data.address = (i);\
- (event)->data_type = (dt);\
- (event)->code = (c);\
- (event)->kind = (k);\
- delta = counter - data->last_event_counter;\
- if (delta < MAX_EVENT_VALUE) {\
- (event)->value = delta;\
- } else {\
- ProfilerEventData *extension = data->next_unreserved_event;\
- data->next_unreserved_event ++;\
- (event)->value = MAX_EVENT_VALUE;\
- *(guint64*)extension = delta;\
- }\
- data->last_event_counter = counter;\
- LOG_EVENT (data, (event), delta);\
-} while (0);
-#define STORE_EVENT_ITEM_VALUE(event,p,i,dt,c,k,v) do {\
- (event)->data.address = (i);\
- (event)->data_type = (dt);\
- (event)->code = (c);\
- (event)->kind = (k);\
- if ((v) < MAX_EVENT_VALUE) {\
- (event)->value = (v);\
- } else {\
- ProfilerEventData *extension = data->next_unreserved_event;\
- data->next_unreserved_event ++;\
- (event)->value = MAX_EVENT_VALUE;\
- *(guint64*)extension = (v);\
- }\
- LOG_EVENT (data, (event), (v));\
-}while (0);
-#define STORE_EVENT_NUMBER_COUNTER(event,p,n,dt,c,k) do {\
- guint64 counter;\
- guint64 delta;\
- MONO_PROFILER_GET_CURRENT_COUNTER (counter);\
- (event)->data.number = (n);\
- (event)->data_type = (dt);\
- (event)->code = (c);\
- (event)->kind = (k);\
- delta = counter - data->last_event_counter;\
- if (delta < MAX_EVENT_VALUE) {\
- (event)->value = delta;\
- } else {\
- ProfilerEventData *extension = data->next_unreserved_event;\
- data->next_unreserved_event ++;\
- (event)->value = MAX_EVENT_VALUE;\
- *(guint64*)extension = delta;\
- }\
- data->last_event_counter = counter;\
- LOG_EVENT (data, (event), delta);\
-}while (0);
-#define STORE_EVENT_NUMBER_VALUE(event,p,n,dt,c,k,v) do {\
- (event)->data.number = (n);\
- (event)->data_type = (dt);\
- (event)->code = (c);\
- (event)->kind = (k);\
- if ((v) < MAX_EVENT_VALUE) {\
- (event)->value = (v);\
- } else {\
- ProfilerEventData *extension = data->next_unreserved_event;\
- data->next_unreserved_event ++;\
- (event)->value = MAX_EVENT_VALUE;\
- *(guint64*)extension = (v);\
- }\
- LOG_EVENT (data, (event), (v));\
-}while (0);
-#define INCREMENT_EVENT(event) do {\
- if ((event)->value != MAX_EVENT_VALUE) {\
- (event) ++;\
- } else {\
- (event) += 2;\
- }\
-}while (0);
-
-static void
-class_start_load (MonoProfiler *profiler, MonoClass *klass) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, klass, MONO_PROFILER_EVENT_DATA_TYPE_CLASS, MONO_PROFILER_EVENT_CLASS_LOAD, MONO_PROFILER_EVENT_KIND_START);
- COMMIT_RESERVED_EVENTS (data);
-}
-static void
-class_end_load (MonoProfiler *profiler, MonoClass *klass, int result) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, klass, MONO_PROFILER_EVENT_DATA_TYPE_CLASS, MONO_PROFILER_EVENT_CLASS_LOAD | RESULT_TO_EVENT_CODE (result), MONO_PROFILER_EVENT_KIND_END);
- COMMIT_RESERVED_EVENTS (data);
-}
-static void
-class_start_unload (MonoProfiler *profiler, MonoClass *klass) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, klass, MONO_PROFILER_EVENT_DATA_TYPE_CLASS, MONO_PROFILER_EVENT_CLASS_UNLOAD, MONO_PROFILER_EVENT_KIND_START);
- COMMIT_RESERVED_EVENTS (data);
-}
-static void
-class_end_unload (MonoProfiler *profiler, MonoClass *klass) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, klass, MONO_PROFILER_EVENT_DATA_TYPE_CLASS, MONO_PROFILER_EVENT_CLASS_UNLOAD, MONO_PROFILER_EVENT_KIND_END);
- COMMIT_RESERVED_EVENTS (data);
-}
-
-static void
-method_start_jit (MonoProfiler *profiler, MonoMethod *method) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- thread_stack_push_jitted_safely (&(data->stack), method, TRUE);
- STORE_EVENT_ITEM_COUNTER (event, profiler, method, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_JIT, MONO_PROFILER_EVENT_KIND_START);
- COMMIT_RESERVED_EVENTS (data);
-}
-static void
-method_end_jit (MonoProfiler *profiler, MonoMethod *method, int result) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, method, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_JIT | RESULT_TO_EVENT_CODE (result), MONO_PROFILER_EVENT_KIND_END);
- thread_stack_pop (&(data->stack));
- COMMIT_RESERVED_EVENTS (data);
-}
-
-#if (HAS_OPROFILE)
-static void
-method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
- if (profiler->action_flags.oprofile && (result == MONO_PROFILE_OK)) {
- MonoClass *klass = mono_method_get_class (method);
- char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
- char *name = g_strdup_printf ("%s.%s:%s (%s)", mono_class_get_namespace (klass), mono_class_get_name (klass), mono_method_get_name (method), signature);
- gpointer code_start = mono_jit_info_get_code_start (jinfo);
- int code_size = mono_jit_info_get_code_size (jinfo);
-
- if (op_write_native_code (name, code_start, code_size)) {
- g_warning ("Problem calling op_write_native_code\n");
- }
-
- g_free (signature);
- g_free (name);
- }
-}
-#endif
-
-
-static void
-method_enter (MonoProfiler *profiler, MonoMethod *method) {
- ProfilerPerThreadData *data;
-
- CHECK_PROFILER_ENABLED ();
- GET_PROFILER_THREAD_DATA (data);
- if (profiler->action_flags.track_calls) {
- ProfilerEventData *event;
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, method, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_CALL, MONO_PROFILER_EVENT_KIND_START);
- COMMIT_RESERVED_EVENTS (data);
- }
- if (profiler->action_flags.track_stack) {
- thread_stack_push_safely (&(data->stack), method);
- }
-}
-static void
-method_leave (MonoProfiler *profiler, MonoMethod *method) {
- ProfilerPerThreadData *data;
-
- CHECK_PROFILER_ENABLED ();
- GET_PROFILER_THREAD_DATA (data);
- if (profiler->action_flags.track_calls) {
- ProfilerEventData *event;
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, method, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_CALL, MONO_PROFILER_EVENT_KIND_END);
- COMMIT_RESERVED_EVENTS (data);
- }
- if (profiler->action_flags.track_stack) {
- thread_stack_pop (&(data->stack));
- }
-}
-
-static void
-method_free (MonoProfiler *profiler, MonoMethod *method) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_ITEM_COUNTER (event, profiler, method, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_FREED, 0);
- COMMIT_RESERVED_EVENTS (data);
-}
-
-static void
-thread_start (MonoProfiler *profiler, uintptr_t tid) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_NUMBER_COUNTER (event, profiler, tid, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, MONO_PROFILER_EVENT_THREAD, MONO_PROFILER_EVENT_KIND_START);
- COMMIT_RESERVED_EVENTS (data);
-}
-static void
-thread_end (MonoProfiler *profiler, uintptr_t tid) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_NUMBER_COUNTER (event, profiler, tid, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, MONO_PROFILER_EVENT_THREAD, MONO_PROFILER_EVENT_KIND_END);
- COMMIT_RESERVED_EVENTS (data);
-}
-
-static ProfilerEventData*
-save_stack_delta (MonoProfiler *profiler, ProfilerPerThreadData *data, ProfilerEventData *events, int unsaved_frames) {
- int i;
-
- /* In this loop it is safe to simply increment "events" because MAX_EVENT_VALUE cannot be reached. */
- STORE_EVENT_NUMBER_VALUE (events, profiler, data->stack.last_saved_top, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, MONO_PROFILER_EVENT_STACK_SECTION, 0, unsaved_frames);
- events++;
- for (i = 0; i < unsaved_frames; i++) {
- if (! thread_stack_index_from_top_is_jitted (&(data->stack), i)) {
- STORE_EVENT_ITEM_VALUE (events, profiler, thread_stack_index_from_top (&(data->stack), i), MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_ALLOCATION_CALLER, 0, 0);
- } else {
- STORE_EVENT_ITEM_VALUE (events, profiler, thread_stack_index_from_top (&(data->stack), i), MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER, 0, 0);
- }
- events ++;
- }
-
- data->stack.last_saved_top = data->stack.top;
-
- return events;
-}
-
-static void
-object_allocated (MonoProfiler *profiler, MonoObject *obj, MonoClass *klass) {
- ProfilerPerThreadData *data;
- ProfilerEventData *events;
- int unsaved_frames;
- int event_slot_count;
-
- GET_PROFILER_THREAD_DATA (data);
- event_slot_count = 1;
- if (profiler->action_flags.save_allocation_caller) {
- event_slot_count ++;
- }
- if (profiler->action_flags.allocations_carry_id) {
- event_slot_count ++;
- }
- if (profiler->action_flags.save_allocation_stack) {
- unsaved_frames = thread_stack_count_unsaved_frames (&(data->stack));
- event_slot_count += (unsaved_frames + 1);
- } else {
- unsaved_frames = 0;
- }
- RESERVE_EVENTS (data, events, event_slot_count);
-
- if (profiler->action_flags.save_allocation_stack) {
- events = save_stack_delta (profiler, data, events, unsaved_frames);
- }
-
- STORE_EVENT_ITEM_VALUE (events, profiler, klass, MONO_PROFILER_EVENT_DATA_TYPE_CLASS, MONO_PROFILER_EVENT_CLASS_ALLOCATION, 0, (guint64) mono_object_get_size (obj));
- if (profiler->action_flags.unreachable_objects || profiler->action_flags.heap_shot || profiler->action_flags.collection_summary) {
- STORE_ALLOCATED_OBJECT (data, obj);
- }
-
- if (profiler->action_flags.save_allocation_caller) {
- MonoMethod *caller = thread_stack_top (&(data->stack));
- gboolean caller_is_jitted = thread_stack_top_is_jitted (&(data->stack));
- int index = 1;
- /* In this loop it is safe to simply increment "events" because MAX_EVENT_VALUE cannot be reached. */
- events ++;
-
- while ((caller != NULL) && (caller->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)) {
- caller = thread_stack_index_from_top (&(data->stack), index);
- caller_is_jitted = thread_stack_index_from_top_is_jitted (&(data->stack), index);
- index ++;
- }
- if (! caller_is_jitted) {
- STORE_EVENT_ITEM_VALUE (events, profiler, caller, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_ALLOCATION_CALLER, 0, 0);
- } else {
- STORE_EVENT_ITEM_VALUE (events, profiler, caller, MONO_PROFILER_EVENT_DATA_TYPE_METHOD, MONO_PROFILER_EVENT_METHOD_ALLOCATION_JIT_TIME_CALLER, 0, 0);
- }
- }
- if (profiler->action_flags.allocations_carry_id) {
- events ++;
- STORE_EVENT_ITEM_VALUE (events, profiler, obj, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, MONO_PROFILER_EVENT_ALLOCATION_OBJECT_ID, 0, 0);
- }
-
- COMMIT_RESERVED_EVENTS (data);
-}
-
-static void
-monitor_event (MonoProfiler *profiler, MonoObject *obj, MonoProfilerMonitorEvent event) {
- ProfilerPerThreadData *data;
- ProfilerEventData *events;
- MonoClass *klass;
- int unsaved_frames;
- int event_slot_count;
-
- CHECK_PROFILER_ENABLED ();
-
- GET_PROFILER_THREAD_DATA (data);
- klass = mono_object_get_class (obj);
-
- unsaved_frames = thread_stack_count_unsaved_frames (&(data->stack));
- if (unsaved_frames > 0) {
- event_slot_count = unsaved_frames + 3;
- } else {
- event_slot_count = 2;
- }
-
- RESERVE_EVENTS (data, events, event_slot_count);
- if (unsaved_frames > 0) {
- events = save_stack_delta (profiler, data, events, unsaved_frames);
- }
- STORE_EVENT_ITEM_COUNTER (events, profiler, klass, MONO_PROFILER_EVENT_DATA_TYPE_CLASS, MONO_PROFILER_EVENT_CLASS_MONITOR, MONO_PROFILER_EVENT_KIND_START);
- INCREMENT_EVENT (events);
- STORE_EVENT_ITEM_VALUE (events, profiler, obj, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, MONO_PROFILER_EVENT_OBJECT_MONITOR, 0, event);
- COMMIT_RESERVED_EVENTS (data);
-}
-
-static void
-statistical_call_chain (MonoProfiler *profiler, int call_chain_depth, guchar **ips, void *context) {
- MonoDomain *domain = mono_domain_get ();
- ProfilerStatisticalData *data;
- unsigned int index;
-
- CHECK_PROFILER_ENABLED ();
- do {
- data = profiler->statistical_data;
- index = InterlockedIncrement ((int*) &data->next_free_index);
-
- if (index <= data->end_index) {
- unsigned int base_index = (index - 1) * (profiler->statistical_call_chain_depth + 1);
- unsigned int call_chain_index = 0;
-
- //printf ("[statistical_call_chain] (%d)\n", call_chain_depth);
- while (call_chain_index < call_chain_depth) {
- ProfilerStatisticalHit *hit = & (data->hits [base_index + call_chain_index]);
- //printf ("[statistical_call_chain] [%d] = %p\n", base_index + call_chain_index, ips [call_chain_index]);
- hit->address = (gpointer) ips [call_chain_index];
- hit->domain = domain;
- call_chain_index ++;
- }
- while (call_chain_index <= profiler->statistical_call_chain_depth) {
- ProfilerStatisticalHit *hit = & (data->hits [base_index + call_chain_index]);
- //printf ("[statistical_call_chain] [%d] = NULL\n", base_index + call_chain_index);
- hit->address = NULL;
- hit->domain = NULL;
- call_chain_index ++;
- }
- } else {
- /* Check if we are the one that must swap the buffers */
- if (index == data->end_index + 1) {
- ProfilerStatisticalData *new_data;
-
- /* In the *impossible* case that the writer thread has not finished yet, */
- /* loop waiting for it and meanwhile lose all statistical events... */
- do {
- /* First, wait that it consumed the ready buffer */
- while (profiler->statistical_data_ready != NULL);
- /* Then, wait that it produced the free buffer */
- new_data = profiler->statistical_data_second_buffer;
- } while (new_data == NULL);
-
- profiler->statistical_data_ready = data;
- profiler->statistical_data = new_data;
- profiler->statistical_data_second_buffer = NULL;
- WRITER_EVENT_RAISE ();
- /* Otherwise exit from the handler and drop the event... */
- } else {
- break;
- }
-
- /* Loop again, hoping to acquire a free slot this time (otherwise the event will be dropped) */
- data = NULL;
- }
- } while (data == NULL);
-}
-
-static void
-statistical_hit (MonoProfiler *profiler, guchar *ip, void *context) {
- MonoDomain *domain = mono_domain_get ();
- ProfilerStatisticalData *data;
- unsigned int index;
-
- CHECK_PROFILER_ENABLED ();
- do {
- data = profiler->statistical_data;
- index = InterlockedIncrement ((int*) &data->next_free_index);
-
- if (index <= data->end_index) {
- ProfilerStatisticalHit *hit = & (data->hits [index - 1]);
- hit->address = (gpointer) ip;
- hit->domain = domain;
- } else {
- /* Check if we are the one that must swap the buffers */
- if (index == data->end_index + 1) {
- ProfilerStatisticalData *new_data;
-
- /* In the *impossible* case that the writer thread has not finished yet, */
- /* loop waiting for it and meanwhile lose all statistical events... */
- do {
- /* First, wait that it consumed the ready buffer */
- while (profiler->statistical_data_ready != NULL);
- /* Then, wait that it produced the free buffer */
- new_data = profiler->statistical_data_second_buffer;
- } while (new_data == NULL);
-
- profiler->statistical_data_ready = data;
- profiler->statistical_data = new_data;
- profiler->statistical_data_second_buffer = NULL;
- WRITER_EVENT_RAISE ();
- }
-
- /* Loop again, hoping to acquire a free slot this time */
- data = NULL;
- }
- } while (data == NULL);
-}
-
-static MonoProfilerEvents
-gc_event_code_from_profiler_event (MonoGCEvent event) {
- switch (event) {
- case MONO_GC_EVENT_START:
- case MONO_GC_EVENT_END:
- return MONO_PROFILER_EVENT_GC_COLLECTION;
- case MONO_GC_EVENT_MARK_START:
- case MONO_GC_EVENT_MARK_END:
- return MONO_PROFILER_EVENT_GC_MARK;
- case MONO_GC_EVENT_RECLAIM_START:
- case MONO_GC_EVENT_RECLAIM_END:
- return MONO_PROFILER_EVENT_GC_SWEEP;
- case MONO_GC_EVENT_PRE_STOP_WORLD:
- case MONO_GC_EVENT_POST_STOP_WORLD:
- return MONO_PROFILER_EVENT_GC_STOP_WORLD;
- case MONO_GC_EVENT_PRE_START_WORLD:
- case MONO_GC_EVENT_POST_START_WORLD:
- return MONO_PROFILER_EVENT_GC_START_WORLD;
- default:
- g_assert_not_reached ();
- return 0;
- }
-}
-
-static MonoProfilerEventKind
-gc_event_kind_from_profiler_event (MonoGCEvent event) {
- switch (event) {
- case MONO_GC_EVENT_START:
- case MONO_GC_EVENT_MARK_START:
- case MONO_GC_EVENT_RECLAIM_START:
- case MONO_GC_EVENT_PRE_STOP_WORLD:
- case MONO_GC_EVENT_PRE_START_WORLD:
- return MONO_PROFILER_EVENT_KIND_START;
- case MONO_GC_EVENT_END:
- case MONO_GC_EVENT_MARK_END:
- case MONO_GC_EVENT_RECLAIM_END:
- case MONO_GC_EVENT_POST_START_WORLD:
- case MONO_GC_EVENT_POST_STOP_WORLD:
- return MONO_PROFILER_EVENT_KIND_END;
- default:
- g_assert_not_reached ();
- return 0;
- }
-}
-
-static gboolean
-dump_current_heap_snapshot (void) {
- gboolean result;
-
- if (profiler->heap_shot_was_requested) {
- result = TRUE;
- } else {
- if (profiler->dump_next_heap_snapshots > 0) {
- profiler->dump_next_heap_snapshots--;
- result = TRUE;
- } else if (profiler->dump_next_heap_snapshots < 0) {
- result = TRUE;
- } else {
- result = FALSE;
- }
- }
-
- return result;
-}
-
-static void
-profiler_heap_buffers_setup (ProfilerHeapShotHeapBuffers *heap) {
- heap->buffers = g_new (ProfilerHeapShotHeapBuffer, 1);
- heap->buffers->previous = NULL;
- heap->buffers->next = NULL;
- heap->buffers->start_slot = &(heap->buffers->buffer [0]);
- heap->buffers->end_slot = &(heap->buffers->buffer [PROFILER_HEAP_SHOT_HEAP_BUFFER_SIZE]);
- heap->last = heap->buffers;
- heap->current = heap->buffers;
- heap->first_free_slot = & (heap->buffers->buffer [0]);
-}
-static void
-profiler_heap_buffers_clear (ProfilerHeapShotHeapBuffers *heap) {
- heap->buffers = NULL;
- heap->last = NULL;
- heap->current = NULL;
- heap->first_free_slot = NULL;
-}
-static void
-profiler_heap_buffers_free (ProfilerHeapShotHeapBuffers *heap) {
- ProfilerHeapShotHeapBuffer *current = heap->buffers;
- while (current != NULL) {
- ProfilerHeapShotHeapBuffer *next = current->next;
- g_free (current);
- current = next;
- }
- profiler_heap_buffers_clear (heap);
-}
-
-static int
-report_object_references (gpointer *start, ClassIdMappingElement *layout, ProfilerHeapShotWriteJob *job) {
- int reported_references = 0;
- int slot;
-
- for (slot = 0; slot < layout->data.layout.slots; slot ++) {
- gboolean slot_has_reference;
- if (layout->data.layout.slots <= CLASS_LAYOUT_PACKED_BITMAP_SIZE) {
- if (layout->data.bitmap.compact & (((guint64)1) << slot)) {
- slot_has_reference = TRUE;
- } else {
- slot_has_reference = FALSE;
- }
- } else {
- if (layout->data.bitmap.extended [slot >> 3] & (1 << (slot & 7))) {
- slot_has_reference = TRUE;
- } else {
- slot_has_reference = FALSE;
- }
- }
-
- if (slot_has_reference) {
- gpointer field = start [slot];
-
- if ((field != NULL) && mono_object_is_alive (field)) {
- reported_references ++;
- WRITE_HEAP_SHOT_JOB_VALUE (job, field);
- }
- }
- }
-
- return reported_references;
-}
-
-static void
-profiler_heap_report_object_reachable (ProfilerHeapShotWriteJob *job, MonoObject *obj) {
- if (job != NULL) {
- MonoClass *klass = mono_object_get_class (obj);
- ClassIdMappingElement *class_id = class_id_mapping_element_get (klass);
- if (class_id == NULL) {
- printf ("profiler_heap_report_object_reachable: class %p (%s.%s) has no id\n", klass, mono_class_get_namespace (klass), mono_class_get_name (klass));
- }
- g_assert (class_id != NULL);
-
- if (job->summary.capacity > 0) {
- guint32 id = class_id->id;
- g_assert (id < job->summary.capacity);
-
- job->summary.per_class_data [id].reachable.instances ++;
- job->summary.per_class_data [id].reachable.bytes += mono_object_get_size (obj);
- }
- if (profiler->action_flags.heap_shot && job->dump_heap_data) {
- int reference_counter = 0;
- gpointer *reference_counter_location;
-
- WRITE_HEAP_SHOT_JOB_VALUE_WITH_CODE (job, obj, HEAP_CODE_OBJECT);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_report_object_reachable: reported object %p at cursor %p\n", obj, (job->cursor - 1));
-#endif
- WRITE_HEAP_SHOT_JOB_VALUE (job, NULL);
- reference_counter_location = job->cursor - 1;
-
- if (mono_class_get_rank (klass)) {
- MonoArray *array = (MonoArray *) obj;
- MonoClass *element_class = mono_class_get_element_class (klass);
- ClassIdMappingElement *element_id = class_id_mapping_element_get (element_class);
-
- g_assert (element_id != NULL);
- if (element_id->data.layout.slots == CLASS_LAYOUT_NOT_INITIALIZED) {
- class_id_mapping_element_build_layout_bitmap (element_class, element_id);
- }
- if (! mono_class_is_valuetype (element_class)) {
- int length = mono_array_length (array);
- int i;
- for (i = 0; i < length; i++) {
- MonoObject *array_element = mono_array_get (array, MonoObject*, i);
- if ((array_element != NULL) && mono_object_is_alive (array_element)) {
- reference_counter ++;
- WRITE_HEAP_SHOT_JOB_VALUE (job, array_element);
- }
- }
- } else if (element_id->data.layout.references > 0) {
- int length = mono_array_length (array);
- int array_element_size = mono_array_element_size (klass);
- int i;
- for (i = 0; i < length; i++) {
- gpointer array_element_address = mono_array_addr_with_size (array, array_element_size, i);
- reference_counter += report_object_references (array_element_address, element_id, job);
- }
- }
- } else {
- if (class_id->data.layout.slots == CLASS_LAYOUT_NOT_INITIALIZED) {
- class_id_mapping_element_build_layout_bitmap (klass, class_id);
- }
- if (class_id->data.layout.references > 0) {
- reference_counter += report_object_references ((gpointer)(((char*)obj) + sizeof (MonoObject)), class_id, job);
- }
- }
-
- *reference_counter_location = GINT_TO_POINTER (reference_counter);
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_report_object_reachable: updated reference_counter_location %p with value %d\n", reference_counter_location, reference_counter);
-#endif
- }
- }
-}
-static void
-profiler_heap_report_object_unreachable (ProfilerHeapShotWriteJob *job, MonoObject *obj) {
- if (job != NULL) {
- MonoClass *klass = mono_object_get_class (obj);
- guint32 size = mono_object_get_size (obj);
-
- if (job->summary.capacity > 0) {
- ClassIdMappingElement *class_id = class_id_mapping_element_get (klass);
- guint32 id;
-
- if (class_id == NULL) {
- printf ("profiler_heap_report_object_reachable: class %p (%s.%s) has no id\n", klass, mono_class_get_namespace (klass), mono_class_get_name (klass));
- }
- g_assert (class_id != NULL);
- id = class_id->id;
- g_assert (id < job->summary.capacity);
-
- job->summary.per_class_data [id].unreachable.instances ++;
- job->summary.per_class_data [id].unreachable.bytes += size;
- }
- if (profiler->action_flags.unreachable_objects && job->dump_heap_data) {
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_report_object_unreachable: at job %p writing klass %p\n", job, klass);
-#endif
- WRITE_HEAP_SHOT_JOB_VALUE_WITH_CODE (job, klass, HEAP_CODE_FREE_OBJECT_CLASS);
-
-#if DEBUG_HEAP_PROFILER
- printf ("profiler_heap_report_object_unreachable: at job %p writing size %p\n", job, GUINT_TO_POINTER (size));
-#endif
- WRITE_HEAP_SHOT_JOB_VALUE (job, GUINT_TO_POINTER (size));
- }
- }
-}
-
-static void
-profiler_heap_add_object (ProfilerHeapShotHeapBuffers *heap, ProfilerHeapShotWriteJob *job, MonoObject *obj) {
- if (heap->first_free_slot >= heap->current->end_slot) {
- if (heap->current->next != NULL) {
- heap->current = heap->current->next;
- } else {
- ProfilerHeapShotHeapBuffer *buffer = g_new (ProfilerHeapShotHeapBuffer, 1);
- buffer->previous = heap->last;
- buffer->next = NULL;
- buffer->start_slot = &(buffer->buffer [0]);
- buffer->end_slot = &(buffer->buffer [PROFILER_HEAP_SHOT_HEAP_BUFFER_SIZE]);
- heap->current = buffer;
- heap->last->next = buffer;
- heap->last = buffer;
- }
- heap->first_free_slot = &(heap->current->buffer [0]);
- }
-
- *(heap->first_free_slot) = obj;
- heap->first_free_slot ++;
- profiler_heap_report_object_reachable (job, obj);
-}
-
-static MonoObject*
-profiler_heap_pop_object_from_end (ProfilerHeapShotHeapBuffers *heap, ProfilerHeapShotWriteJob *job, MonoObject** current_slot) {
- while (heap->first_free_slot != current_slot) {
- MonoObject* obj;
-
- if (heap->first_free_slot > heap->current->start_slot) {
- heap->first_free_slot --;
- } else {
- heap->current = heap->current->previous;
- g_assert (heap->current != NULL);
- heap->first_free_slot = heap->current->end_slot - 1;
- }
-
- obj = *(heap->first_free_slot);
-
- if (mono_object_is_alive (obj)) {
- profiler_heap_report_object_reachable (job, obj);
- return obj;
- } else {
- profiler_heap_report_object_unreachable (job, obj);
- }
- }
- return NULL;
-}
-
-static void
-profiler_heap_scan (ProfilerHeapShotHeapBuffers *heap, ProfilerHeapShotWriteJob *job) {
- ProfilerHeapShotHeapBuffer *current_buffer = heap->buffers;
- MonoObject** current_slot = current_buffer->start_slot;
-
- while (current_slot != heap->first_free_slot) {
- MonoObject *obj = *current_slot;
- if (mono_object_is_alive (obj)) {
- profiler_heap_report_object_reachable (job, obj);
- } else {
- profiler_heap_report_object_unreachable (job, obj);
- *current_slot = profiler_heap_pop_object_from_end (heap, job, current_slot);
- }
-
- if (*current_slot != NULL) {
- current_slot ++;
-
- if (current_slot == current_buffer->end_slot) {
- current_buffer = current_buffer->next;
- g_assert (current_buffer != NULL);
- current_slot = current_buffer->start_slot;
- }
- }
- }
-}
-
-static inline gboolean
-heap_shot_write_job_should_be_created (gboolean dump_heap_data) {
- return dump_heap_data || profiler->action_flags.unreachable_objects || profiler->action_flags.collection_summary;
-}
-
-static void
-process_gc_event (MonoProfiler *profiler, gboolean do_heap_profiling, MonoGCEvent ev) {
- static gboolean dump_heap_data;
-
- switch (ev) {
- case MONO_GC_EVENT_PRE_STOP_WORLD:
- // Get the lock, so we are sure nobody is flushing events during the collection,
- // and we can update all mappings (building the class descriptors).
- // This is necessary also during lock profiling (even if do_heap_profiling is FALSE).
- LOCK_PROFILER ();
- break;
- case MONO_GC_EVENT_POST_STOP_WORLD:
- if (do_heap_profiling) {
- dump_heap_data = dump_current_heap_snapshot ();
- if (heap_shot_write_job_should_be_created (dump_heap_data)) {
- ProfilerPerThreadData *data;
- // Update all mappings, so that we have built all the class descriptors.
- flush_all_mappings ();
- // Also write all event buffers, so that allocations are recorded.
- for (data = profiler->per_thread_data; data != NULL; data = data->next) {
- write_thread_data_block (data);
- }
- }
- } else {
- dump_heap_data = FALSE;
- }
- // Release lock...
- UNLOCK_PROFILER ();
- break;
- case MONO_GC_EVENT_MARK_END: {
- if (do_heap_profiling) {
- ProfilerHeapShotWriteJob *job;
- ProfilerPerThreadData *data;
-
- if (heap_shot_write_job_should_be_created (dump_heap_data)) {
- job = profiler_heap_shot_write_job_new (profiler->heap_shot_was_requested, dump_heap_data, profiler->garbage_collection_counter);
- profiler->heap_shot_was_requested = FALSE;
- MONO_PROFILER_GET_CURRENT_COUNTER (job->start_counter);
- MONO_PROFILER_GET_CURRENT_TIME (job->start_time);
- } else {
- job = NULL;
- }
-
- profiler_heap_scan (&(profiler->heap), job);
-
- for (data = profiler->per_thread_data; data != NULL; data = data->next) {
- ProfilerHeapShotObjectBuffer *buffer;
- for (buffer = data->heap_shot_object_buffers; buffer != NULL; buffer = buffer->next) {
- MonoObject **cursor;
- for (cursor = buffer->first_unprocessed_slot; cursor < buffer->next_free_slot; cursor ++) {
- MonoObject *obj = *cursor;
-#if DEBUG_HEAP_PROFILER
- printf ("gc_event: in object buffer %p(%p-%p) cursor at %p has object %p ", buffer, &(buffer->buffer [0]), buffer->end, cursor, obj);
-#endif
- if (mono_object_is_alive (obj)) {
-#if DEBUG_HEAP_PROFILER
- printf ("(object is alive, adding to heap)\n");
-#endif
- profiler_heap_add_object (&(profiler->heap), job, obj);
- } else {
-#if DEBUG_HEAP_PROFILER
- printf ("(object is unreachable, reporting in job)\n");
-#endif
- profiler_heap_report_object_unreachable (job, obj);
- }
- }
- buffer->first_unprocessed_slot = cursor;
- }
- }
-
- if (job != NULL) {
- MONO_PROFILER_GET_CURRENT_COUNTER (job->end_counter);
- MONO_PROFILER_GET_CURRENT_TIME (job->end_time);
-
- profiler_add_heap_shot_write_job (job);
- profiler_free_heap_shot_write_jobs ();
- WRITER_EVENT_RAISE ();
- }
- }
- break;
- }
- default:
- break;
- }
-}
-
-static void
-gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- gboolean do_heap_profiling = profiler->action_flags.unreachable_objects || profiler->action_flags.heap_shot || profiler->action_flags.collection_summary;
- guint32 event_value;
-
- if (ev == MONO_GC_EVENT_START) {
- profiler->garbage_collection_counter ++;
- }
-
- event_value = (profiler->garbage_collection_counter << 8) | generation;
-
- if (ev == MONO_GC_EVENT_POST_STOP_WORLD) {
- process_gc_event (profiler, do_heap_profiling, ev);
- }
-
- /* Check if the gc event should be recorded. */
- if (profiler->action_flags.report_gc_events || do_heap_profiling) {
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- STORE_EVENT_NUMBER_COUNTER (event, profiler, event_value, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, gc_event_code_from_profiler_event (ev), gc_event_kind_from_profiler_event (ev));
- COMMIT_RESERVED_EVENTS (data);
- }
-
- if (ev != MONO_GC_EVENT_POST_STOP_WORLD) {
- process_gc_event (profiler, do_heap_profiling, ev);
- }
-}
-
-static void
-gc_resize (MonoProfiler *profiler, gint64 new_size) {
- ProfilerPerThreadData *data;
- ProfilerEventData *event;
- GET_PROFILER_THREAD_DATA (data);
- GET_NEXT_FREE_EVENT (data, event);
- profiler->garbage_collection_counter ++;
- STORE_EVENT_NUMBER_VALUE (event, profiler, new_size, MONO_PROFILER_EVENT_DATA_TYPE_OTHER, MONO_PROFILER_EVENT_GC_RESIZE, 0, profiler->garbage_collection_counter);
- COMMIT_RESERVED_EVENTS (data);
-}
-
-static void
-runtime_initialized (MonoProfiler *profiler) {
- LOG_WRITER_THREAD ("runtime_initialized: initializing internal calls.\n");
- mono_add_internal_call ("Mono.Profiler.RuntimeControls::EnableProfiler", enable_profiler);
- mono_add_internal_call ("Mono.Profiler.RuntimeControls::DisableProfiler", disable_profiler);
- mono_add_internal_call ("Mono.Profiler.RuntimeControls::TakeHeapSnapshot", request_heap_snapshot);
- LOG_WRITER_THREAD ("runtime_initialized: initialized internal calls.\n");
-}
-
-
-#define MAX_COMMAND_LENGTH (1024)
-static int server_socket;
-static int command_socket;
-
-static void
-write_user_response (const char *response) {
- LOG_USER_THREAD ("write_user_response: writing response:");
- LOG_USER_THREAD (response);
- send (command_socket, response, strlen (response), 0);
-}
-
-static void
-execute_user_command (char *command) {
- char *line_feed;
-
- LOG_USER_THREAD ("execute_user_command: executing command:");
- LOG_USER_THREAD (command);
-
- /* Ignore leading and trailing '\r' */
- line_feed = strchr (command, '\r');
- if (line_feed == command) {
- command ++;
- line_feed = strchr (command, '\r');
- }
- if ((line_feed != NULL) && (* (line_feed + 1) == 0)) {
- *line_feed = 0;
- }
-
- if (strcmp (command, "enable") == 0) {
- LOG_USER_THREAD ("execute_user_command: enabling profiler");
- enable_profiler ();
- write_user_response ("DONE\n");
- } else if (strcmp (command, "disable") == 0) {
- LOG_USER_THREAD ("execute_user_command: disabling profiler");
- disable_profiler ();
- write_user_response ("DONE\n");
- } else if (strcmp (command, "heap-snapshot") == 0) {
- LOG_USER_THREAD ("execute_user_command: taking heap snapshot");
- profiler->heap_shot_was_requested = TRUE;
- WRITER_EVENT_RAISE ();
- write_user_response ("DONE\n");
- } else if (strstr (command, "heap-snapshot-counter") == 0) {
- char *equals;
- LOG_USER_THREAD ("execute_user_command: changing heap counter");
- equals = strstr (command, "=");
- if (equals != NULL) {
- equals ++;
- if (strcmp (equals, "all") == 0) {
- LOG_USER_THREAD ("execute_user_command: heap counter is \"all\"");
- profiler->garbage_collection_counter = -1;
- } else if (strcmp (equals, "none") == 0) {
- LOG_USER_THREAD ("execute_user_command: heap counter is \"none\"");
- profiler->garbage_collection_counter = 0;
- } else {
- profiler->garbage_collection_counter = atoi (equals);
- }
- write_user_response ("DONE\n");
- } else {
- write_user_response ("ERROR\n");
- }
- profiler->heap_shot_was_requested = TRUE;
- } else {
- LOG_USER_THREAD ("execute_user_command: command not recognized");
- write_user_response ("ERROR\n");
- }
-}
-
-static gboolean
-process_user_commands (void) {
- char *command_buffer = malloc (MAX_COMMAND_LENGTH);
- int command_buffer_current_index = 0;
- gboolean loop = TRUE;
- gboolean result = TRUE;
-
- while (loop) {
- int unprocessed_characters;
-
- LOG_USER_THREAD ("process_user_commands: reading from socket...");
- unprocessed_characters = recv (command_socket, command_buffer + command_buffer_current_index, MAX_COMMAND_LENGTH - command_buffer_current_index, 0);
-
- if (unprocessed_characters > 0) {
- char *command_end = NULL;
-
- LOG_USER_THREAD ("process_user_commands: received characters.");
-
- do {
- if (command_end != NULL) {
- *command_end = 0;
- execute_user_command (command_buffer);
- unprocessed_characters -= (((command_end - command_buffer) - command_buffer_current_index) + 1);
-
- if (unprocessed_characters > 0) {
- memmove (command_buffer, command_end + 1, unprocessed_characters);
- }
- command_buffer_current_index = 0;
- }
-
- command_end = memchr (command_buffer, '\n', command_buffer_current_index + unprocessed_characters);
- } while (command_end != NULL);
-
- command_buffer_current_index += unprocessed_characters;
-
- } else if (unprocessed_characters == 0) {
- LOG_USER_THREAD ("process_user_commands: received no character.");
- result = TRUE;
- loop = FALSE;
- } else {
- LOG_USER_THREAD ("process_user_commands: received error.");
- result = FALSE;
- loop = FALSE;
- }
- }
-
- free (command_buffer);
- return result;
-}
-
-static guint32
-user_thread (gpointer nothing) {
- struct sockaddr_in server_address;
-
- server_socket = -1;
- command_socket = -1;
-
- LOG_USER_THREAD ("user_thread: starting up...");
-
- server_socket = socket (AF_INET, SOCK_STREAM, 0);
- if (server_socket < 0) {
- LOG_USER_THREAD ("user_thread: error creating socket.");
- return 0;
- }
- memset (& server_address, 0, sizeof (server_address));
-
- server_address.sin_family = AF_INET;
- server_address.sin_addr.s_addr = INADDR_ANY;
- if ((profiler->command_port < 1023) || (profiler->command_port > 65535)) {
- LOG_USER_THREAD ("user_thread: invalid port number.");
- return 0;
- }
- server_address.sin_port = htons (profiler->command_port);
-
- if (bind (server_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
- LOG_USER_THREAD ("user_thread: error binding socket.");
- close (server_socket);
- return 0;
- }
-
- LOG_USER_THREAD ("user_thread: listening...\n");
- listen (server_socket, 1);
- command_socket = accept (server_socket, NULL, NULL);
- if (command_socket < 0) {
- LOG_USER_THREAD ("user_thread: error accepting socket.");
- close (server_socket);
- return 0;
- }
-
- LOG_USER_THREAD ("user_thread: processing user commands...");
- process_user_commands ();
-
- LOG_USER_THREAD ("user_thread: exiting cleanly.");
- close (server_socket);
- close (command_socket);
- return 0;
-}
-
-
-/* called at the end of the program */
-static void
-profiler_shutdown (MonoProfiler *prof)
-{
- ProfilerPerThreadData* current_thread_data;
- ProfilerPerThreadData* next_thread_data;
-
- LOG_WRITER_THREAD ("profiler_shutdown: zeroing relevant flags");
- mono_profiler_set_events (0);
- /* During shutdown searching for MonoJitInfo is not possible... */
- if (profiler->statistical_call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
- mono_profiler_install_statistical_call_chain (NULL, 0, MONO_PROFILER_CALL_CHAIN_NONE);
- }
- //profiler->flags = 0;
- //profiler->action_flags.unreachable_objects = FALSE;
- //profiler->action_flags.heap_shot = FALSE;
-
- LOG_WRITER_THREAD ("profiler_shutdown: asking stats thread to exit");
- profiler->terminate_writer_thread = TRUE;
- WRITER_EVENT_RAISE ();
- LOG_WRITER_THREAD ("profiler_shutdown: waiting for stats thread to exit");
- WAIT_WRITER_THREAD ();
- LOG_WRITER_THREAD ("profiler_shutdown: stats thread should be dead now");
- WRITER_EVENT_DESTROY ();
-
- LOCK_PROFILER ();
- flush_everything ();
- MONO_PROFILER_GET_CURRENT_TIME (profiler->end_time);
- MONO_PROFILER_GET_CURRENT_COUNTER (profiler->end_counter);
- write_end_block ();
- FLUSH_FILE ();
- CLOSE_FILE();
- mono_profiler_install_code_chunk_new (NULL);
- mono_profiler_install_code_chunk_destroy (NULL);
- mono_profiler_install_code_buffer_new (NULL);
- profiler_code_chunks_cleanup (& (profiler->code_chunks));
- UNLOCK_PROFILER ();
-
- g_free (profiler->file_name);
- if (profiler->file_name_suffix != NULL) {
- g_free (profiler->file_name_suffix);
- }
-
- method_id_mapping_destroy (profiler->methods);
- class_id_mapping_destroy (profiler->classes);
- g_hash_table_destroy (profiler->loaded_assemblies);
- g_hash_table_destroy (profiler->loaded_modules);
- g_hash_table_destroy (profiler->loaded_appdomains);
-
- FREE_PROFILER_THREAD_DATA ();
-
- for (current_thread_data = profiler->per_thread_data; current_thread_data != NULL; current_thread_data = next_thread_data) {
- next_thread_data = current_thread_data->next;
- profiler_per_thread_data_destroy (current_thread_data);
- }
- if (profiler->statistical_data != NULL) {
- profiler_statistical_data_destroy (profiler->statistical_data);
- }
- if (profiler->statistical_data_ready != NULL) {
- profiler_statistical_data_destroy (profiler->statistical_data_ready);
- }
- if (profiler->statistical_data_second_buffer != NULL) {
- profiler_statistical_data_destroy (profiler->statistical_data_second_buffer);
- }
- if (profiler->executable_regions != NULL) {
- profiler_executable_memory_regions_destroy (profiler->executable_regions);
- }
-
- profiler_heap_buffers_free (&(profiler->heap));
-
- profiler_free_write_buffers ();
- profiler_destroy_heap_shot_write_jobs ();
-
- DELETE_PROFILER_MUTEX ();
-
-#if (HAS_OPROFILE)
- if (profiler->action_flags.oprofile) {
- op_close_agent ();
- }
-#endif
-
- g_free (profiler);
- profiler = NULL;
-}
-
-#define FAIL_ARGUMENT_CHECK(message) do {\
- failure_message = (message);\
- goto failure_handling;\
-} while (0)
-#define FAIL_PARSING_VALUED_ARGUMENT FAIL_ARGUMENT_CHECK("cannot parse valued argument %s")
-#define FAIL_PARSING_FLAG_ARGUMENT FAIL_ARGUMENT_CHECK("cannot parse flag argument %s")
-#define CHECK_CONDITION(condition,message) do {\
- gboolean result = (condition);\
- if (result) {\
- FAIL_ARGUMENT_CHECK (message);\
- }\
-} while (0)
-#define FAIL_IF_HAS_MINUS CHECK_CONDITION(has_minus,"minus ('-') modifier not allowed for argument %s")
-#define TRUE_IF_NOT_MINUS ((!has_minus)?TRUE:FALSE)
-
-#define DEFAULT_ARGUMENTS "s"
-static void
-setup_user_options (const char *arguments) {
- gchar **arguments_array, **current_argument;
- detect_fast_timer ();
-
- profiler->file_name = NULL;
- profiler->file_name_suffix = NULL;
- profiler->per_thread_buffer_size = 10000;
- profiler->statistical_buffer_size = 10000;
- profiler->statistical_call_chain_depth = 0;
- profiler->statistical_call_chain_strategy = MONO_PROFILER_CALL_CHAIN_NATIVE;
- profiler->write_buffer_size = 1024;
- profiler->dump_next_heap_snapshots = 0;
- profiler->heap_shot_was_requested = FALSE;
- profiler->flags = MONO_PROFILE_APPDOMAIN_EVENTS|
- MONO_PROFILE_ASSEMBLY_EVENTS|
- MONO_PROFILE_MODULE_EVENTS|
- MONO_PROFILE_CLASS_EVENTS|
- MONO_PROFILE_METHOD_EVENTS|
- MONO_PROFILE_JIT_COMPILATION;
- profiler->profiler_enabled = TRUE;
-
- if (arguments == NULL) {
- arguments = DEFAULT_ARGUMENTS;
- } else if (strstr (arguments, ":")) {
- arguments = strstr (arguments, ":") + 1;
- if (arguments [0] == 0) {
- arguments = DEFAULT_ARGUMENTS;
- }
- }
-
- arguments_array = g_strsplit (arguments, ",", -1);
-
- for (current_argument = arguments_array; ((current_argument != NULL) && (current_argument [0] != 0)); current_argument ++) {
- char *argument = *current_argument;
- char *equals = strstr (argument, "=");
- const char *failure_message = NULL;
- gboolean has_plus;
- gboolean has_minus;
-
- if (*argument == '+') {
- has_plus = TRUE;
- has_minus = FALSE;
- argument ++;
- } else if (*argument == '-') {
- has_plus = FALSE;
- has_minus = TRUE;
- argument ++;
- } else {
- has_plus = FALSE;
- has_minus = FALSE;
- }
-
- if (equals != NULL) {
- int equals_position = equals - argument;
-
- if (! (strncmp (argument, "per-thread-buffer-size", equals_position) && strncmp (argument, "tbs", equals_position))) {
- int value = atoi (equals + 1);
- FAIL_IF_HAS_MINUS;
- if (value > 0) {
- profiler->per_thread_buffer_size = value;
- }
- } else if (! (strncmp (argument, "statistical", equals_position) && strncmp (argument, "stat", equals_position) && strncmp (argument, "s", equals_position))) {
- int value = atoi (equals + 1);
- FAIL_IF_HAS_MINUS;
- if (value > 0) {
- if (value > MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH) {
- value = MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH;
- }
- profiler->statistical_call_chain_depth = value;
- profiler->flags |= MONO_PROFILE_STATISTICAL;
- }
- } else if (! (strncmp (argument, "call-chain-strategy", equals_position) && strncmp (argument, "ccs", equals_position))) {
- char *parameter = equals + 1;
- FAIL_IF_HAS_MINUS;
- if (! strcmp (parameter, "native")) {
- profiler->statistical_call_chain_strategy = MONO_PROFILER_CALL_CHAIN_NATIVE;
- } else if (! strcmp (parameter, "glibc")) {
- profiler->statistical_call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
- } else if (! strcmp (parameter, "managed")) {
- profiler->statistical_call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
- } else {
- failure_message = "invalid call chain strategy in argument %s";
- goto failure_handling;
- }
- } else if (! (strncmp (argument, "statistical-thread-buffer-size", equals_position) && strncmp (argument, "sbs", equals_position))) {
- int value = atoi (equals + 1);
- FAIL_IF_HAS_MINUS;
- if (value > 0) {
- profiler->statistical_buffer_size = value;
- }
- } else if (! (strncmp (argument, "write-buffer-size", equals_position) && strncmp (argument, "wbs", equals_position))) {
- int value = atoi (equals + 1);
- FAIL_IF_HAS_MINUS;
- if (value > 0) {
- profiler->write_buffer_size = value;
- }
- } else if (! (strncmp (argument, "output", equals_position) && strncmp (argument, "out", equals_position) && strncmp (argument, "o", equals_position) && strncmp (argument, "O", equals_position))) {
- FAIL_IF_HAS_MINUS;
- if (strlen (equals + 1) > 0) {
- profiler->file_name = g_strdup (equals + 1);
- }
- } else if (! (strncmp (argument, "output-suffix", equals_position) && strncmp (argument, "suffix", equals_position) && strncmp (argument, "os", equals_position) && strncmp (argument, "OS", equals_position))) {
- FAIL_IF_HAS_MINUS;
- if (strlen (equals + 1) > 0) {
- profiler->file_name_suffix = g_strdup (equals + 1);
- }
- } else if (! (strncmp (argument, "heap-shot", equals_position) && strncmp (argument, "heap", equals_position) && strncmp (argument, "h", equals_position))) {
- char *parameter = equals + 1;
- if (! strcmp (parameter, "all")) {
- profiler->dump_next_heap_snapshots = -1;
- } else {
- profiler->dump_next_heap_snapshots = atoi (parameter);
- }
- FAIL_IF_HAS_MINUS;
- if (! has_plus) {
- profiler->action_flags.save_allocation_caller = TRUE;
- profiler->action_flags.save_allocation_stack = TRUE;
- profiler->action_flags.allocations_carry_id = TRUE_IF_NOT_MINUS;
- }
- profiler->action_flags.heap_shot = TRUE_IF_NOT_MINUS;
- } else if (! (strncmp (argument, "gc-dumps", equals_position) && strncmp (argument, "gc-d", equals_position) && strncmp (argument, "gcd", equals_position))) {
- FAIL_IF_HAS_MINUS;
- if (strlen (equals + 1) > 0) {
- profiler->dump_next_heap_snapshots = atoi (equals + 1);
- }
- } else if (! (strncmp (argument, "command-port", equals_position) && strncmp (argument, "cp", equals_position))) {
- FAIL_IF_HAS_MINUS;
- if (strlen (equals + 1) > 0) {
- profiler->command_port = atoi (equals + 1);
- }
- } else {
- FAIL_PARSING_VALUED_ARGUMENT;
- }
- } else {
- if (! (strcmp (argument, "jit") && strcmp (argument, "j"))) {
- profiler->action_flags.jit_time = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "allocations") && strcmp (argument, "alloc") && strcmp (argument, "a"))) {
- FAIL_IF_HAS_MINUS;
- if (! has_plus) {
- profiler->action_flags.save_allocation_caller = TRUE;
- profiler->action_flags.save_allocation_stack = TRUE;
- }
- if (! has_minus) {
- profiler->flags |= MONO_PROFILE_ALLOCATIONS;
- } else {
- profiler->flags &= ~MONO_PROFILE_ALLOCATIONS;
- }
- } else if (! (strcmp (argument, "monitor") && strcmp (argument, "locks") && strcmp (argument, "lock"))) {
- FAIL_IF_HAS_MINUS;
- profiler->action_flags.track_stack = TRUE;
- profiler->flags |= MONO_PROFILE_MONITOR_EVENTS;
- profiler->flags |= MONO_PROFILE_GC;
- } else if (! (strcmp (argument, "gc") && strcmp (argument, "g"))) {
- FAIL_IF_HAS_MINUS;
- profiler->action_flags.report_gc_events = TRUE;
- profiler->flags |= MONO_PROFILE_GC;
- } else if (! (strcmp (argument, "allocations-summary") && strcmp (argument, "as"))) {
- profiler->action_flags.collection_summary = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "heap-shot") && strcmp (argument, "heap") && strcmp (argument, "h"))) {
- FAIL_IF_HAS_MINUS;
- if (! has_plus) {
- profiler->action_flags.save_allocation_caller = TRUE;
- profiler->action_flags.save_allocation_stack = TRUE;
- profiler->action_flags.allocations_carry_id = TRUE_IF_NOT_MINUS;
- }
- profiler->action_flags.heap_shot = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "unreachable") && strcmp (argument, "free") && strcmp (argument, "f"))) {
- profiler->action_flags.unreachable_objects = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "threads") && strcmp (argument, "t"))) {
- if (! has_minus) {
- profiler->flags |= MONO_PROFILE_THREADS;
- } else {
- profiler->flags &= ~MONO_PROFILE_THREADS;
- }
- } else if (! (strcmp (argument, "enter-leave") && strcmp (argument, "calls") && strcmp (argument, "c"))) {
- profiler->action_flags.track_calls = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "statistical") && strcmp (argument, "stat") && strcmp (argument, "s"))) {
- if (! has_minus) {
- profiler->flags |= MONO_PROFILE_STATISTICAL;
- } else {
- profiler->flags &= ~MONO_PROFILE_STATISTICAL;
- }
- } else if (! (strcmp (argument, "save-allocation-caller") && strcmp (argument, "sac"))) {
- profiler->action_flags.save_allocation_caller = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "save-allocation-stack") && strcmp (argument, "sas"))) {
- profiler->action_flags.save_allocation_stack = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "allocations-carry-id") && strcmp (argument, "aci"))) {
- profiler->action_flags.allocations_carry_id = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "start-enabled") && strcmp (argument, "se"))) {
- profiler->profiler_enabled = TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "start-disabled") && strcmp (argument, "sd"))) {
- profiler->profiler_enabled = ! TRUE_IF_NOT_MINUS;
- } else if (! (strcmp (argument, "force-accurate-timer") && strcmp (argument, "fac"))) {
- use_fast_timer = TRUE_IF_NOT_MINUS;
-#if (HAS_OPROFILE)
- } else if (! (strcmp (argument, "oprofile") && strcmp (argument, "oprof"))) {
- profiler->flags |= MONO_PROFILE_JIT_COMPILATION;
- profiler->action_flags.oprofile = TRUE;
- if (op_open_agent ()) {
- FAIL_ARGUMENT_CHECK ("problem calling op_open_agent");
- }
-#endif
- } else if (strcmp (argument, "logging")) {
- FAIL_PARSING_FLAG_ARGUMENT;
- }
- }
-
-failure_handling:
- if (failure_message != NULL) {
- g_warning (failure_message, argument);
- failure_message = NULL;
- }
- }
-
- g_free (arguments_array);
-
- /* Ensure that the profiler flags needed to support required action flags are active */
- if (profiler->action_flags.jit_time) {
- profiler->flags |= MONO_PROFILE_JIT_COMPILATION;
- }
- if (profiler->action_flags.save_allocation_caller || profiler->action_flags.save_allocation_stack || profiler->action_flags.allocations_carry_id) {
- profiler->flags |= MONO_PROFILE_ALLOCATIONS;
- }
- if (profiler->action_flags.collection_summary || profiler->action_flags.heap_shot || profiler->action_flags.unreachable_objects) {
- profiler->flags |= MONO_PROFILE_ALLOCATIONS;
- profiler->action_flags.report_gc_events = TRUE;
- }
- if (profiler->action_flags.track_calls) {
- profiler->flags |= MONO_PROFILE_ENTER_LEAVE;
- profiler->action_flags.jit_time = TRUE;
- }
- if (profiler->action_flags.save_allocation_caller || profiler->action_flags.save_allocation_stack) {
- profiler->action_flags.track_stack = TRUE;
- profiler->flags |= MONO_PROFILE_ENTER_LEAVE;
- }
- if (profiler->action_flags.track_stack) {
- profiler->flags |= MONO_PROFILE_ENTER_LEAVE;
- }
-
- /* Tracking call stacks is useless if we already emit all enter-exit events... */
- if (profiler->action_flags.track_calls) {
- profiler->action_flags.track_stack = FALSE;
- profiler->action_flags.save_allocation_caller = FALSE;
- profiler->action_flags.save_allocation_stack = FALSE;
- }
-
- /* Without JIT events the stat profiler will not find method IDs... */
- if (profiler->flags | MONO_PROFILE_STATISTICAL) {
- profiler->flags |= MONO_PROFILE_JIT_COMPILATION;
- }
- /* Profiling allocations without knowing which gc we are doing is not nice... */
- if (profiler->flags | MONO_PROFILE_ALLOCATIONS) {
- profiler->flags |= MONO_PROFILE_GC;
- profiler->action_flags.report_gc_events = TRUE;
- }
-
-
- if (profiler->file_name == NULL) {
- char *program_name = g_get_prgname ();
-
- if (program_name != NULL) {
- char *name_buffer = g_strdup (program_name);
- char *name_start = name_buffer;
- char *cursor;
-
- /* Jump over the last '/' */
- cursor = strrchr (name_buffer, '/');
- if (cursor == NULL) {
- cursor = name_buffer;
- } else {
- cursor ++;
- }
- name_start = cursor;
-
- /* Then jump over the last '\\' */
- cursor = strrchr (name_start, '\\');
- if (cursor == NULL) {
- cursor = name_start;
- } else {
- cursor ++;
- }
- name_start = cursor;
-
- /* Finally, find the last '.' */
- cursor = strrchr (name_start, '.');
- if (cursor != NULL) {
- *cursor = 0;
- }
-
- if (profiler->file_name_suffix == NULL) {
- profiler->file_name = g_strdup_printf ("%s.mprof", name_start);
- } else {
- profiler->file_name = g_strdup_printf ("%s-%s.mprof", name_start, profiler->file_name_suffix);
- }
- g_free (name_buffer);
- } else {
- profiler->file_name = g_strdup_printf ("%s.mprof", "profiler-log");
- }
- }
-}
-
-static guint32
-data_writer_thread (gpointer nothing) {
- for (;;) {
- ProfilerStatisticalData *statistical_data;
- gboolean done;
-
- LOG_WRITER_THREAD ("data_writer_thread: going to sleep");
- WRITER_EVENT_WAIT ();
- LOG_WRITER_THREAD ("data_writer_thread: just woke up");
-
- if (profiler->heap_shot_was_requested) {
- MonoDomain * root_domain = mono_get_root_domain ();
-
- if (root_domain != NULL) {
- MonoThread *this_thread;
- LOG_WRITER_THREAD ("data_writer_thread: attaching thread");
- this_thread = mono_thread_attach (root_domain);
- LOG_WRITER_THREAD ("data_writer_thread: starting requested collection");
- mono_gc_collect (mono_gc_max_generation ());
- LOG_WRITER_THREAD ("data_writer_thread: requested collection done");
- LOG_WRITER_THREAD ("data_writer_thread: detaching thread");
- mono_thread_detach (this_thread);
- this_thread = NULL;
- LOG_WRITER_THREAD ("data_writer_thread: collection sequence completed");
- } else {
- LOG_WRITER_THREAD ("data_writer_thread: cannot get root domain, collection sequence skipped");
- }
-
- }
-
- statistical_data = profiler->statistical_data_ready;
- done = (statistical_data == NULL) && (profiler->heap_shot_write_jobs == NULL);
-
- if (!done) {
- LOG_WRITER_THREAD ("data_writer_thread: acquiring lock and writing data");
- LOCK_PROFILER ();
-
- // This makes sure that all method ids are in place
- LOG_WRITER_THREAD ("data_writer_thread: writing mapping...");
- flush_all_mappings ();
- LOG_WRITER_THREAD ("data_writer_thread: wrote mapping");
-
- if (statistical_data != NULL) {
- LOG_WRITER_THREAD ("data_writer_thread: writing statistical data...");
- profiler->statistical_data_ready = NULL;
- write_statistical_data_block (statistical_data);
- statistical_data->next_free_index = 0;
- statistical_data->first_unwritten_index = 0;
- profiler->statistical_data_second_buffer = statistical_data;
- LOG_WRITER_THREAD ("data_writer_thread: wrote statistical data");
- }
-
- profiler_process_heap_shot_write_jobs ();
-
- UNLOCK_PROFILER ();
- LOG_WRITER_THREAD ("data_writer_thread: wrote data and released lock");
- } else {
- LOG_WRITER_THREAD ("data_writer_thread: acquiring lock and flushing buffers");
- LOCK_PROFILER ();
- LOG_WRITER_THREAD ("data_writer_thread: lock acquired, flushing buffers");
- flush_everything ();
- UNLOCK_PROFILER ();
- LOG_WRITER_THREAD ("data_writer_thread: flushed buffers and released lock");
- }
-
- if (profiler->terminate_writer_thread) {
- LOG_WRITER_THREAD ("data_writer_thread: exiting thread");
- CLEANUP_WRITER_THREAD ();
- EXIT_THREAD ();
- }
- }
- return 0;
-}
-
-void
-mono_profiler_startup (const char *desc);
-
-/* the entry point (mono_profiler_load?) */
-void
-mono_profiler_startup (const char *desc)
-{
- profiler = g_new0 (MonoProfiler, 1);
-
- setup_user_options ((desc != NULL) ? desc : DEFAULT_ARGUMENTS);
-
- INITIALIZE_PROFILER_MUTEX ();
- MONO_PROFILER_GET_CURRENT_TIME (profiler->start_time);
- MONO_PROFILER_GET_CURRENT_COUNTER (profiler->start_counter);
- profiler->last_header_counter = 0;
-
- profiler->methods = method_id_mapping_new ();
- profiler->classes = class_id_mapping_new ();
- profiler->loaded_element_next_free_id = 1;
- profiler->loaded_assemblies = g_hash_table_new_full (g_direct_hash, NULL, NULL, loaded_element_destroy);
- profiler->loaded_modules = g_hash_table_new_full (g_direct_hash, NULL, NULL, loaded_element_destroy);
- profiler->loaded_appdomains = g_hash_table_new_full (g_direct_hash, NULL, NULL, loaded_element_destroy);
-
- profiler->statistical_data = profiler_statistical_data_new (profiler);
- profiler->statistical_data_second_buffer = profiler_statistical_data_new (profiler);
-
- profiler->write_buffers = g_malloc (sizeof (ProfilerFileWriteBuffer) + PROFILER_FILE_WRITE_BUFFER_SIZE);
- profiler->write_buffers->next = NULL;
- profiler->current_write_buffer = profiler->write_buffers;
- profiler->current_write_position = 0;
- profiler->full_write_buffers = 0;
- profiler_code_chunks_initialize (& (profiler->code_chunks));
-
- profiler->executable_regions = profiler_executable_memory_regions_new (1, 1);
-
- profiler->executable_files.table = g_hash_table_new (g_str_hash, g_str_equal);
- profiler->executable_files.new_files = NULL;
-
- profiler->heap_shot_write_jobs = NULL;
- if (profiler->action_flags.unreachable_objects || profiler->action_flags.heap_shot || profiler->action_flags.collection_summary) {
- profiler_heap_buffers_setup (&(profiler->heap));
- } else {
- profiler_heap_buffers_clear (&(profiler->heap));
- }
- profiler->garbage_collection_counter = 0;
-
- WRITER_EVENT_INIT ();
- LOG_WRITER_THREAD ("mono_profiler_startup: creating writer thread");
- CREATE_WRITER_THREAD (data_writer_thread);
- LOG_WRITER_THREAD ("mono_profiler_startup: created writer thread");
- if ((profiler->command_port >= 1024) && (profiler->command_port <= 65535)) {
- LOG_USER_THREAD ("mono_profiler_startup: creating user thread");
- CREATE_USER_THREAD (user_thread);
- LOG_USER_THREAD ("mono_profiler_startup: created user thread");
- } else {
- LOG_USER_THREAD ("mono_profiler_startup: skipping user thread creation");
- }
-
- ALLOCATE_PROFILER_THREAD_DATA ();
-
- OPEN_FILE ();
-
- write_intro_block ();
- write_directives_block (TRUE);
-
- mono_profiler_install (profiler, profiler_shutdown);
-
- mono_profiler_install_appdomain (appdomain_start_load, appdomain_end_load,
- appdomain_start_unload, appdomain_end_unload);
- mono_profiler_install_assembly (assembly_start_load, assembly_end_load,
- assembly_start_unload, assembly_end_unload);
- mono_profiler_install_module (module_start_load, module_end_load,
- module_start_unload, module_end_unload);
- mono_profiler_install_class (class_start_load, class_end_load,
- class_start_unload, class_end_unload);
- mono_profiler_install_jit_compile (method_start_jit, method_end_jit);
- mono_profiler_install_enter_leave (method_enter, method_leave);
- mono_profiler_install_method_free (method_free);
- mono_profiler_install_thread (thread_start, thread_end);
- mono_profiler_install_allocation (object_allocated);
- mono_profiler_install_monitor (monitor_event);
- mono_profiler_install_statistical (statistical_hit);
- mono_profiler_install_statistical_call_chain (statistical_call_chain, profiler->statistical_call_chain_depth, profiler->statistical_call_chain_strategy);
- mono_profiler_install_gc (gc_event, gc_resize);
- mono_profiler_install_runtime_initialized (runtime_initialized);
-#if (HAS_OPROFILE)
- mono_profiler_install_jit_end (method_jit_result);
-#endif
- if (profiler->flags | MONO_PROFILE_STATISTICAL) {
- mono_profiler_install_code_chunk_new (profiler_code_chunk_new_callback);
- mono_profiler_install_code_chunk_destroy (profiler_code_chunk_destroy_callback);
- mono_profiler_install_code_buffer_new (profiler_code_buffer_new_callback);
- }
-
- mono_profiler_set_events (profiler->flags);
-}
-
#define LOG_HEADER_ID 0x4D505A01
#define LOG_VERSION_MAJOR 0
#define LOG_VERSION_MINOR 4
-#define LOG_DATA_VERSION 8
+#define LOG_DATA_VERSION 9
/*
* Changes in data versions:
* version 2: added offsets in heap walk
* version 5: added counters sampling
* version 6: added optional backtrace in sampling info
* version 8: added TYPE_RUNTIME and JIT helpers/trampolines
+ * version 9: added MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING
*/
enum {
struct _MonoCodeManager {
int dynamic;
int read_only;
+ int bind_size;
CodeChunk *current;
CodeChunk *full;
CodeChunk *last;
* Creates a new code manager suitable for holding native code that can be
* used for single or small methods that need to be deallocated independently
* of other native code.
+ * BIND_SIZE is the amount of memory reserved for storing thunks. If its 0,
+ * the default size is used.
*
* Returns: the new code manager
*/
MonoCodeManager*
-mono_code_manager_new_dynamic (void)
+mono_code_manager_new_dynamic (int bind_size)
{
MonoCodeManager *cman = mono_code_manager_new ();
cman->dynamic = 1;
+ cman->bind_size = bind_size;
return cman;
}
#define BIND_ROOM 8
#endif
#if defined(TARGET_ARM64)
-#define BIND_ROOM 8
+#define BIND_ROOM 4
#endif
static CodeChunk*
-new_codechunk (CodeChunk *last, int dynamic, int size)
+new_codechunk (CodeChunk *last, int dynamic, int size, int bind_size)
{
int minsize, flags = CODE_FLAG_MMAP;
int chunk_size, bsize = 0;
}
}
#ifdef BIND_ROOM
- bsize = chunk_size / BIND_ROOM;
+ if (bind_size) {
+ bsize = bind_size;
+ } else {
+ if (dynamic)
+ /* Reserve more space since there are no other chunks we might use if this one gets full */
+ bsize = (chunk_size * 2) / BIND_ROOM;
+ else
+ bsize = chunk_size / BIND_ROOM;
+ }
if (bsize < MIN_BSIZE)
bsize = MIN_BSIZE;
bsize += MIN_ALIGN -1;
bsize &= ~ (MIN_ALIGN - 1);
if (chunk_size - size < bsize) {
chunk_size = size + bsize;
- chunk_size += pagesize - 1;
- chunk_size &= ~ (pagesize - 1);
+ if (!dynamic) {
+ chunk_size += pagesize - 1;
+ chunk_size &= ~ (pagesize - 1);
+ }
}
#endif
}
if (!cman->current) {
- cman->current = new_codechunk (cman->last, cman->dynamic, size);
+ cman->current = new_codechunk (cman->last, cman->dynamic, size, cman->bind_size);
if (!cman->current)
return NULL;
cman->last = cman->current;
cman->full = chunk;
break;
}
- chunk = new_codechunk (cman->last, cman->dynamic, size);
+ chunk = new_codechunk (cman->last, cman->dynamic, size, cman->bind_size);
if (!chunk)
return NULL;
chunk->next = cman->current;
typedef struct _MonoCodeManager MonoCodeManager;
MONO_API MonoCodeManager* mono_code_manager_new (void);
-MONO_API MonoCodeManager* mono_code_manager_new_dynamic (void);
+MONO_API MonoCodeManager* mono_code_manager_new_dynamic (int bind_size);
MONO_API void mono_code_manager_destroy (MonoCodeManager *cman);
MONO_API void mono_code_manager_invalidate (MonoCodeManager *cman);
MONO_API void mono_code_manager_set_read_only (MonoCodeManager *cman);
g_free (wname);
return result;
#else
- return (MonoFileMap *)fopen (name, "rb");
+ int fd = open (name, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+ return (MonoFileMap *)(size_t)fd;
#endif
}
mono_file_map_size (MonoFileMap *fmap)
{
struct stat stat_buf;
- if (fstat (fileno ((FILE*)fmap), &stat_buf) < 0)
+ if (fstat (mono_file_map_fd (fmap), &stat_buf) < 0)
return 0;
return stat_buf.st_size;
}
int
mono_file_map_fd (MonoFileMap *fmap)
{
+#ifdef WIN32
return fileno ((FILE*)fmap);
+#else
+ return (int)(size_t)fmap;
+#endif
}
int
mono_file_map_close (MonoFileMap *fmap)
{
+#ifdef WIN32
return fclose ((FILE*)fmap);
+#else
+ close (mono_file_map_fd (fmap));
+#endif
}
#if !defined (HOST_WIN32)
return NULL;
}
-/**
- * mono_process_get_name:
- * @pid: pid of the process
- * @buf: byte buffer where to store the name of the prcoess
- * @len: size of the buffer @buf
- *
- * Return the name of the process identified by @pid, storing it
- * inside @buf for a maximum of len bytes (including the terminating 0).
- */
-char*
-mono_process_get_name (gpointer pid, char *buf, int len)
-{
#if USE_SYSCTL
- int res;
+
#ifdef KERN_PROC2
- int mib [6];
- size_t data_len = sizeof (struct kinfo_proc2);
- struct kinfo_proc2 processi;
+#define KINFO_PROC struct kinfo_proc2
#else
- int mib [4];
- size_t data_len = sizeof (struct kinfo_proc);
- struct kinfo_proc processi;
-#endif /* KERN_PROC2 */
+#define KINFO_PROC struct kinfo_proc
+#endif
- memset (buf, 0, len);
+static gboolean
+sysctl_kinfo_proc (gpointer pid, KINFO_PROC* processi)
+{
+ int res;
+ size_t data_len = sizeof (KINFO_PROC);
#ifdef KERN_PROC2
+ int mib [6];
mib [0] = CTL_KERN;
mib [1] = KERN_PROC2;
mib [2] = KERN_PROC_PID;
mib [3] = GPOINTER_TO_UINT (pid);
- mib [4] = sizeof(struct kinfo_proc2);
+ mib [4] = sizeof(KINFO_PROC);
mib [5] = 400; /* XXX */
- res = sysctl (mib, 6, &processi, &data_len, NULL, 0);
-
- if (res < 0 || data_len != sizeof (struct kinfo_proc2)) {
- return buf;
- }
+ res = sysctl (mib, 6, processi, &data_len, NULL, 0);
#else
+ int mib [4];
mib [0] = CTL_KERN;
mib [1] = KERN_PROC;
mib [2] = KERN_PROC_PID;
mib [3] = GPOINTER_TO_UINT (pid);
-
- res = sysctl (mib, 4, &processi, &data_len, NULL, 0);
- if (res < 0 || data_len != sizeof (struct kinfo_proc)) {
- return buf;
- }
+
+ res = sysctl (mib, 4, processi, &data_len, NULL, 0);
#endif /* KERN_PROC2 */
- strncpy (buf, processi.kinfo_name_member, len - 1);
+
+ if (res < 0 || data_len != sizeof (KINFO_PROC))
+ return FALSE;
+
+ return TRUE;
+}
+#endif /* USE_SYSCTL */
+
+/**
+ * mono_process_get_name:
+ * @pid: pid of the process
+ * @buf: byte buffer where to store the name of the prcoess
+ * @len: size of the buffer @buf
+ *
+ * Return the name of the process identified by @pid, storing it
+ * inside @buf for a maximum of len bytes (including the terminating 0).
+ */
+char*
+mono_process_get_name (gpointer pid, char *buf, int len)
+{
+#if USE_SYSCTL
+ KINFO_PROC processi;
+
+ memset (buf, 0, len);
+
+ if (sysctl_kinfo_proc (pid, &processi))
+ strncpy (buf, processi.kinfo_name_member, len - 1);
+
return buf;
#else
char fname [128];
#endif
}
+void
+mono_process_get_times (gpointer pid, gint64 *start_time, gint64 *user_time, gint64 *kernel_time)
+{
+ if (user_time)
+ *user_time = mono_process_get_data (pid, MONO_PROCESS_USER_TIME);
+
+ if (kernel_time)
+ *kernel_time = mono_process_get_data (pid, MONO_PROCESS_SYSTEM_TIME);
+
+ if (start_time) {
+ *start_time = 0;
+
+#if USE_SYSCTL
+ {
+ KINFO_PROC processi;
+
+ if (sysctl_kinfo_proc (pid, &processi))
+ *start_time = mono_100ns_datetime_from_timeval (processi.kp_proc.p_starttime);
+ }
+#endif
+
+ if (*start_time == 0) {
+ static guint64 boot_time = 0;
+ if (!boot_time)
+ boot_time = mono_100ns_datetime () - ((guint64)mono_msec_ticks ()) * 10000;
+
+ *start_time = boot_time + mono_process_get_data (pid, MONO_PROCESS_ELAPSED);
+ }
+ }
+}
+
/*
* /proc/pid/stat format:
* pid (cmdname) S
* [0] ppid pgid sid tty_nr tty_pgrp flags min_flt cmin_flt maj_flt cmaj_flt
- * [10] utime stime cutime cstime prio nice threads 0 start_time vsize rss
+ * [10] utime stime cutime cstime prio nice threads 0 start_time vsize
* [20] rss rsslim start_code end_code start_stack esp eip pending blocked sigign
* [30] sigcatch wchan 0 0 exit_signal cpu rt_prio policy
*/
case MONO_PROCESS_FAULTS:
return get_process_stat_item (rpid, 6, TRUE, error);
case MONO_PROCESS_ELAPSED:
- return get_process_stat_item (rpid, 18, FALSE, error) / get_user_hz ();
+ return get_process_stat_time (rpid, 18, FALSE, error);
case MONO_PROCESS_PPID:
return get_process_stat_time (rpid, 0, FALSE, error);
case MONO_PROCESS_PAGED_BYTES:
if (count > 0)
return count + 1;
#endif
-#ifdef _SC_NPROCESSORS_ONLN
- count = sysconf (_SC_NPROCESSORS_ONLN);
+#ifdef _SC_NPROCESSORS_CONF
+ count = sysconf (_SC_NPROCESSORS_CONF);
if (count > 0)
return count;
#endif
gpointer* mono_process_list (int *size);
+void mono_process_get_times (gpointer pid, gint64 *start_time, gint64 *user_time, gint64 *kernel_time);
+
char* mono_process_get_name (gpointer pid, char *buf, int len);
gint64 mono_process_get_data (gpointer pid, MonoProcessData data);
* Copyright (C) 2008 Novell, Inc.
*/
-#include <utils/mono-time.h>
+#include <config.h>
#include <stdlib.h>
#include <stdio.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <utils/mono-time.h>
+
+
#define MTICKS_PER_SEC 10000000
#ifdef HOST_WIN32
#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
{
struct timeval tv;
if (gettimeofday (&tv, NULL) == 0)
- return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;
+ return mono_100ns_datetime_from_timeval (tv);
return 0;
}
+gint64
+mono_100ns_datetime_from_timeval (struct timeval tv)
+{
+ return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;
+}
+
#endif
#include <mono/utils/mono-compiler.h>
#include <glib.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
/* Returns the number of milliseconds from boot time: this should be monotonic */
guint32 mono_msec_ticks (void);
/* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
gint64 mono_100ns_ticks (void);
-/* Returns the number of 100ns ticks since 1/1/1, UTC timezone */
+/* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */
gint64 mono_100ns_datetime (void);
+#ifndef HOST_WIN32
+gint64 mono_100ns_datetime_from_timeval (struct timeval tv);
+#endif
+
/* Stopwatch class for internal runtime use */
typedef struct {
gint64 start, stop;
+++ /dev/null
-Random collection of notes
-
- * What is the point of having the InlineVar argument to
- opcodes be a signed integer instead of unsigned?
-
-
-Storage
-
- The CIL metadata is a very compressed file format, even the
- sizes of blobs and strings are recorded in a compressed form.
- Still, all strings are encoded using 16-bit chars, instead of the
- more efficient UTF-8.
-
build_profiles =
if INSTALL_4_5
-build_profiles += net_4_0 net_4_5 xbuild_12 xbuild_14
+build_profiles += binary_reference_assemblies net_4_5 xbuild_12 xbuild_14
al_profile = net_4_5
endif
# Compile all assemblies with the verifier turned on. Code must be valid but not verifiable.
# TODO it would be nice to split assemblies without unsafe code to use the verifier with verifiable mode.
-# Skip net 4.0 assemblies because they contain metadata only
+# Skip binary_reference_assemblies because they contain metadata only
mcs-compileall: mono-wrapper etc/mono/config
save_MONO_PATH=$$MONO_PATH; mcs_topdir=`cd $(mcs_topdir) && $(cur_dir_cmd)`; ok=:; \
for profile in $(test_profiles); do \
- if [ "net_4_0" = "$$profile" ]; then \
+ if [ "binary_reference_assemblies" = "$$profile" ]; then \
continue; \
fi; \
if [ "xbuild_12" = "$$profile" ]; then \
/*
* Bare bones profiler. Compile with:
- * gcc -shared -o mono-profiler-sample.so sample.c `pkg-config --cflags --libs mono`
- * Install the binary where the dynamic loader can find it.
+ *
+ * linux : gcc -shared -o mono-profiler-sample.so sample.c `pkg-config --cflags --libs mono`
+ * mac : gcc sample.c -o mono-profiler-sample.dylib -Dmono_free=free -lz `pkg-config --cflags mono-2` -undefined suppress -flat_namespace
+ *
+ * Install the binary where the dynamic loader can find it. eg /usr/lib etc
* Then run mono with:
* mono --profile=sample your_application.exe
+ *
+ * Note if you name a profiler with more than 8 characters (eg sample6789) appears to not work
*/
struct _MonoProfiler {
# set LD_LIBRARY_PATH to ensure that libmono is found
export LD_LIBRARY_PATH=$libdir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
# and set MONO_PATH to ensure that mscorlib.dll can be found
-export MONO_PATH=$prefix/lib/mono/2.0
+export MONO_PATH=$prefix/lib/mono/4.5
for i in "${monolist[@]}"; do
($bindir/monodis --assembly $i | awk '
# set LD_LIBRARY_PATH to ensure that libmono is found
export LD_LIBRARY_PATH=$libdir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
# and set MONO_PATH to ensure that mscorlib.dll can be found
-export MONO_PATH=$prefix/lib/mono/2.0
+export MONO_PATH=$prefix/lib/mono/4.5
REQUIRES=$(
for i in "${monolist[@]}"; do
result->gchandle = gchandle;
result->compress = compress;
result->buffer = g_new (guchar, BUFFER_SIZE);
+ result->stream->next_out = result->buffer;
+ result->stream->avail_out = BUFFER_SIZE;
return result;
}
if (!stream->compress)
return 0;
- if (!is_final) {
+ if (!is_final && stream->stream->avail_in != 0) {
status = deflate (stream->stream, Z_PARTIAL_FLUSH);
if (status != Z_OK && status != Z_STREAM_END)
return status;