From: Zoltan Varga Date: Mon, 13 Apr 2015 18:48:35 +0000 (-0400) Subject: Merge pull request #1708 from alexanderkyte/always_use_imt X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=2ffce7f1bf6b6303f6a42d357570d849c3d50476;hp=4d31a8b43fe2e6e09c2c19de403660db86d7dbb8;p=mono.git Merge pull request #1708 from alexanderkyte/always_use_imt [runtime] Remove checks for mono_use_imt because always true. --- diff --git a/.gitignore b/.gitignore index 60701266888..e5b638b53e8 100644 --- a/.gitignore +++ b/.gitignore @@ -122,8 +122,6 @@ docs/perlmod* compile mono.h mono-*.tar.* -mono.spec -mono-core.spec tmpinst-dir.stamp msvc/scripts/inputs/ diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 6c19bda941e..00000000000 --- a/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Miguel de Icaza (miguel@ximian.com) -Paolo Molaro (lupus@ximian.com) -Dietmar Maurer (dietmar@ximian.com) diff --git a/Makefile.am b/Makefile.am index cddaff16211..68269d7e917 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,11 +36,9 @@ EXTRA_DIST= \ 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 @@ -52,7 +50,7 @@ dist-hook: 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: diff --git a/README.md b/README.md index 36a9c1ef398..e7ed2c4f704 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ create cross platform applications. It is an open source 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) @@ -21,9 +23,9 @@ Officially supported architectures: 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/ @@ -35,10 +37,8 @@ Community supported architectures: [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 ============================ @@ -145,13 +145,6 @@ runtime as an embedded library. * `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 ==================== diff --git a/README.vsnet b/README.vsnet deleted file mode 100644 index f3a07a1d8c8..00000000000 --- a/README.vsnet +++ /dev/null @@ -1,120 +0,0 @@ -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 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 diff --git a/build-mingw32.sh b/build-mingw32.sh deleted file mode 100755 index 4c8ed8c1dc4..00000000000 --- a/build-mingw32.sh +++ /dev/null @@ -1,227 +0,0 @@ -#!/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 < /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 diff --git a/configure.ac b/configure.ac index f6680e3cb09..7ef32a6deed 100644 --- a/configure.ac +++ b/configure.ac @@ -96,20 +96,16 @@ platform_android=no 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 @@ -360,6 +356,14 @@ if test x$need_link_unlink = xyes; then 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) @@ -432,7 +436,7 @@ AC_PROG_LD_GNU 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 #include @@ -631,17 +635,6 @@ fi 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 @@ -3061,6 +3054,19 @@ if test "x$host" != "x$target"; then 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; @@ -3837,7 +3843,6 @@ AC_CONFIG_COMMANDS([nolock-libtool], [sed -e 's/lock_old_archive_extraction=yes/ AC_OUTPUT([ Makefile -mono-core.spec mono-uninstalled.pc scripts/mono-find-provides scripts/mono-find-requires @@ -4018,22 +4023,6 @@ fi 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} diff --git a/docs/Makefile.am b/docs/Makefile.am index 811955257bb..9c514420403 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -14,7 +14,6 @@ ASSEMBLED_DOCS = \ EXTRA_DIST = \ abc-removal.txt \ api-style.css \ - assembly-bundle \ check-exports \ check-coverage \ convert.cs \ @@ -23,7 +22,6 @@ EXTRA_DIST = \ docs.make \ documented \ embedded-api \ - exceptions \ exdoc \ file-share-modes \ gc-issues \ @@ -35,33 +33,25 @@ EXTRA_DIST = \ 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: diff --git a/docs/assembly-bundle b/docs/assembly-bundle deleted file mode 100644 index 3e64e147cb1..00000000000 --- a/docs/assembly-bundle +++ /dev/null @@ -1,57 +0,0 @@ - - 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. - - diff --git a/docs/exceptions b/docs/exceptions index d5ecaeead43..bd22de9f25f 100644 --- a/docs/exceptions +++ b/docs/exceptions @@ -71,40 +71,3 @@ unwinding code. 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 diff --git a/docs/local-regalloc.txt b/docs/local-regalloc.txt deleted file mode 100644 index a6e523557fe..00000000000 --- a/docs/local-regalloc.txt +++ /dev/null @@ -1,208 +0,0 @@ - -* 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 diff --git a/docs/mono_handle_d b/docs/mono_handle_d deleted file mode 100644 index a8f97b141c3..00000000000 --- a/docs/mono_handle_d +++ /dev/null @@ -1,98 +0,0 @@ -=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) 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. - -=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. A L 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 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 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 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 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 diff --git a/docs/new-regalloc b/docs/new-regalloc deleted file mode 100644 index b687c2b50c6..00000000000 --- a/docs/new-regalloc +++ /dev/null @@ -1,68 +0,0 @@ -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. - diff --git a/docs/opcode-decomp.txt b/docs/opcode-decomp.txt deleted file mode 100644 index 48968d17ab9..00000000000 --- a/docs/opcode-decomp.txt +++ /dev/null @@ -1,113 +0,0 @@ - -* 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...) - diff --git a/docs/reactive-extension-bundle.txt b/docs/reactive-extension-bundle.txt deleted file mode 100644 index 175818a63be..00000000000 --- a/docs/reactive-extension-bundle.txt +++ /dev/null @@ -1,49 +0,0 @@ -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). - diff --git a/docs/release-notes-1.0.html b/docs/release-notes-1.0.html deleted file mode 100644 index 9c305433c51..00000000000 --- a/docs/release-notes-1.0.html +++ /dev/null @@ -1,16 +0,0 @@ -

Mono 1.0 Release Notes

- -

What does Mono Include

- -

Missing functionality

- -

COM support. - -

EnterpriseServices are non-existant. - -

Windows.Forms is only available as a preview, it is not - completed nor stable. - -

Assembly: System.Drawing

- -

System.Drawing.Printing is not supported. \ No newline at end of file diff --git a/docs/stack-alignment b/docs/stack-alignment deleted file mode 100644 index da995fb288f..00000000000 --- a/docs/stack-alignment +++ /dev/null @@ -1,33 +0,0 @@ -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 | ------------------------------------------------------------ - | | | | | | | | | ------------------------------------------------------------ diff --git a/docs/tree-mover.txt b/docs/tree-mover.txt deleted file mode 100644 index 3ee836a5b2f..00000000000 --- a/docs/tree-mover.txt +++ /dev/null @@ -1,261 +0,0 @@ - -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). diff --git a/external/ikvm b/external/ikvm index d589df6e8a2..061a13cc772 160000 --- a/external/ikvm +++ b/external/ikvm @@ -1 +1 @@ -Subproject commit d589df6e8a206e28b84304a75917006a0e076c29 +Subproject commit 061a13cc772ef15f4d5528eb84fea4d51d4bda1d diff --git a/external/referencesource b/external/referencesource index ada5da77050..8f6de34a64f 160000 --- a/external/referencesource +++ b/external/referencesource @@ -1 +1 @@ -Subproject commit ada5da770505b718b60e4e40b837ffcbd758e17e +Subproject commit 8f6de34a64fb52c25c07bacf0ac5ee824c5153ed diff --git a/man/mcs.1 b/man/mcs.1 index 14221a83c10..a193f9f0850 100644 --- a/man/mcs.1 +++ b/man/mcs.1 @@ -249,29 +249,6 @@ This will instruct the compiler to reference the System.* libraries 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 diff --git a/man/mono.1 b/man/mono.1 index 17ec6e29446..fc49f3b9065 100644 --- a/man/mono.1 +++ b/man/mono.1 @@ -1129,9 +1129,16 @@ to 100 percent. A value of 0 turns evacuation off. .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 @@ -1462,6 +1469,12 @@ include "clearlooks", "nice" and "win32". .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 diff --git a/mcs/Makefile b/mcs/Makefile index cbcfdcc3e0b..b94a7c82d6e 100644 --- a/mcs/Makefile +++ b/mcs/Makefile @@ -12,7 +12,7 @@ monotouch_runtime_SUBDIRS := build class 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 @@ -30,7 +30,7 @@ dir-check: # 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--% @@ -51,7 +51,7 @@ profiles-do--run-test: _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--% diff --git a/mcs/build/Makefile b/mcs/build/Makefile index 8ca1e7c7fa2..e6d2d0a68af 100644 --- a/mcs/build/Makefile +++ b/mcs/build/Makefile @@ -18,7 +18,7 @@ PLATFORMS = darwin linux win32 PROFILES = \ basic \ build \ - net_4_0 \ + binary_reference_assemblies \ net_4_5 \ xbuild_12 \ xbuild_14 diff --git a/mcs/build/profiles/binary_reference_assemblies.make b/mcs/build/profiles/binary_reference_assemblies.make new file mode 100644 index 00000000000..d50e674b986 --- /dev/null +++ b/mcs/build/profiles/binary_reference_assemblies.make @@ -0,0 +1,7 @@ +# -*- makefile -*- + +profile-check: + @: + +NO_BUILD = yes +NO_TEST = yes diff --git a/mcs/build/profiles/net_4_0.make b/mcs/build/profiles/net_4_0.make deleted file mode 100644 index 83e22c4dcb0..00000000000 --- a/mcs/build/profiles/net_4_0.make +++ /dev/null @@ -1,12 +0,0 @@ -# -*- 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 diff --git a/mcs/class/Makefile b/mcs/class/Makefile index bddf0290938..5e3a041c1e2 100644 --- a/mcs/class/Makefile +++ b/mcs/class/Makefile @@ -223,7 +223,7 @@ monotouch_runtime_SUBDIRS := $(monotouch_runtime_dirs) 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) diff --git a/mcs/class/Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs b/mcs/class/Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs index ca6c2b16c8a..78cda036a91 100644 --- a/mcs/class/Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs +++ b/mcs/class/Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs @@ -154,7 +154,7 @@ namespace Mono.Security.Cryptography { 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) @@ -167,7 +167,7 @@ namespace Mono.Security.Cryptography { 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); } diff --git a/mcs/class/SMDiagnostics/Makefile b/mcs/class/SMDiagnostics/Makefile index e0956289610..685d7f5ff1a 100644 --- a/mcs/class/SMDiagnostics/Makefile +++ b/mcs/class/SMDiagnostics/Makefile @@ -15,12 +15,4 @@ TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) 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 diff --git a/mcs/class/System.Data/.gitignore b/mcs/class/System.Data/.gitignore index 26520536f94..c1bb3ed4186 100644 --- a/mcs/class/System.Data/.gitignore +++ b/mcs/class/System.Data/.gitignore @@ -1 +1,7 @@ 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 diff --git a/mcs/class/System.Data/mobile_referencesource.sources b/mcs/class/System.Data/mobile_referencesource.sources index cf6c782316c..4e86efd946f 100644 --- a/mcs/class/System.Data/mobile_referencesource.sources +++ b/mcs/class/System.Data/mobile_referencesource.sources @@ -63,7 +63,6 @@ ../../../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 diff --git a/mcs/class/System.ServiceModel.Internals/Makefile b/mcs/class/System.ServiceModel.Internals/Makefile index 80683a02fb0..a246259b5d5 100644 --- a/mcs/class/System.ServiceModel.Internals/Makefile +++ b/mcs/class/System.ServiceModel.Internals/Makefile @@ -11,14 +11,4 @@ LIB_MCS_FLAGS = /unsafe 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 diff --git a/mcs/class/System/ReferenceSources/MonoSocketRuntimeWorkItem.cs b/mcs/class/System/ReferenceSources/MonoSocketRuntimeWorkItem.cs index 3c9643511f5..c935280838c 100644 --- a/mcs/class/System/ReferenceSources/MonoSocketRuntimeWorkItem.cs +++ b/mcs/class/System/ReferenceSources/MonoSocketRuntimeWorkItem.cs @@ -6,7 +6,7 @@ namespace System.Net.Sockets { internal sealed class MonoSocketRuntimeWorkItem : IThreadPoolWorkItem { - Socket.SocketAsyncResult socket_async_result; + SocketAsyncResult socket_async_result; [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern void ExecuteWorkItem(); diff --git a/mcs/class/System/ReferenceSources/Socket.cs b/mcs/class/System/ReferenceSources/Socket.cs index d6db248b751..8c1d12b8aaa 100644 --- a/mcs/class/System/ReferenceSources/Socket.cs +++ b/mcs/class/System/ReferenceSources/Socket.cs @@ -37,10 +37,10 @@ namespace System.Net.Sockets // 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) @@ -86,7 +86,7 @@ namespace System.Net.Sockets 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 ()); @@ -94,7 +94,7 @@ namespace System.Net.Sockets int error; - SetSocketOption_internal (socket, optionLevel, optionName, null, + SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error); if (!silent && error != 0) diff --git a/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs b/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs index 9c9d8d75128..00f14114077 100644 --- a/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs +++ b/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs @@ -32,24 +32,6 @@ namespace System.Net.Sockets { { } - 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; diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs b/mcs/class/System/System.Net.Sockets/Socket.cs index f3a1102f464..998246c8d72 100644 --- a/mcs/class/System/System.Net.Sockets/Socket.cs +++ b/mcs/class/System/System.Net.Sockets/Socket.cs @@ -6,6 +6,7 @@ // 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 @@ -50,215 +51,318 @@ namespace System.Net.Sockets { 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 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 readQ = new Queue (2); + internal Queue writeQ = new Queue (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 (); - 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"); } } @@ -266,186 +370,124 @@ namespace System.Net.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); @@ -454,222 +496,472 @@ namespace System.Net.Sockets } } - 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 (); + 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 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 (); @@ -683,1538 +975,2110 @@ namespace System.Net.Sockets 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> 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> 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> 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 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> 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> 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> 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> 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> 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> 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> 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> 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> 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 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> 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> 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 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); } } diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncCallback.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncCallback.cs new file mode 100644 index 00000000000..0ea4479cde7 --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncCallback.cs @@ -0,0 +1,32 @@ +// System.Net.Sockets.SocketAsyncCallback.cs +// +// Authors: +// Ludovic Henry +// +// 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); +} diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs index b7b38c150c1..8a3f703f295 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs @@ -40,7 +40,7 @@ namespace System.Net.Sockets { bool disposed; int in_progress; - internal Socket.Worker Worker; + internal SocketAsyncWorker Worker; EndPoint remote_ep; public Exception ConnectByNameError { get; internal set; } @@ -101,7 +101,7 @@ namespace System.Net.Sockets public SocketAsyncEventArgs () { - Worker = new Socket.Worker (this); + Worker = new SocketAsyncWorker (this); AcceptSocket = null; Buffer = null; BufferList = null; @@ -208,33 +208,42 @@ namespace System.Net.Sockets 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) diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs new file mode 100644 index 00000000000..5f361f47a80 --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs @@ -0,0 +1,305 @@ +// System.Net.Sockets.SocketAsyncResult.cs +// +// Authors: +// Ludovic Henry +// +// 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> 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 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 (); + } + } +} diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncWorker.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncWorker.cs new file mode 100644 index 00000000000..a4e3a752cb2 --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncWorker.cs @@ -0,0 +1,381 @@ +// System.Net.Sockets.SocketAsyncWorker.cs +// +// Authors: +// Ludovic Henry +// +// 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); + } + } +} diff --git a/mcs/class/System/System.Net.Sockets/SocketOperation.cs b/mcs/class/System/System.Net.Sockets/SocketOperation.cs new file mode 100644 index 00000000000..22ffd6e71ee --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/SocketOperation.cs @@ -0,0 +1,48 @@ +// System.Net.Sockets.SocketOperation.cs +// +// Authors: +// Ludovic Henry +// +// 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 + } +} diff --git a/mcs/class/System/System.Net.Sockets/Socket_2_1.cs b/mcs/class/System/System.Net.Sockets/Socket_2_1.cs deleted file mode 100644 index 17e9d2aa248..00000000000 --- a/mcs/class/System/System.Net.Sockets/Socket_2_1.cs +++ /dev/null @@ -1,2005 +0,0 @@ -// System.Net.Sockets.Socket.cs -// -// Authors: -// Phillip Pearson (pp@myelin.co.nz) -// Dick Porter -// 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> 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> 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> 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> 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 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> 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> 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> 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 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); - } -} - diff --git a/mcs/class/System/System.Net/Dns.cs b/mcs/class/System/System.Net/Dns.cs index d5ff6effa2b..9045052ccf7 100644 --- a/mcs/class/System/System.Net/Dns.cs +++ b/mcs/class/System/System.Net/Dns.cs @@ -56,8 +56,6 @@ namespace System.Net { static Dns () { - System.Net.Sockets.Socket.CheckProtocolSupport(); - #if !MOBILE if (Environment.GetEnvironmentVariable ("MONO_DNS") != null) { resolver = new SimpleResolver (); diff --git a/mcs/class/System/System.Net/ServicePoint.cs b/mcs/class/System/System.Net/ServicePoint.cs index 2a2c1cb048f..bb47c65c48f 100644 --- a/mcs/class/System/System.Net/ServicePoint.cs +++ b/mcs/class/System/System.Net/ServicePoint.cs @@ -401,15 +401,21 @@ namespace System.Net } 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; } diff --git a/mcs/class/System/System.Net/WebConnectionGroup.cs b/mcs/class/System/System.Net/WebConnectionGroup.cs index 5e142154f91..3936ee42898 100644 --- a/mcs/class/System/System.Net/WebConnectionGroup.cs +++ b/mcs/class/System/System.Net/WebConnectionGroup.cs @@ -66,6 +66,8 @@ namespace System.Net public void Close () { + List 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) { @@ -76,7 +78,17 @@ namespace System.Net var node = iter; iter = iter.Next; + // Closing connections inside the lock leads to a deadlock. + if (connectionsToClose == null) + connectionsToClose = new List(); + + connectionsToClose.Add (cnc); connections.Remove (node); + } + } + + if (connectionsToClose != null) { + foreach (var cnc in connectionsToClose) { cnc.Close (false); OnConnectionClosed (); } diff --git a/mcs/class/System/System.dll.sources b/mcs/class/System/System.dll.sources index b6114e4e51a..27a566c1b17 100644 --- a/mcs/class/System/System.dll.sources +++ b/mcs/class/System/System.dll.sources @@ -533,14 +533,17 @@ System.Net.Sockets/SafeSocketHandle.cs 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 diff --git a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs index 436e0e1252c..de12a43d3cf 100644 --- a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs @@ -52,6 +52,15 @@ namespace MonoTests.System.Diagnostics } } + [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 () { diff --git a/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs b/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs index 3a0c7d89e58..f3cefe8c151 100644 --- a/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs +++ b/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs @@ -374,6 +374,29 @@ namespace MonoTests.System.IO.Compression 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 (); + } } } diff --git a/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs b/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs index 697830b3fd8..cfe2bb092e2 100755 --- a/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs @@ -3156,7 +3156,7 @@ namespace MonoTests.System.Net.Sockets 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) { @@ -3178,7 +3178,7 @@ namespace MonoTests.System.Net.Sockets 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"); @@ -3322,7 +3322,7 @@ namespace MonoTests.System.Net.Sockets 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"); diff --git a/mcs/class/System/mobile_System.dll.sources b/mcs/class/System/mobile_System.dll.sources index 6f061db7e6e..061b9830702 100644 --- a/mcs/class/System/mobile_System.dll.sources +++ b/mcs/class/System/mobile_System.dll.sources @@ -129,18 +129,21 @@ System.Net.Sockets/SafeSocketHandle.cs 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 diff --git a/mcs/class/corlib/Makefile b/mcs/class/corlib/Makefile index 05283f88bcf..42ae018b29b 100644 --- a/mcs/class/corlib/Makefile +++ b/mcs/class/corlib/Makefile @@ -36,12 +36,12 @@ RESOURCE_FILES = \ 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) diff --git a/mcs/class/corlib/ReferenceSources/Buffer.cs b/mcs/class/corlib/ReferenceSources/Buffer.cs new file mode 100644 index 00000000000..94b3a955269 --- /dev/null +++ b/mcs/class/corlib/ReferenceSources/Buffer.cs @@ -0,0 +1,176 @@ +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 diff --git a/mcs/class/corlib/ReferenceSources/CultureData.cs b/mcs/class/corlib/ReferenceSources/CultureData.cs index 6e69b7c5825..a0d79238e73 100644 --- a/mcs/class/corlib/ReferenceSources/CultureData.cs +++ b/mcs/class/corlib/ReferenceSources/CultureData.cs @@ -67,6 +67,13 @@ namespace System.Globalization int numberIndex; + int iDefaultAnsiCodePage; + int iDefaultOemCodePage; + int iDefaultMacCodePage; + int iDefaultEbcdicCodePage; + bool isRightToLeft; + string sListSeparator; + private CultureData (string name) { this.sRealName = name; @@ -97,6 +104,13 @@ namespace System.Globalization // 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); } @@ -115,7 +129,8 @@ namespace System.Globalization } } - 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; @@ -126,6 +141,12 @@ namespace System.Globalization 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; } @@ -240,11 +261,17 @@ namespace System.Globalization } } - internal String SCOMPAREINFO { - get { - return ""; + internal String SCOMPAREINFO { + get { + return ""; + } + } + + internal String STEXTINFO { + get { + return sRealName; + } } - } internal int ILANGUAGE { get { @@ -252,6 +279,42 @@ namespace System.Globalization } } + 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? diff --git a/mcs/class/corlib/ReferenceSources/Environment.cs b/mcs/class/corlib/ReferenceSources/Environment.cs index afdf9315a47..92057e9b5c3 100644 --- a/mcs/class/corlib/ReferenceSources/Environment.cs +++ b/mcs/class/corlib/ReferenceSources/Environment.cs @@ -38,5 +38,11 @@ namespace System default: return codePage.ToString (CultureInfo.InvariantCulture); } } + + internal static bool IsWindows8OrAbove { + get { + return false; + } + } } } \ No newline at end of file diff --git a/mcs/class/corlib/ReferenceSources/JitHelpers.cs b/mcs/class/corlib/ReferenceSources/JitHelpers.cs index 05c4d716cc1..d5d822fdb00 100644 --- a/mcs/class/corlib/ReferenceSources/JitHelpers.cs +++ b/mcs/class/corlib/ReferenceSources/JitHelpers.cs @@ -6,7 +6,17 @@ namespace System.Runtime.CompilerServices { { static internal T UnsafeCast(Object o) where T : class { - return (T)o; + return Array.UnsafeMov (o); + } + + static internal int UnsafeEnumCast(T val) where T : struct + { + return Array.UnsafeMov (val); + } + + static internal long UnsafeEnumCastLong(T val) where T : struct + { + throw new NotImplementedException (); } } } \ No newline at end of file diff --git a/mcs/class/corlib/ReferenceSources/ParseNumbers.cs b/mcs/class/corlib/ReferenceSources/ParseNumbers.cs index b6b73bea817..c87ea8f0860 100644 --- a/mcs/class/corlib/ReferenceSources/ParseNumbers.cs +++ b/mcs/class/corlib/ReferenceSources/ParseNumbers.cs @@ -168,6 +168,13 @@ namespace System { } } + // 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) @@ -177,11 +184,13 @@ namespace System { 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 @@ -195,7 +204,7 @@ namespace System { 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; @@ -211,9 +220,9 @@ namespace System { 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."); @@ -224,7 +233,7 @@ namespace System { break; } - if (digitValue >= fromBase) { + if (digitValue >= fromBaseULong) { if (chars > 0) { throw new FormatException ("Additional unparsable " + "characters are at the end of the string."); @@ -234,7 +243,18 @@ namespace System { } } - 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; } @@ -245,7 +265,24 @@ namespace System { 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) diff --git a/mcs/class/corlib/ReferenceSources/RuntimeType.cs b/mcs/class/corlib/ReferenceSources/RuntimeType.cs index 3557e77817c..9dd5e9c6ad0 100644 --- a/mcs/class/corlib/ReferenceSources/RuntimeType.cs +++ b/mcs/class/corlib/ReferenceSources/RuntimeType.cs @@ -394,42 +394,11 @@ namespace System 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)] @@ -612,7 +581,7 @@ namespace System 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 (); diff --git a/mcs/class/corlib/ReferenceSources/String.cs b/mcs/class/corlib/ReferenceSources/String.cs index d4cec69780f..a3ca19e5589 100644 --- a/mcs/class/corlib/ReferenceSources/String.cs +++ b/mcs/class/corlib/ReferenceSources/String.cs @@ -611,6 +611,44 @@ namespace System { 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 diff --git a/mcs/class/corlib/ReferenceSources/TextInfo.cs b/mcs/class/corlib/ReferenceSources/TextInfo.cs new file mode 100644 index 00000000000..52bf3a1306a --- /dev/null +++ b/mcs/class/corlib/ReferenceSources/TextInfo.cs @@ -0,0 +1,201 @@ +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 diff --git a/mcs/class/corlib/ReferenceSources/TimeZoneInfoOptions.cs b/mcs/class/corlib/ReferenceSources/TimeZoneInfoOptions.cs deleted file mode 100644 index 50ce810a716..00000000000 --- a/mcs/class/corlib/ReferenceSources/TimeZoneInfoOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace System -{ - [Flags] - internal enum TimeZoneInfoOptions { - None = 1, - NoThrowOnInvalidTime = 2 - }; -} \ No newline at end of file diff --git a/mcs/class/corlib/ReferenceSources/TypeBuilderInstantiation.cs b/mcs/class/corlib/ReferenceSources/TypeBuilderInstantiation.cs new file mode 100644 index 00000000000..9e826646321 --- /dev/null +++ b/mcs/class/corlib/ReferenceSources/TypeBuilderInstantiation.cs @@ -0,0 +1,14 @@ +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 diff --git a/mcs/class/corlib/System.Collections.Generic/Comparer.cs b/mcs/class/corlib/System.Collections.Generic/Comparer.cs deleted file mode 100644 index d19ce2cc8bb..00000000000 --- a/mcs/class/corlib/System.Collections.Generic/Comparer.cs +++ /dev/null @@ -1,126 +0,0 @@ -// -// 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 : IComparer, IComparer - { - static readonly Comparer _default = typeof (IComparable).IsAssignableFrom (typeof (T)) ? - (Comparer) Activator.CreateInstance (typeof (GenericComparer <>).MakeGenericType (typeof (T))) : - new DefaultComparer (); - - public abstract int Compare (T x, T y); - - public static Comparer Default { - get { - return _default; - } - } - - public static Comparer Create (Comparison comparison) - { - if (comparison == null) - throw new ArgumentNullException ("comparison"); - - return new ComparisonComparer (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 - { - 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 : Comparer where T : IComparable - { - 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 : Comparer - { - readonly Comparison comparison; - - public ComparisonComparer (Comparison comparison) - { - this.comparison = comparison; - } - - public override int Compare (T x, T y) - { - return comparison (x, y); - } - } -} diff --git a/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs b/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs deleted file mode 100644 index 9338f966f50..00000000000 --- a/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs +++ /dev/null @@ -1,229 +0,0 @@ -// -// 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 : IEqualityComparer, IEqualityComparer { - - static EqualityComparer () - { - var t = typeof (T); - if (t == typeof (string)) { - _default = (EqualityComparer) (object) new InternalStringComparer (); - return; - } - - if (t == typeof (int)) { - _default = (EqualityComparer) (object) new IntEqualityComparer (); - return; - } - - if (t.IsEnum && Enum.GetUnderlyingType (t) == typeof (int)) { - _default = new EnumIntEqualityComparer (); - return; - } - - if (typeof (IEquatable ).IsAssignableFrom (t)) - _default = (EqualityComparer ) Activator.CreateInstance (typeof (GenericEqualityComparer <>).MakeGenericType (t)); - else - _default = new DefaultComparer (); - } - - public abstract int GetHashCode (T obj); - public abstract bool Equals (T x, T y); - - static readonly EqualityComparer _default; - - public static EqualityComparer 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 : EqualityComparer { - - 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 { - - 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 - { - 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 : EqualityComparer - { - public override int GetHashCode (T obj) - { - return Array.UnsafeMov (obj); - } - - public override bool Equals (T x, T y) - { - return Array.UnsafeMov (x) == Array.UnsafeMov (y); - } - - internal override int IndexOf (T[] array, T value, int startIndex, int endIndex) - { - int v = Array.UnsafeMov (value); - var a = Array.UnsafeMov (array); - for (int i = startIndex; i < endIndex; ++i) { - if (Array.UnsafeLoad (a, i) == v) - return i; - } - - return -1; - } - } - - [Serializable] - sealed class GenericEqualityComparer : EqualityComparer where T : IEquatable { - - 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); - } - } -} diff --git a/mcs/class/corlib/System.Globalization/.gitattributes b/mcs/class/corlib/System.Globalization/.gitattributes deleted file mode 100644 index 1e0deee1a0d..00000000000 --- a/mcs/class/corlib/System.Globalization/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -/CodePageDataItem.cs -crlf diff --git a/mcs/class/corlib/System.Globalization/CalendarAlgorithmType.cs b/mcs/class/corlib/System.Globalization/CalendarAlgorithmType.cs deleted file mode 100644 index f66c25e0be2..00000000000 --- a/mcs/class/corlib/System.Globalization/CalendarAlgorithmType.cs +++ /dev/null @@ -1,41 +0,0 @@ -// ::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, - } - -} diff --git a/mcs/class/corlib/System.Globalization/CalendarWeekRule.cs b/mcs/class/corlib/System.Globalization/CalendarWeekRule.cs deleted file mode 100644 index 678eded7fd9..00000000000 --- a/mcs/class/corlib/System.Globalization/CalendarWeekRule.cs +++ /dev/null @@ -1,52 +0,0 @@ -// ::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 -{ - ///

- /// The System.Globalization.CalendarWeekRule enumeration - /// - [System.Runtime.InteropServices.ComVisible(true)] - [System.Serializable] - public enum CalendarWeekRule - { - FirstDay = 0, - FirstFullWeek = 1, - FirstFourDayWeek = 2 - - } - -} diff --git a/mcs/class/corlib/System.Globalization/CultureInfo.cs b/mcs/class/corlib/System.Globalization/CultureInfo.cs index 0793fe501e4..b806082b188 100644 --- a/mcs/class/corlib/System.Globalization/CultureInfo.cs +++ b/mcs/class/corlib/System.Globalization/CultureInfo.cs @@ -84,6 +84,16 @@ namespace System.Globalization [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 @@ -417,18 +427,26 @@ namespace System.Globalization // 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 (); @@ -624,7 +642,9 @@ namespace System.Globalization 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) {} @@ -644,8 +664,8 @@ namespace System.Globalization if (culture == InvariantCultureId) { /* Short circuit the invariant culture */ - ConstructInvariant (read_only); m_cultureData = CultureData.Invariant; + ConstructInvariant (read_only); return; } @@ -657,7 +677,9 @@ namespace System.Globalization 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) {} @@ -677,8 +699,8 @@ namespace System.Globalization if (name.Length == 0) { /* Short circuit the invariant culture */ - ConstructInvariant (read_only); m_cultureData = CultureData.Invariant; + ConstructInvariant (read_only); return; } @@ -686,7 +708,9 @@ namespace System.Globalization 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 @@ -803,7 +827,10 @@ namespace System.Globalization 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; } diff --git a/mcs/class/corlib/System.Globalization/DateTimeStyles.cs b/mcs/class/corlib/System.Globalization/DateTimeStyles.cs deleted file mode 100644 index a61d31595a3..00000000000 --- a/mcs/class/corlib/System.Globalization/DateTimeStyles.cs +++ /dev/null @@ -1,52 +0,0 @@ -// 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 diff --git a/mcs/class/corlib/System.Globalization/DigitShapes.cs b/mcs/class/corlib/System.Globalization/DigitShapes.cs deleted file mode 100644 index a1a2142bdb3..00000000000 --- a/mcs/class/corlib/System.Globalization/DigitShapes.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Globalization/GregorianCalendarTypes.cs b/mcs/class/corlib/System.Globalization/GregorianCalendarTypes.cs deleted file mode 100644 index 49a98dbbf7d..00000000000 --- a/mcs/class/corlib/System.Globalization/GregorianCalendarTypes.cs +++ /dev/null @@ -1,68 +0,0 @@ -// 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 { - - /// - /// - Localized = 1, - - /// - /// - USEnglish = 2, - - /// - /// - MiddleEastFrench = 9, - - /// - /// - Arabic = 10, - - /// - /// - TransliteratedEnglish = 11, - - /// - /// - TransliteratedFrench = 12, - } // GregorianCalendarTypes - -} // System.Globalization diff --git a/mcs/class/corlib/System.Globalization/TextInfo.cs b/mcs/class/corlib/System.Globalization/TextInfo.cs deleted file mode 100644 index 07d1eeb9b2b..00000000000 --- a/mcs/class/corlib/System.Globalization/TextInfo.cs +++ /dev/null @@ -1,673 +0,0 @@ -// -// System.Globalization.TextInfo.cs -// -// Authors: -// Dick Porter (dick@ximian.com) -// Duncan Mak (duncan@ximian.com) -// Atsushi Enomoto (atsushi@ximian.com) -// Sebastien Pouliot -// -// (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; - } - } -} diff --git a/mcs/class/corlib/System.IO/DirectoryNotFoundException.cs b/mcs/class/corlib/System.IO/DirectoryNotFoundException.cs deleted file mode 100644 index 8a3392e99ff..00000000000 --- a/mcs/class/corlib/System.IO/DirectoryNotFoundException.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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) - { - } - } -} diff --git a/mcs/class/corlib/System.IO/DriveNotFoundException.cs b/mcs/class/corlib/System.IO/DriveNotFoundException.cs deleted file mode 100644 index 52434e251e7..00000000000 --- a/mcs/class/corlib/System.IO/DriveNotFoundException.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// System.IO.DriveNotFoundException.cs -// -// Author: -// Kornél Pál -// -// 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) - { - } - } -} diff --git a/mcs/class/corlib/System.IO/EndOfStreamException.cs b/mcs/class/corlib/System.IO/EndOfStreamException.cs deleted file mode 100644 index 4073c8bcce3..00000000000 --- a/mcs/class/corlib/System.IO/EndOfStreamException.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// 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) - { - } - - } -} diff --git a/mcs/class/corlib/System.IO/FileLoadException.cs b/mcs/class/corlib/System.IO/FileLoadException.cs deleted file mode 100644 index e978bac6499..00000000000 --- a/mcs/class/corlib/System.IO/FileLoadException.cs +++ /dev/null @@ -1,139 +0,0 @@ -// -// 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 (); - } - } -} diff --git a/mcs/class/corlib/System.IO/FileNotFoundException.cs b/mcs/class/corlib/System.IO/FileNotFoundException.cs deleted file mode 100644 index 0f12284110c..00000000000 --- a/mcs/class/corlib/System.IO/FileNotFoundException.cs +++ /dev/null @@ -1,144 +0,0 @@ -// -// 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 (); - } - } -} diff --git a/mcs/class/corlib/System.IO/FileStream.cs b/mcs/class/corlib/System.IO/FileStream.cs index 1cc5364dfd5..610247d2e08 100644 --- a/mcs/class/corlib/System.IO/FileStream.cs +++ b/mcs/class/corlib/System.IO/FileStream.cs @@ -988,7 +988,7 @@ namespace System.IO 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; } diff --git a/mcs/class/corlib/System.IO/IOException.cs b/mcs/class/corlib/System.IO/IOException.cs deleted file mode 100644 index e4c2deff921..00000000000 --- a/mcs/class/corlib/System.IO/IOException.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// 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; - } - } -} diff --git a/mcs/class/corlib/System.IO/PathTooLongException.cs b/mcs/class/corlib/System.IO/PathTooLongException.cs deleted file mode 100644 index a856ea83c29..00000000000 --- a/mcs/class/corlib/System.IO/PathTooLongException.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// 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) - { - } - - } -} diff --git a/mcs/class/corlib/System.Runtime.ConstrainedExecution/CER.cs b/mcs/class/corlib/System.Runtime.ConstrainedExecution/CER.cs deleted file mode 100644 index ba07f91f3f1..00000000000 --- a/mcs/class/corlib/System.Runtime.ConstrainedExecution/CER.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.ConstrainedExecution/ChangeLog b/mcs/class/corlib/System.Runtime.ConstrainedExecution/ChangeLog deleted file mode 100644 index 115efbb7514..00000000000 --- a/mcs/class/corlib/System.Runtime.ConstrainedExecution/ChangeLog +++ /dev/null @@ -1,35 +0,0 @@ -2008-04-02 Andreas Nahr - - * ReliabilityContractAttribute.cs: Fix parameter names - -2005-10-28 Sebastien Pouliot - - * CriticialFinalizerObject.cs: Added [ReliabilityContract] to ctor. - * ReliabilityContractAttribute.cs: Removed (obsoleted) default ctor. - -2005-05-24 Sebastien Pouliot - - * CriticialFinalizerObject.cs: Changed ComVisible to true. - * ReliabilityContractAttribute.cs: Default constructor is obsolete. - Properties don't have setters. - -2005-03-04 Kazuki Oikawa - - * PrePrepareMethodAttribute.cs: - * ReliabilityContractAttribute.cs: Fixed attributes. - -2004-08-12 Sebastien Pouliot - - * 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 - - * CriticalFinalizerObject.cs: Moved from System.Runtime.Reliability to - match Fx 2.0 beta 1. diff --git a/mcs/class/corlib/System.Runtime.ConstrainedExecution/Consistency.cs b/mcs/class/corlib/System.Runtime.ConstrainedExecution/Consistency.cs deleted file mode 100644 index fa3d687c4e9..00000000000 --- a/mcs/class/corlib/System.Runtime.ConstrainedExecution/Consistency.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.ConstrainedExecution/CriticialFinalizerObject.cs b/mcs/class/corlib/System.Runtime.ConstrainedExecution/CriticialFinalizerObject.cs deleted file mode 100644 index 412377afed7..00000000000 --- a/mcs/class/corlib/System.Runtime.ConstrainedExecution/CriticialFinalizerObject.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System.Runtime.ConstrainedExecution/PrePrepareMethodAttribute.cs b/mcs/class/corlib/System.Runtime.ConstrainedExecution/PrePrepareMethodAttribute.cs deleted file mode 100644 index d7cb07dd086..00000000000 --- a/mcs/class/corlib/System.Runtime.ConstrainedExecution/PrePrepareMethodAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System.Runtime.ConstrainedExecution/ReliabilityContractAttribute.cs b/mcs/class/corlib/System.Runtime.ConstrainedExecution/ReliabilityContractAttribute.cs deleted file mode 100644 index 8f191fd510e..00000000000 --- a/mcs/class/corlib/System.Runtime.ConstrainedExecution/ReliabilityContractAttribute.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// 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; } - } - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/BINDPTR.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/BINDPTR.cs deleted file mode 100644 index bf88b9e6cc0..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/BINDPTR.cs +++ /dev/null @@ -1,44 +0,0 @@ - -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/BIND_OPTS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/BIND_OPTS.cs deleted file mode 100644 index c3b9b0fd02e..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/BIND_OPTS.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/CALLCONV.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/CALLCONV.cs deleted file mode 100644 index 7534760b9d5..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/CALLCONV.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/CONNECTDATA.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/CONNECTDATA.cs deleted file mode 100644 index f1b4957610a..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/CONNECTDATA.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ChangeLog b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ChangeLog deleted file mode 100644 index 650af5d2c4c..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ChangeLog +++ /dev/null @@ -1,105 +0,0 @@ -2008-04-02 Andreas Nahr - - * IEnumVARIANT.cs: Fix parameter names - -2007-08-10 Atsushi Enomoto - - * 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 - - * IMoniker.cs ELEMDESC.cs VARDESC.cs IRunningObjectTable.cs : - cosmetic 2.0 API fixes. - -2005-09-21 Kornél Pál - - * 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 - - * 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 - - * 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 - - * 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 diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/DESCKIND.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/DESCKIND.cs deleted file mode 100644 index 0fbd6969cf7..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/DESCKIND.cs +++ /dev/null @@ -1,45 +0,0 @@ - -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/DISPPARAMS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/DISPPARAMS.cs deleted file mode 100644 index a8518e55ff1..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/DISPPARAMS.cs +++ /dev/null @@ -1,42 +0,0 @@ - -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ELEMDESC.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ELEMDESC.cs deleted file mode 100644 index 56429a75c88..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ELEMDESC.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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; - } - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/EXCEPINFO.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/EXCEPINFO.cs deleted file mode 100644 index d30f264b393..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/EXCEPINFO.cs +++ /dev/null @@ -1,52 +0,0 @@ - -// -// 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 diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FILETIME.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FILETIME.cs deleted file mode 100644 index 1a6b08b060e..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FILETIME.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCDESC.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCDESC.cs deleted file mode 100644 index 8276293ce41..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCDESC.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCFLAGS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCFLAGS.cs deleted file mode 100644 index 10f165f1586..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCFLAGS.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCKIND.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCKIND.cs deleted file mode 100644 index 38abc1b262f..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/FUNCKIND.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IBindCtx.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IBindCtx.cs deleted file mode 100644 index 49d9c044c70..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IBindCtx.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IConnectionPoint.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IConnectionPoint.cs deleted file mode 100644 index 68d9175f37c..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IConnectionPoint.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IConnectionPointContainer.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IConnectionPointContainer.cs deleted file mode 100644 index 92ab88eae5d..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IConnectionPointContainer.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IDLDESC.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IDLDESC.cs deleted file mode 100644 index 94aa57d05a2..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IDLDESC.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IDLFLAG.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IDLFLAG.cs deleted file mode 100644 index a2334df3303..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IDLFLAG.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumConnectionPoints.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumConnectionPoints.cs deleted file mode 100644 index b6afc1de6fd..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumConnectionPoints.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumConnections.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumConnections.cs deleted file mode 100644 index 1980ea5590a..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumConnections.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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); - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumMoniker.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumMoniker.cs deleted file mode 100644 index 3aa4c79cb1a..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumMoniker.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumString.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumString.cs deleted file mode 100644 index b7563f99921..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumString.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumVARIANT.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumVARIANT.cs deleted file mode 100644 index b1079441c51..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IEnumVARIANT.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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 (); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IMPLTYPEFLAGS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IMPLTYPEFLAGS.cs deleted file mode 100644 index ff3375ee601..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IMPLTYPEFLAGS.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IMoniker.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IMoniker.cs deleted file mode 100644 index ddf2b64e899..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IMoniker.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/INVOKEKIND.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/INVOKEKIND.cs deleted file mode 100644 index 348e3352513..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/INVOKEKIND.cs +++ /dev/null @@ -1,43 +0,0 @@ - -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IPersistFile.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IPersistFile.cs deleted file mode 100644 index 24e97a0f10b..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IPersistFile.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IRunningObjectTable.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IRunningObjectTable.cs deleted file mode 100644 index 52e37a02e64..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IRunningObjectTable.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IStream.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IStream.cs deleted file mode 100644 index 78cccb04894..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/IStream.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeComp.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeComp.cs deleted file mode 100644 index ad65589d6f8..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeComp.cs +++ /dev/null @@ -1,42 +0,0 @@ - -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeInfo.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeInfo.cs deleted file mode 100644 index 607f044eb58..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeInfo.cs +++ /dev/null @@ -1,62 +0,0 @@ - -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeInfo2.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeInfo2.cs deleted file mode 100644 index 1b9544f3578..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeInfo2.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeLib.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeLib.cs deleted file mode 100644 index 8f9330db2f3..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeLib.cs +++ /dev/null @@ -1,54 +0,0 @@ - -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeLib2.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeLib2.cs deleted file mode 100644 index 6aae3ee4528..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/ITypeLib2.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// 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 (); - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/LIBFLAGS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/LIBFLAGS.cs deleted file mode 100644 index c25dbb23e19..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/LIBFLAGS.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/PARAMDESC.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/PARAMDESC.cs deleted file mode 100644 index ba54d8b1c53..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/PARAMDESC.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/PARAMFLAG.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/PARAMFLAG.cs deleted file mode 100644 index 5d2af1c246f..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/PARAMFLAG.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/STATSTG.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/STATSTG.cs deleted file mode 100644 index ffc4c1a484a..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/STATSTG.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// 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; - } - -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/SYSKIND.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/SYSKIND.cs deleted file mode 100644 index e854f098b4a..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/SYSKIND.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEATTR.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEATTR.cs deleted file mode 100644 index 9ff0bc1adc0..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEATTR.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// 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; - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEDESC.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEDESC.cs deleted file mode 100644 index ac11106b5c7..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEDESC.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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; - } -} diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEFLAGS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEFLAGS.cs deleted file mode 100644 index 1a25108d0d4..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEFLAGS.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEKIND.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEKIND.cs deleted file mode 100644 index 3156769d56f..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPEKIND.cs +++ /dev/null @@ -1,50 +0,0 @@ - -// -// 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 - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPELIBATTR.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPELIBATTR.cs deleted file mode 100644 index ceacf684d2c..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/TYPELIBATTR.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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; - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARDESC.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARDESC.cs deleted file mode 100644 index 08fb7e62219..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARDESC.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// 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; - } - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARFLAGS.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARFLAGS.cs deleted file mode 100644 index 5ef00075fbf..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARFLAGS.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARKIND.cs b/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARKIND.cs deleted file mode 100644 index d104208b14e..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.ComTypes/VARKIND.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System.Runtime.InteropServices.Expando/Changelog b/mcs/class/corlib/System.Runtime.InteropServices.Expando/Changelog deleted file mode 100644 index 18f209a5e6f..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.Expando/Changelog +++ /dev/null @@ -1,11 +0,0 @@ -2007-08-08 Atsushi Enomoto - - * IExpando.cs : [ComVisible] - -2003-11-13 Andreas Nahr - - * IExpando.cs: Added attribute - -2002-11-20 Alejandro Sánchez Acosta - - * IExpando.cs added. diff --git a/mcs/class/corlib/System.Runtime.InteropServices.Expando/IExpando.cs b/mcs/class/corlib/System.Runtime.InteropServices.Expando/IExpando.cs deleted file mode 100644 index 1a2b2837d7a..00000000000 --- a/mcs/class/corlib/System.Runtime.InteropServices.Expando/IExpando.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System.Runtime.Reliability/CER.cs b/mcs/class/corlib/System.Runtime.Reliability/CER.cs deleted file mode 100644 index 3a80a166a3d..00000000000 --- a/mcs/class/corlib/System.Runtime.Reliability/CER.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.Reliability/ChangeLog b/mcs/class/corlib/System.Runtime.Reliability/ChangeLog deleted file mode 100644 index 57a6f68d16e..00000000000 --- a/mcs/class/corlib/System.Runtime.Reliability/ChangeLog +++ /dev/null @@ -1,20 +0,0 @@ -2005-03-04 Kazuki Oikawa - - * CER.cs: - * Consistency.cs: - * PrePrepareMethodAttribute.cs: - * ReliabilityContractAttribute.cs: Added missing attributes. - -2004-08-03 Sebastien Pouliot - - * CriticialFinalizerObject.cs: Moved to System.Runtime. - ConstrainedExecution to match Fx 2.0 beta 1. - -2004-07-12 Duncan Mak - - * CER.cs: - * Consistency.cs: - * CriticialFinalizerObject.cs: - * PrePrepareMethodAttribute.cs: - * ReliabilityContractAttribute.cs: Added. - diff --git a/mcs/class/corlib/System.Runtime.Reliability/Consistency.cs b/mcs/class/corlib/System.Runtime.Reliability/Consistency.cs deleted file mode 100644 index 5babff4f30e..00000000000 --- a/mcs/class/corlib/System.Runtime.Reliability/Consistency.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System.Runtime.Reliability/PrePrepareMethodAttribute.cs b/mcs/class/corlib/System.Runtime.Reliability/PrePrepareMethodAttribute.cs deleted file mode 100644 index 8f1c0552a61..00000000000 --- a/mcs/class/corlib/System.Runtime.Reliability/PrePrepareMethodAttribute.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System.Runtime.Reliability/ReliabilityContractAttribute.cs b/mcs/class/corlib/System.Runtime.Reliability/ReliabilityContractAttribute.cs deleted file mode 100644 index 59e76c54a60..00000000000 --- a/mcs/class/corlib/System.Runtime.Reliability/ReliabilityContractAttribute.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// 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; } - } - } -} - diff --git a/mcs/class/corlib/System.Runtime.Remoting.Contexts/Context.cs b/mcs/class/corlib/System.Runtime.Remoting.Contexts/Context.cs index 3dcdce4733e..7b8c0dfd920 100644 --- a/mcs/class/corlib/System.Runtime.Remoting.Contexts/Context.cs +++ b/mcs/class/corlib/System.Runtime.Remoting.Contexts/Context.cs @@ -150,7 +150,13 @@ namespace System.Runtime.Remoting.Contexts { return rp.ObjectIdentity.ClientDynamicProperties; } else + { +#if FEATURE_REMOTING return obj.ObjectIdentity.ServerDynamicProperties; +#else + throw new NotSupportedException (); +#endif + } } else if (ctx != null && obj == null) { diff --git a/mcs/class/corlib/System.Runtime.Remoting/TypeInfo.cs b/mcs/class/corlib/System.Runtime.Remoting/TypeInfo.cs index 59f2c8bbd8e..06f54b12ceb 100644 --- a/mcs/class/corlib/System.Runtime.Remoting/TypeInfo.cs +++ b/mcs/class/corlib/System.Runtime.Remoting/TypeInfo.cs @@ -56,7 +56,7 @@ namespace System.Runtime.Remoting int baseCount = 0; Type baseType = type.BaseType; - while (baseType != typeof (MarshalByRefObject) && baseType != typeof(object)) + while (baseType != typeof (MarshalByRefObject) && baseType != null) { baseType = baseType.BaseType; baseCount++; diff --git a/mcs/class/corlib/System/Action.cs b/mcs/class/corlib/System/Action.cs deleted file mode 100644 index 438f7fc31d2..00000000000 --- a/mcs/class/corlib/System/Action.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// 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 (T obj); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate void Action (T1 arg1, T2 arg2); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate void Action (T1 arg1, T2 arg2, T3 arg3); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4); - - public delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - public delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - public delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - public delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); -} diff --git a/mcs/class/corlib/System/ApplicationId.cs b/mcs/class/corlib/System/ApplicationId.cs deleted file mode 100644 index b8675911fc3..00000000000 --- a/mcs/class/corlib/System/ApplicationId.cs +++ /dev/null @@ -1,138 +0,0 @@ -// -// System.ApplicationId class -// -// Author: -// Sebastien Pouliot -// -// 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 (); - } - } -} diff --git a/mcs/class/corlib/System/Array.cs b/mcs/class/corlib/System/Array.cs index b4afbe2eb84..9c263400572 100644 --- a/mcs/class/corlib/System/Array.cs +++ b/mcs/class/corlib/System/Array.cs @@ -3045,7 +3045,7 @@ namespace System if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count) throw new ArgumentOutOfRangeException (); - return EqualityComparer.Default.IndexOf (array, value, startIndex, startIndex + count); + return EqualityComparer.Default.IndexOf (array, value, startIndex, count); } public static int LastIndexOf (T [] array, T value) diff --git a/mcs/class/corlib/System/AsyncCallback.cs b/mcs/class/corlib/System/AsyncCallback.cs deleted file mode 100644 index 3f2bf733cb6..00000000000 --- a/mcs/class/corlib/System/AsyncCallback.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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); -} diff --git a/mcs/class/corlib/System/AttributeTargets.cs b/mcs/class/corlib/System/AttributeTargets.cs deleted file mode 100644 index 3a023d38b22..00000000000 --- a/mcs/class/corlib/System/AttributeTargets.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System/BadImageFormatException.cs b/mcs/class/corlib/System/BadImageFormatException.cs deleted file mode 100644 index a6db337bb4e..00000000000 --- a/mcs/class/corlib/System/BadImageFormatException.cs +++ /dev/null @@ -1,147 +0,0 @@ -// -// 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 (); - } - } -} diff --git a/mcs/class/corlib/System/Buffer.cs b/mcs/class/corlib/System/Buffer.cs deleted file mode 100644 index 3f4960d7b79..00000000000 --- a/mcs/class/corlib/System/Buffer.cs +++ /dev/null @@ -1,264 +0,0 @@ -// -// 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); - } - } -} diff --git a/mcs/class/corlib/System/CLSCompliantAttribute.cs b/mcs/class/corlib/System/CLSCompliantAttribute.cs deleted file mode 100644 index 37d317daa52..00000000000 --- a/mcs/class/corlib/System/CLSCompliantAttribute.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// 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 -{ - /// - /// Used to indicate if an element of a program is CLS compliant. - /// - [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; - } - } - } -} diff --git a/mcs/class/corlib/System/Comparison.cs b/mcs/class/corlib/System/Comparison.cs deleted file mode 100644 index f15ba11b37c..00000000000 --- a/mcs/class/corlib/System/Comparison.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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 (T x, T y); -} - diff --git a/mcs/class/corlib/System/ConsoleCancelEventArgs.cs b/mcs/class/corlib/System/ConsoleCancelEventArgs.cs deleted file mode 100644 index 8684879fd16..00000000000 --- a/mcs/class/corlib/System/ConsoleCancelEventArgs.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// 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; } - } - } -} - diff --git a/mcs/class/corlib/System/ConsoleCancelEventHandler.cs b/mcs/class/corlib/System/ConsoleCancelEventHandler.cs deleted file mode 100644 index 027072f7054..00000000000 --- a/mcs/class/corlib/System/ConsoleCancelEventHandler.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// 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); -} - diff --git a/mcs/class/corlib/System/ConsoleColor.cs b/mcs/class/corlib/System/ConsoleColor.cs deleted file mode 100644 index e148296f694..00000000000 --- a/mcs/class/corlib/System/ConsoleColor.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System/ConsoleKey.cs b/mcs/class/corlib/System/ConsoleKey.cs deleted file mode 100644 index 78660b594a0..00000000000 --- a/mcs/class/corlib/System/ConsoleKey.cs +++ /dev/null @@ -1,180 +0,0 @@ -// -// 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, - } -} - diff --git a/mcs/class/corlib/System/ConsoleKeyInfo.cs b/mcs/class/corlib/System/ConsoleKeyInfo.cs deleted file mode 100644 index 961cb949d62..00000000000 --- a/mcs/class/corlib/System/ConsoleKeyInfo.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// 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 (); - } - } -} diff --git a/mcs/class/corlib/System/ConsoleModifiers.cs b/mcs/class/corlib/System/ConsoleModifiers.cs deleted file mode 100644 index da716264af6..00000000000 --- a/mcs/class/corlib/System/ConsoleModifiers.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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 - } -} - diff --git a/mcs/class/corlib/System/ConsoleSpecialKey.cs b/mcs/class/corlib/System/ConsoleSpecialKey.cs deleted file mode 100644 index 2d08ba4b854..00000000000 --- a/mcs/class/corlib/System/ConsoleSpecialKey.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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 - } -} - - diff --git a/mcs/class/corlib/System/ContextBoundObject.cs b/mcs/class/corlib/System/ContextBoundObject.cs deleted file mode 100644 index ca954d6d758..00000000000 --- a/mcs/class/corlib/System/ContextBoundObject.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System/ContextStaticAttribute.cs b/mcs/class/corlib/System/ContextStaticAttribute.cs deleted file mode 100644 index 9593d24a2df..00000000000 --- a/mcs/class/corlib/System/ContextStaticAttribute.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// 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 -{ - /// - /// The ContextStatic attribute is used to flag fields as being unique - /// - [AttributeUsage (AttributeTargets.Field, Inherited=false)] - [Serializable] - [ComVisible (true)] - public class ContextStaticAttribute : Attribute - { - public ContextStaticAttribute () - : base () - { - } - } -} diff --git a/mcs/class/corlib/System/Converter.cs b/mcs/class/corlib/System/Converter.cs deleted file mode 100644 index 07e56188ea3..00000000000 --- a/mcs/class/corlib/System/Converter.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// 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 (TInput input); -} diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs index ddbd37a5e27..fceac801220 100644 --- a/mcs/class/corlib/System/Environment.cs +++ b/mcs/class/corlib/System/Environment.cs @@ -57,7 +57,7 @@ namespace System { * 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)] diff --git a/mcs/class/corlib/System/EventArgs.cs b/mcs/class/corlib/System/EventArgs.cs deleted file mode 100644 index 6d903ec2cab..00000000000 --- a/mcs/class/corlib/System/EventArgs.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System/EventHandler.cs b/mcs/class/corlib/System/EventHandler.cs deleted file mode 100644 index 4d6706799dd..00000000000 --- a/mcs/class/corlib/System/EventHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// 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 (object sender, TEventArgs e) - ; - - [Serializable] - [System.Runtime.InteropServices.ComVisible (true)] - public delegate void EventHandler (object sender, EventArgs e); -} diff --git a/mcs/class/corlib/System/Exception.cs b/mcs/class/corlib/System/Exception.cs index 23e4469433b..0e305c1ede2 100644 --- a/mcs/class/corlib/System/Exception.cs +++ b/mcs/class/corlib/System/Exception.cs @@ -57,7 +57,7 @@ namespace System (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; @@ -80,7 +80,7 @@ namespace System public Exception (string message) { - this.message = message; + this._message = message; } protected Exception (SerializationInfo info, StreamingContext context) @@ -89,7 +89,7 @@ namespace System 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"); @@ -108,7 +108,7 @@ namespace System public Exception (string message, Exception innerException) { inner_exception = innerException; - this.message = message; + this._message = message; } public Exception InnerException { @@ -132,7 +132,7 @@ namespace System internal void SetMessage (string s) { - message = s; + _message = s; } internal void SetStackTrace (string s) @@ -150,11 +150,11 @@ namespace System 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; } } @@ -302,7 +302,7 @@ namespace System 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); @@ -407,13 +407,7 @@ namespace System // 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; } diff --git a/mcs/class/corlib/System/FlagsAttribute.cs b/mcs/class/corlib/System/FlagsAttribute.cs deleted file mode 100644 index cab0eec6513..00000000000 --- a/mcs/class/corlib/System/FlagsAttribute.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// 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 { - - /// - /// The FlagsAttribute tags enumerations as bitfields. - /// - /// - /// - /// 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. - /// - - [AttributeUsage (AttributeTargets.Enum, Inherited=false)] - [Serializable] - [ComVisible (true)] - public class FlagsAttribute : Attribute { - - // No methods. - - } -} diff --git a/mcs/class/corlib/System/Funcs.cs b/mcs/class/corlib/System/Funcs.cs deleted file mode 100644 index df011e8cea8..00000000000 --- a/mcs/class/corlib/System/Funcs.cs +++ /dev/null @@ -1,71 +0,0 @@ -// -// 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 (); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate TResult Func (T arg); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate TResult Func (T1 arg1, T2 arg2); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate TResult Func (T1 arg1, T2 arg2, T3 arg3); - -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - public delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4); - - public delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - public delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - public delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - public delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); -} diff --git a/mcs/class/corlib/System/Guid.cs b/mcs/class/corlib/System/Guid.cs index be979f692bf..753855f7a77 100644 --- a/mcs/class/corlib/System/Guid.cs +++ b/mcs/class/corlib/System/Guid.cs @@ -30,7 +30,7 @@ // 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; diff --git a/mcs/class/corlib/System/IAppDomainSetup.cs b/mcs/class/corlib/System/IAppDomainSetup.cs deleted file mode 100644 index c4e6a7a4fdc..00000000000 --- a/mcs/class/corlib/System/IAppDomainSetup.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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; } - } -} diff --git a/mcs/class/corlib/System/IApplicationDescription.cs b/mcs/class/corlib/System/IApplicationDescription.cs deleted file mode 100644 index 95f2967700a..00000000000 --- a/mcs/class/corlib/System/IApplicationDescription.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// System.IApplicationDescription interface -// -// Author: -// Sebastien Pouliot -// -// 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; - } - } -} diff --git a/mcs/class/corlib/System/IAsyncResult.cs b/mcs/class/corlib/System/IAsyncResult.cs deleted file mode 100644 index 94062b85493..00000000000 --- a/mcs/class/corlib/System/IAsyncResult.cs +++ /dev/null @@ -1,67 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 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 - - diff --git a/mcs/class/corlib/System/ICloneable.cs b/mcs/class/corlib/System/ICloneable.cs deleted file mode 100644 index 931f53422a2..00000000000 --- a/mcs/class/corlib/System/ICloneable.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 (); - } -} diff --git a/mcs/class/corlib/System/IComparable.cs b/mcs/class/corlib/System/IComparable.cs deleted file mode 100644 index c5330021b0e..00000000000 --- a/mcs/class/corlib/System/IComparable.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// 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 { - int CompareTo (T other); - } -} diff --git a/mcs/class/corlib/System/IConvertible.cs b/mcs/class/corlib/System/IConvertible.cs deleted file mode 100644 index 3816252230c..00000000000 --- a/mcs/class/corlib/System/IConvertible.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System/ICustomFormatter.cs b/mcs/class/corlib/System/ICustomFormatter.cs deleted file mode 100644 index 876c5ce3c45..00000000000 --- a/mcs/class/corlib/System/ICustomFormatter.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System/IDisposable.cs b/mcs/class/corlib/System/IDisposable.cs deleted file mode 100644 index 9c1859af508..00000000000 --- a/mcs/class/corlib/System/IDisposable.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// 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 (); - - } -} diff --git a/mcs/class/corlib/System/IEquatable.cs b/mcs/class/corlib/System/IEquatable.cs deleted file mode 100644 index c4092d9b243..00000000000 --- a/mcs/class/corlib/System/IEquatable.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// System.IEquatable.cs -// -// Author: -// Ben Maurer -// -// 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 { - bool Equals (T other); - } -} diff --git a/mcs/class/corlib/System/IFormatProvider.cs b/mcs/class/corlib/System/IFormatProvider.cs deleted file mode 100644 index 26afc9e16a7..00000000000 --- a/mcs/class/corlib/System/IFormatProvider.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System/IFormattable.cs b/mcs/class/corlib/System/IFormattable.cs deleted file mode 100644 index 30a8670972a..00000000000 --- a/mcs/class/corlib/System/IFormattable.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System/IHostContext.cs b/mcs/class/corlib/System/IHostContext.cs deleted file mode 100644 index 841fa084999..00000000000 --- a/mcs/class/corlib/System/IHostContext.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// System.IHostContext interface -// -// Author: -// Sebastien Pouliot -// -// 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; - } - } -} diff --git a/mcs/class/corlib/System/IObservable.cs b/mcs/class/corlib/System/IObservable.cs deleted file mode 100644 index 5274dbb30cd..00000000000 --- a/mcs/class/corlib/System/IObservable.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// IObservable.cs -// -// Authors: -// Marek Safar -// -// 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 - { - IDisposable Subscribe (IObserver observer); - } -} - diff --git a/mcs/class/corlib/System/IObserver.cs b/mcs/class/corlib/System/IObserver.cs deleted file mode 100644 index f6aaf6bb320..00000000000 --- a/mcs/class/corlib/System/IObserver.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// IObserver.cs -// -// Authors: -// Marek Safar -// -// 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 - { - void OnCompleted (); - void OnError (Exception error); - void OnNext(T value); - } -} - diff --git a/mcs/class/corlib/System/IProgress.cs b/mcs/class/corlib/System/IProgress.cs deleted file mode 100644 index 690f62d5b3e..00000000000 --- a/mcs/class/corlib/System/IProgress.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// IProgress.cs -// -// Authors: -// Marek Safar -// -// 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 - { - void Report (T value); - } -} - diff --git a/mcs/class/corlib/System/IServiceProvider.cs b/mcs/class/corlib/System/IServiceProvider.cs deleted file mode 100644 index d9d0faa809d..00000000000 --- a/mcs/class/corlib/System/IServiceProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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); - } -} diff --git a/mcs/class/corlib/System/InvalidTimeZoneException.cs b/mcs/class/corlib/System/InvalidTimeZoneException.cs deleted file mode 100644 index 27dd66a92a5..00000000000 --- a/mcs/class/corlib/System/InvalidTimeZoneException.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * System.InvalidimeZoneException - * - * Author(s) - * Stephane Delcroix - * - * 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) - {} - } -} diff --git a/mcs/class/corlib/System/LoaderOptimization.cs b/mcs/class/corlib/System/LoaderOptimization.cs deleted file mode 100644 index 885ee079c59..00000000000 --- a/mcs/class/corlib/System/LoaderOptimization.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// 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 - } -} diff --git a/mcs/class/corlib/System/LoaderOptimizationAttribute.cs b/mcs/class/corlib/System/LoaderOptimizationAttribute.cs deleted file mode 100644 index c817f15b69c..00000000000 --- a/mcs/class/corlib/System/LoaderOptimizationAttribute.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// 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; } - } - } -} diff --git a/mcs/class/corlib/System/MTAThreadAttribute.cs b/mcs/class/corlib/System/MTAThreadAttribute.cs deleted file mode 100644 index d684ee9d7e4..00000000000 --- a/mcs/class/corlib/System/MTAThreadAttribute.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System/NonSerializedAttribute.cs b/mcs/class/corlib/System/NonSerializedAttribute.cs deleted file mode 100644 index e5e2eeab1e4..00000000000 --- a/mcs/class/corlib/System/NonSerializedAttribute.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System/NullConsoleDriver.cs b/mcs/class/corlib/System/NullConsoleDriver.cs index 4ffabc85a30..ecec3b508b2 100644 --- a/mcs/class/corlib/System/NullConsoleDriver.cs +++ b/mcs/class/corlib/System/NullConsoleDriver.cs @@ -30,7 +30,10 @@ 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 { @@ -151,7 +154,7 @@ namespace System { public ConsoleKeyInfo ReadKey (bool intercept) { - return ConsoleKeyInfo.Empty; + return EmptyConsoleKeyInfo; } public void ResetColor () diff --git a/mcs/class/corlib/System/ObsoleteAttribute.cs b/mcs/class/corlib/System/ObsoleteAttribute.cs deleted file mode 100644 index 942bbbc610e..00000000000 --- a/mcs/class/corlib/System/ObsoleteAttribute.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// 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; } - } - } -} diff --git a/mcs/class/corlib/System/ParamArrayAttribute.cs b/mcs/class/corlib/System/ParamArrayAttribute.cs deleted file mode 100644 index 4084798838d..00000000000 --- a/mcs/class/corlib/System/ParamArrayAttribute.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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 -{ - /// - /// Used to flag that the method will take a variable number - /// of arguments - /// - [AttributeUsage (AttributeTargets.Parameter)] - [ComVisible (true)] - public sealed class ParamArrayAttribute : Attribute - { - public ParamArrayAttribute () - { - } - } -} diff --git a/mcs/class/corlib/System/Predicate.cs b/mcs/class/corlib/System/Predicate.cs deleted file mode 100644 index 66086b0a9bb..00000000000 --- a/mcs/class/corlib/System/Predicate.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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 (T obj); -} - diff --git a/mcs/class/corlib/System/STAThreadAttribute.cs b/mcs/class/corlib/System/STAThreadAttribute.cs deleted file mode 100644 index 754ad34f834..00000000000 --- a/mcs/class/corlib/System/STAThreadAttribute.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System/SerializableAttribute.cs b/mcs/class/corlib/System/SerializableAttribute.cs deleted file mode 100644 index cfbb7669001..00000000000 --- a/mcs/class/corlib/System/SerializableAttribute.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// 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 -{ - /// - /// Serialization Attribute for classes. - /// - - /// - /// 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). - /// - - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct - | AttributeTargets.Enum | AttributeTargets.Delegate, - Inherited=false)] - [ComVisible (true)] - public sealed class SerializableAttribute : Attribute - { - } -} diff --git a/mcs/class/corlib/System/TermInfoReader.cs b/mcs/class/corlib/System/TermInfoReader.cs index f4b03396225..6424d4fb79a 100644 --- a/mcs/class/corlib/System/TermInfoReader.cs +++ b/mcs/class/corlib/System/TermInfoReader.cs @@ -229,7 +229,7 @@ namespace System { length++; byte [] result = new byte [length]; - Buffer.BlockCopyInternal (buffer, offset, result, 0, length); + Buffer.InternalBlockCopy (buffer, offset, result, 0, length); return result; } diff --git a/mcs/class/corlib/System/ThreadStaticAttribute.cs b/mcs/class/corlib/System/ThreadStaticAttribute.cs deleted file mode 100644 index 3c13c3d58f9..00000000000 --- a/mcs/class/corlib/System/ThreadStaticAttribute.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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 () - { - } - } -} diff --git a/mcs/class/corlib/System/TimeZoneInfo.AdjustmentRule.cs b/mcs/class/corlib/System/TimeZoneInfo.AdjustmentRule.cs deleted file mode 100644 index 3afac7722d7..00000000000 --- a/mcs/class/corlib/System/TimeZoneInfo.AdjustmentRule.cs +++ /dev/null @@ -1,185 +0,0 @@ -/* - * System.TimeZoneInfo.AdjustmentRule - * - * Author(s) - * Stephane Delcroix - * - * 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, 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"); - } - } - } -} diff --git a/mcs/class/corlib/System/TimeZoneInfo.TransitionTime.cs b/mcs/class/corlib/System/TimeZoneInfo.TransitionTime.cs deleted file mode 100644 index 37a70641be4..00000000000 --- a/mcs/class/corlib/System/TimeZoneInfo.TransitionTime.cs +++ /dev/null @@ -1,290 +0,0 @@ -/* - * System.TimeZoneInfo.TransitionTime - * - * Author(s) - * Stephane Delcroix - * - * 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, 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"); - } - } - } - } -} diff --git a/mcs/class/corlib/System/TimeZoneInfo.cs b/mcs/class/corlib/System/TimeZoneInfo.cs index 3c0b535b43b..aa93584c933 100644 --- a/mcs/class/corlib/System/TimeZoneInfo.cs +++ b/mcs/class/corlib/System/TimeZoneInfo.cs @@ -45,14 +45,7 @@ using Microsoft.Win32; namespace System { -#if MOBILE - [TypeForwardedFrom (Consts.AssemblySystem_Core)] -#else - [TypeForwardedFrom (Consts.AssemblySystemCore_3_5)] -#endif - [SerializableAttribute] - public - sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback + partial class TimeZoneInfo { TimeSpan baseUtcOffset; public TimeSpan BaseUtcOffset { diff --git a/mcs/class/corlib/System/TimeZoneNotFoundException.cs b/mcs/class/corlib/System/TimeZoneNotFoundException.cs deleted file mode 100644 index 1333d971c82..00000000000 --- a/mcs/class/corlib/System/TimeZoneNotFoundException.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * System.TimeZoneNotFoundException - * - * Author(s) - * Stephane Delcroix - * - * 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) - {} - } -} diff --git a/mcs/class/corlib/System/TypeLoadException.cs b/mcs/class/corlib/System/TypeLoadException.cs deleted file mode 100644 index f963ae1de70..00000000000 --- a/mcs/class/corlib/System/TypeLoadException.cs +++ /dev/null @@ -1,120 +0,0 @@ -// -// 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)); - } - } -} diff --git a/mcs/class/corlib/Test/System.Collections.Generic/DictionaryTest.cs b/mcs/class/corlib/Test/System.Collections.Generic/DictionaryTest.cs index a361fbc50f8..129ee6d0bcc 100644 --- a/mcs/class/corlib/Test/System.Collections.Generic/DictionaryTest.cs +++ b/mcs/class/corlib/Test/System.Collections.Generic/DictionaryTest.cs @@ -633,6 +633,60 @@ namespace MonoTests.System.Collections.Generic { } } +#if !MONO + [Test] + public void SerializationCompatibilty () + { + /* Serialization output from .net + + var dict = new Dictionary (); + 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 (); + dict.Add ("key", "value"); + + BinaryFormatter fmt = new BinaryFormatter (); + var mdict = (Dictionary) 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 () { diff --git a/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs b/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs index 5a0fd3b6a25..e238781bcb7 100644 --- a/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs +++ b/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs @@ -37,6 +37,11 @@ namespace MonoTests.System.Collections.Generic { [TestFixture] public class EqualityComparerTest { + enum E + { + A, + B + } [Test] public void Default_GetHashCode_Null () @@ -59,6 +64,13 @@ namespace MonoTests.System.Collections.Generic { IEqualityComparer comparer = EqualityComparer.Default; Assert.IsTrue (comparer.Equals (null, null)); } + + [Test] + public void EnumComparison () + { + Assert.IsFalse (EqualityComparer.Default.Equals (E.A, E.B)); + Assert.IsFalse (EqualityComparer.Default.Equals (E.A, E.B)); + } } } diff --git a/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs b/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs index 3b743845371..48a8e76b63d 100644 --- a/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs +++ b/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs @@ -225,6 +225,15 @@ namespace MonoTests.System.Globalization 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))] diff --git a/mcs/class/corlib/Test/System.Runtime.ExceptionServices/ExceptionDispatchInfoTest.cs b/mcs/class/corlib/Test/System.Runtime.ExceptionServices/ExceptionDispatchInfoTest.cs index 3be96507bf4..fb7d0e57f7c 100644 --- a/mcs/class/corlib/Test/System.Runtime.ExceptionServices/ExceptionDispatchInfoTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.ExceptionServices/ExceptionDispatchInfoTest.cs @@ -26,8 +26,6 @@ // 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; @@ -91,10 +89,40 @@ namespace MonoTests.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 diff --git a/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs b/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs index 48e686ab8dd..e15cb30a839 100644 --- a/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.Serialization/SerializationTest.cs @@ -28,8 +28,8 @@ namespace MonoTests.System.Runtime.Serialization MemoryStream ms; string uri; +#if FEATURE_REMOTING [Test] - [Category ("MobileNotWorking")] public void TestSerialization () { MethodTester mt = new MethodTester(); @@ -41,6 +41,7 @@ namespace MonoTests.System.Runtime.Serialization RemotingServices.Disconnect (mt); } +#endif #if !MONOTOUCH [Test] @@ -77,6 +78,7 @@ namespace MonoTests.System.Runtime.Serialization return 2; } +#if FEATURE_REMOTING void WriteData () { StreamingContext context = new StreamingContext (StreamingContextStates.Other); @@ -148,7 +150,7 @@ namespace MonoTests.System.Runtime.Serialization CheckMessages ("MethodCall", originalMsgData, ProcessMessages (null, calls)); CheckMessages ("MethodResponse", originalMsgData, ProcessMessages (null, resps)); } - +#endif BinderTester_A CreateBinderTestData () { BinderTester_A bta = new BinderTester_A(); diff --git a/mcs/class/corlib/Test/System/ConvertTest.cs b/mcs/class/corlib/Test/System/ConvertTest.cs index c97a0a31b7e..f9dc5929d31 100644 --- a/mcs/class/corlib/Test/System/ConvertTest.cs +++ b/mcs/class/corlib/Test/System/ConvertTest.cs @@ -4711,6 +4711,86 @@ namespace MonoTests.System { 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 () { diff --git a/mcs/class/corlib/Test/System/TimeZoneInfo.AdjustmentRuleTest.cs b/mcs/class/corlib/Test/System/TimeZoneInfo.AdjustmentRuleTest.cs index 940b1290ea3..62ae67cfc81 100644 --- a/mcs/class/corlib/Test/System/TimeZoneInfo.AdjustmentRuleTest.cs +++ b/mcs/class/corlib/Test/System/TimeZoneInfo.AdjustmentRuleTest.cs @@ -55,16 +55,17 @@ namespace MonoTests.System } [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] @@ -79,7 +80,6 @@ namespace MonoTests.System } [Test] - [ExpectedException (typeof (ArgumentOutOfRangeException))] public void DeltaNotInSeconds () { if (Environment.OSVersion.Platform != PlatformID.Unix) @@ -88,7 +88,11 @@ namespace MonoTests.System 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) { + } } } diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index 079fc0d6688..be3f9139aec 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -88,31 +88,16 @@ System/AppDomain.cs 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 @@ -122,36 +107,15 @@ System/Double.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 @@ -161,16 +125,12 @@ System/MonoCustomAttrs.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 @@ -179,28 +139,21 @@ System/RuntimeFieldHandle.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 @@ -208,7 +161,6 @@ System/Void.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 @@ -242,44 +194,31 @@ System.Diagnostics.SymbolStore/SymbolToken.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 @@ -381,11 +320,6 @@ System.Runtime/GCSettings.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 @@ -560,53 +494,7 @@ System.Runtime.InteropServices/VARDESC.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 @@ -1154,12 +1042,6 @@ System.Threading/Timer.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 @@ -1176,7 +1058,6 @@ ReferenceSources/Environment.cs ReferenceSources/ExecutionContext.cs ReferenceSources/HashHelpers.cs ReferenceSources/ParseNumbers.cs -ReferenceSources/TimeZoneInfoOptions.cs ReferenceSources/AppDomain.cs ReferenceSources/CLRConfig.cs ReferenceSources/JitHelpers.cs @@ -1189,28 +1070,47 @@ ReferenceSources/MonoRuntimeWorkItem.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 @@ -1227,10 +1127,24 @@ ReferenceSources/CompareInfo.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 @@ -1240,23 +1154,31 @@ ReferenceSources/CompareInfo.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 @@ -1264,6 +1186,7 @@ ReferenceSources/CompareInfo.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 @@ -1271,11 +1194,16 @@ ReferenceSources/CompareInfo.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 @@ -1322,8 +1250,10 @@ ReferenceSources/CompareInfo.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 @@ -1359,7 +1289,9 @@ ReferenceSources/CompareInfo.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 @@ -1370,10 +1302,14 @@ ReferenceSources/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 @@ -1392,15 +1328,24 @@ ReferenceSources/CompareInfo.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 @@ -1480,6 +1425,34 @@ ReferenceSources/CompareInfo.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 @@ -1542,6 +1515,8 @@ ReferenceSources/CompareInfo.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 diff --git a/mcs/class/reference-assemblies/Makefile b/mcs/class/reference-assemblies/Makefile index a14f96f208a..e4b660ba5df 100644 --- a/mcs/class/reference-assemblies/Makefile +++ b/mcs/class/reference-assemblies/Makefile @@ -4,10 +4,16 @@ include ../../build/rules.make 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 diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index d7d370893c6..5965fb53e9d 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -4727,6 +4727,9 @@ namespace Mono.CSharp { 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: @@ -4734,8 +4737,6 @@ namespace Mono.CSharp { // 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; @@ -4749,8 +4750,7 @@ namespace Mono.CSharp { // 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; diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index f4df8c9c443..40eb0068b2d 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -11437,19 +11437,19 @@ namespace Mono.CSharp // 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; } } @@ -11490,7 +11490,7 @@ namespace Mono.CSharp 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; @@ -11522,7 +11522,7 @@ namespace Mono.CSharp { 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) diff --git a/mcs/mcs/import.cs b/mcs/mcs/import.cs index 98254207136..630548ce8d2 100644 --- a/mcs/mcs/import.cs +++ b/mcs/mcs/import.cs @@ -209,14 +209,14 @@ namespace Mono.CSharp 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; diff --git a/mcs/mcs/property.cs b/mcs/mcs/property.cs index 1d46ab2dab8..7d95e44efdb 100644 --- a/mcs/mcs/property.cs +++ b/mcs/mcs/property.cs @@ -548,19 +548,21 @@ namespace Mono.CSharp } 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) { diff --git a/mcs/tests/gtest-autoproperty-17.cs b/mcs/tests/gtest-autoproperty-17.cs new file mode 100644 index 00000000000..1897e33eb9b --- /dev/null +++ b/mcs/tests/gtest-autoproperty-17.cs @@ -0,0 +1,18 @@ +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) + { + } +} diff --git a/mcs/tests/gtest-optional-09.cs b/mcs/tests/gtest-optional-09.cs index cfbe860a7dc..7117ab291e7 100644 --- a/mcs/tests/gtest-optional-09.cs +++ b/mcs/tests/gtest-optional-09.cs @@ -59,20 +59,30 @@ public class Program 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; } @@ -100,6 +110,9 @@ public class Program if (Test_7 (false) != 0) return 7; + if (Test_8 (typeof (bool)) != 0) + return 8; + Console.WriteLine ("ok"); return 0; } diff --git a/mcs/tests/test-anon-70.cs b/mcs/tests/test-anon-70.cs index 2376311430a..d0fe4b7a07a 100644 --- a/mcs/tests/test-anon-70.cs +++ b/mcs/tests/test-anon-70.cs @@ -26,9 +26,12 @@ public class C Test (delegate () { int i = *v.GetUnsafeValue (); }); + + Test (delegate () { + byte* buffer = stackalloc byte[8192]; + }); } - public static void Main () { Exception diffException; diff --git a/mcs/tests/test-static-using-09-lib.cs b/mcs/tests/test-static-using-09-lib.cs new file mode 100644 index 00000000000..cd0468bbf08 --- /dev/null +++ b/mcs/tests/test-static-using-09-lib.cs @@ -0,0 +1,6 @@ +// Compiler options: -t:library + +public static class Constants +{ + public const long One = 1; +} \ No newline at end of file diff --git a/mcs/tests/test-static-using-09.cs b/mcs/tests/test-static-using-09.cs new file mode 100644 index 00000000000..993fd8df04e --- /dev/null +++ b/mcs/tests/test-static-using-09.cs @@ -0,0 +1,11 @@ +// 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 diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 9e8bdce22c8..cdc88dcbb51 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -20573,6 +20573,32 @@ + + + + 2 + + + 7 + + + + + 0 + + + 7 + + + + + 14 + + + 14 + + + @@ -29740,11 +29766,17 @@ 10 - 161 + 192 7 + + 10 + + + 10 + @@ -58081,7 +58113,7 @@ - 36 + 70 99 @@ -58131,7 +58163,10 @@ - + + 12 + + 17 @@ -70123,6 +70158,13 @@ + + + + 9 + + + diff --git a/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs b/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs index b6276ac2490..b47f8603c5a 100644 --- a/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs +++ b/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs @@ -288,9 +288,25 @@ namespace Mono.Linker.Steps { // 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; diff --git a/mcs/tools/xbuild/Makefile b/mcs/tools/xbuild/Makefile index 05c24763cde..949f3e59663 100644 --- a/mcs/tools/xbuild/Makefile +++ b/mcs/tools/xbuild/Makefile @@ -41,8 +41,12 @@ install-bin-data: 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 diff --git a/mono-core.spec.in b/mono-core.spec.in deleted file mode 100644 index 04c4e326ebf..00000000000 --- a/mono-core.spec.in +++ /dev/null @@ -1,1518 +0,0 @@ -%{!?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 diff --git a/mono/dis/TODO b/mono/dis/TODO deleted file mode 100644 index fb42dc0758a..00000000000 --- a/mono/dis/TODO +++ /dev/null @@ -1,5 +0,0 @@ -* Write test cases - - Write test cases to stress test TypeSpec. This is done by - creating arrays of various dimensions, sizes, and lower - bounds. diff --git a/mono/io-layer/Makefile.am b/mono/io-layer/Makefile.am index bca6a114399..47e31071494 100644 --- a/mono/io-layer/Makefile.am +++ b/mono/io-layer/Makefile.am @@ -28,7 +28,6 @@ OTHER_H = \ semaphores.h \ sockets.h \ status.h \ - system.h \ threads.h \ timefuncs.h \ types.h \ @@ -83,8 +82,6 @@ OTHER_SRC = \ socket-private.h \ socket-wrappers.h \ status.h \ - system.c \ - system.h \ threads.h \ thread-private.h \ timefuncs.c \ diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 913a08570a4..ce7aee14c88 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -90,6 +90,7 @@ #include #include #include +#include /* The process' environment strings */ #if defined(__APPLE__) && !defined (__arm__) && !defined (__aarch64__) @@ -1309,11 +1310,19 @@ GetProcessTimes (gpointer process, WapiFileTime *create_time, /* 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); diff --git a/mono/io-layer/system.c b/mono/io-layer/system.c deleted file mode 100644 index 3a336ce2cef..00000000000 --- a/mono/io-layer/system.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * system.c: System information - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#include -#include -#include -#include -#include - -#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 -} - - diff --git a/mono/io-layer/system.h b/mono/io-layer/system.h deleted file mode 100644 index 390b1776b7d..00000000000 --- a/mono/io-layer/system.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * system.h: System information - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#ifndef _WAPI_SYSTEM_H_ -#define _WAPI_SYSTEM_H_ - -#include - -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_ */ diff --git a/mono/io-layer/threads.h b/mono/io-layer/threads.h index d2dbcbfaf1c..13b6bd1401f 100644 --- a/mono/io-layer/threads.h +++ b/mono/io-layer/threads.h @@ -30,7 +30,6 @@ extern gsize GetCurrentThreadId(void); /* NB return is 32bit in MS API */ 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); diff --git a/mono/io-layer/uglify.h b/mono/io-layer/uglify.h index 120ce317747..aa847569cb8 100644 --- a/mono/io-layer/uglify.h +++ b/mono/io-layer/uglify.h @@ -63,8 +63,6 @@ typedef WapiLargeInteger LARGE_INTEGER; 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; diff --git a/mono/io-layer/wapi.h b/mono/io-layer/wapi.h index e2c9639c3d4..c2a89920c34 100644 --- a/mono/io-layer/wapi.h +++ b/mono/io-layer/wapi.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/mono/io-layer/wthreads.c b/mono/io-layer/wthreads.c index 98a932b7e25..90a8cc4ffa8 100644 --- a/mono/io-layer/wthreads.c +++ b/mono/io-layer/wthreads.c @@ -341,15 +341,6 @@ _wapi_thread_apc_pending (gpointer handle) * 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) { diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 0a6e4067d19..1241a7a079e 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -291,6 +291,8 @@ sgen_sources = \ 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) @@ -365,5 +367,5 @@ endif 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 diff --git a/mono/metadata/TODO b/mono/metadata/TODO deleted file mode 100644 index f37fd656388..00000000000 --- a/mono/metadata/TODO +++ /dev/null @@ -1,4 +0,0 @@ - -* Uniform names - - We have a mess of names in the icall.c file, we need to sort that out. diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index b959cb96b04..c6d3071d05b 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -78,7 +78,7 @@ * 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 { diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 36080792d10..d2b6722e173 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1062,7 +1062,6 @@ mono_inflate_generic_signature (MonoMethodSignature *sig, MonoGenericContext *co typedef struct { MonoImage *corlib; - MonoImage *system; MonoClass *object_class; MonoClass *byte_class; MonoClass *void_class; @@ -1091,6 +1090,7 @@ typedef struct { MonoClass *methodhandle_class; MonoClass *systemtype_class; MonoClass *monotype_class; + MonoClass *runtimetype_class; MonoClass *exception_class; MonoClass *threadabortexception_class; MonoClass *thread_class; diff --git a/mono/metadata/decimal-ms.c b/mono/metadata/decimal-ms.c index 47a4ed06ca8..9330f0fb57b 100644 --- a/mono/metadata/decimal-ms.c +++ b/mono/metadata/decimal-ms.c @@ -55,8 +55,13 @@ static const uint32_t ten_to_ten_div_4 = 2500000000U; #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); \ @@ -2215,6 +2220,8 @@ mono_decimal_compare (MonoDecimal *left, MonoDecimal *right) 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. // diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 801d58e4162..d2d92fd51c9 100755 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -600,9 +600,6 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * } 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); @@ -716,6 +713,10 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * 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); diff --git a/mono/metadata/file-mmap-posix.c b/mono/metadata/file-mmap-posix.c index e4b2bd75d6d..227b3cc9697 100644 --- a/mono/metadata/file-mmap-posix.c +++ b/mono/metadata/file-mmap-posix.c @@ -9,7 +9,7 @@ #include -#ifndef TARGET_WIN32 +#ifndef HOST_WIN32 #include #include diff --git a/mono/metadata/file-mmap-windows.c b/mono/metadata/file-mmap-windows.c index 78203ad47a8..56d598ee7f2 100644 --- a/mono/metadata/file-mmap-windows.c +++ b/mono/metadata/file-mmap-windows.c @@ -9,7 +9,7 @@ #include -#ifdef TARGET_WIN32 +#ifdef HOST_WIN32 #include #include diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 87bb85e5664..530ad048095 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -105,10 +105,10 @@ ICALL(ARRAY_12, "SetValue", ves_icall_System_Array_SetValue) 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) @@ -426,22 +426,22 @@ ICALL(SOCK_6, "Connect_internal(intptr,System.Net.SocketAddress,int&)", ves_ical 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) @@ -733,7 +733,7 @@ ICALL(RT_1, "CreateInstanceInternal", ves_icall_System_Activator_CreateInstanceI 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) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 056e76eada4..1132dbfeb0f 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -2293,31 +2293,38 @@ ves_icall_MonoType_GetArrayRank (MonoReflectionType *type) 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; } @@ -6996,8 +7003,8 @@ mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *f MonoTypedRef res; MonoReflectionField *f; MonoClass *klass; - MonoType *ftype; - guint8 *p; + MonoType *ftype = NULL; + guint8 *p = NULL; int i; memset (&res, 0, sizeof (res)); diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 1e9596cff5d..2cf48fda847 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -1643,7 +1643,6 @@ mono_image_close_except_pools (MonoImage *image) 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) diff --git a/mono/metadata/make-bundle.pl b/mono/metadata/make-bundle.pl deleted file mode 100755 index fff9a87b9c7..00000000000 --- a/mono/metadata/make-bundle.pl +++ /dev/null @@ -1,104 +0,0 @@ -#!/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 () { - ++$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); - diff --git a/mono/metadata/mono-endian.h b/mono/metadata/mono-endian.h index 343b97194a2..acc2590193f 100644 --- a/mono/metadata/mono-endian.h +++ b/mono/metadata/mono-endian.h @@ -14,7 +14,49 @@ typedef union { 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); @@ -24,12 +66,14 @@ guint64 mono_read64 (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) \ diff --git a/mono/metadata/monosn.c b/mono/metadata/monosn.c deleted file mode 100644 index c9114c4744a..00000000000 --- a/mono/metadata/monosn.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include "mono/utils/mono-digest.h" -/* trim headers */ - -#include -#include - -#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; -} - diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 15be4b4a5c2..43a27343c8a 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -266,12 +266,6 @@ typedef struct { MonoString *param_name; } MonoArgumentException; -typedef struct { - MonoSystemException base; - MonoString *msg; - MonoString *type_name; -} MonoTypeLoadException; - typedef struct { MonoObject object; MonoObject *async_state; diff --git a/mono/metadata/object-offsets.h b/mono/metadata/object-offsets.h index ec6eb18540d..37d0f3612ce 100644 --- a/mono/metadata/object-offsets.h +++ b/mono/metadata/object-offsets.h @@ -203,6 +203,7 @@ DECL_OFFSET(MonoContext, rsp) 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) @@ -217,9 +218,10 @@ DECL_OFFSET(MonoLMF, rsp) 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) diff --git a/mono/metadata/sample-bundle b/mono/metadata/sample-bundle deleted file mode 100644 index ef8bbb380f2..00000000000 --- a/mono/metadata/sample-bundle +++ /dev/null @@ -1,5 +0,0 @@ -# sample bundle template for use with the configure option --with-bundle=... - -console: ../tests/console.exe -mscorlib: /usr/local/lib/corlib.dll - diff --git a/mono/metadata/sgen-debug.c b/mono/metadata/sgen-debug.c index 08d953a7aad..4801bd65338 100644 --- a/mono/metadata/sgen-debug.c +++ b/mono/metadata/sgen-debug.c @@ -126,7 +126,7 @@ describe_pointer (char *ptr, gboolean need_setup) 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); @@ -366,20 +366,20 @@ describe_nursery_ptr (char *ptr, gboolean need_setup) 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; } } diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 532e1f74aa5..0c841e28c04 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -328,19 +328,15 @@ static guint64 time_minor_pre_collection_fragment_clear = 0; 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; @@ -593,12 +589,7 @@ gray_queue_redirect (SgenGrayQueue *queue) 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 (); } } @@ -748,6 +739,8 @@ mono_gc_clear_domain (MonoDomain * domain) 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 (); @@ -1902,19 +1895,14 @@ init_stats (void) 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); @@ -1992,66 +1980,75 @@ sgen_concurrent_collection_in_progress (void) } 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)); } @@ -2155,6 +2152,49 @@ init_gray_queue (void) 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. * @@ -2166,8 +2206,6 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) 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); @@ -2191,6 +2229,8 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) 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 (); @@ -2267,7 +2307,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) * 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); @@ -2291,46 +2331,13 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) 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); @@ -2340,14 +2347,6 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) 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); @@ -2445,8 +2444,6 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean start_concurr 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) { @@ -2630,59 +2627,24 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean start_concurr 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 @@ -2749,14 +2711,7 @@ major_start_collection (gboolean concurrent, size_t *old_next_pin_slot) } 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; @@ -2807,14 +2762,6 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean 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); @@ -2916,7 +2863,7 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean 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)); @@ -2939,7 +2886,7 @@ major_finish_collection (const char *reason, size_t old_next_pin_slot, gboolean } static gboolean -major_do_collection (const char *reason) +major_do_collection (const char *reason, gboolean forced) { TV_DECLARE (time_start); TV_DECLARE (time_end); @@ -2957,7 +2904,7 @@ major_do_collection (const char *reason) 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); @@ -3033,7 +2980,7 @@ major_update_concurrent_collection (void) } static void -major_finish_concurrent_collection (void) +major_finish_concurrent_collection (gboolean forced) { TV_DECLARE (total_start); TV_DECLARE (total_end); @@ -3052,7 +2999,7 @@ major_finish_concurrent_collection (void) * 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); @@ -3066,7 +3013,7 @@ major_finish_concurrent_collection (void) 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); @@ -3093,7 +3040,6 @@ sgen_ensure_free_space (size_t size) 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"; @@ -3163,7 +3109,7 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const 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 (); @@ -3210,7 +3156,7 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const 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"; } @@ -3242,7 +3188,7 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const 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); @@ -4855,9 +4801,6 @@ mono_gc_base_init (void) g_strfreev (opts); } - if (major_collector.is_concurrent) - sgen_workers_init (1); - if (major_collector_opt) g_free (major_collector_opt); @@ -5029,6 +4972,9 @@ mono_gc_base_init (void) 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)); diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index f9c09677b86..c157e5257e8 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -169,6 +169,7 @@ extern LOCK_DECLARE (sgen_interruption_mutex); #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; \ @@ -391,8 +392,6 @@ gboolean sgen_resume_thread (SgenThreadInfo *info); 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); @@ -420,7 +419,7 @@ enum { 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, @@ -432,7 +431,6 @@ enum { 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, @@ -612,12 +610,13 @@ void sgen_split_nursery_init (SgenMinorCollector *collector); /* 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; } @@ -653,6 +652,7 @@ typedef struct _SgenMajorCollector SgenMajorCollector; struct _SgenMajorCollector { size_t section_size; gboolean is_concurrent; + gboolean needs_thread_pool; gboolean supports_cardtable; gboolean sweeps_lazily; @@ -673,7 +673,13 @@ struct _SgenMajorCollector { 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); @@ -682,8 +688,9 @@ struct _SgenMajorCollector { 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); @@ -696,13 +703,10 @@ struct _SgenMajorCollector { 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); @@ -959,6 +963,7 @@ typedef struct { 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 */ diff --git a/mono/metadata/sgen-internal.c b/mono/metadata/sgen-internal.c index f5b8995355f..dc484cc2a10 100644 --- a/mono/metadata/sgen-internal.c +++ b/mono/metadata/sgen-internal.c @@ -134,7 +134,7 @@ description_for_type (int type) 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"; @@ -146,7 +146,6 @@ description_for_type (int type) 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"; diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index db91b6773c8..bd2d3bbbbcf 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -43,6 +43,7 @@ #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 @@ -71,6 +72,36 @@ #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; @@ -79,11 +110,12 @@ struct _MSBlockInfo { * 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; @@ -144,16 +176,30 @@ static float evacuation_threshold = 0.666f; 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; @@ -162,14 +208,42 @@ 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; @@ -206,8 +280,7 @@ add_scanned_object (void *ptr) } #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) @@ -246,6 +319,9 @@ update_heap_boundaries_for_block (MSBlockInfo *block) 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) { @@ -327,6 +403,24 @@ ms_free_block (void *block) } 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 @@ -335,16 +429,15 @@ ms_free_block (void *block) 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); @@ -368,14 +461,11 @@ consistency_check (void) 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); @@ -391,11 +481,11 @@ consistency_check (void) 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) { @@ -408,13 +498,24 @@ consistency_check (void) } #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; @@ -437,11 +538,14 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) * 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; @@ -454,12 +558,19 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) /* 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; } @@ -468,36 +579,68 @@ obj_is_from_pinned_alloc (char *ptr) { 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; } @@ -505,7 +648,7 @@ static void* 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]) { @@ -538,23 +681,28 @@ free_object (char *obj, size_t size, gboolean pinned) { 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 @@ -592,17 +740,10 @@ free_pinned_object (char *obj, size_t size) 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; } @@ -640,7 +781,7 @@ major_ptr_is_in_non_pinned_space (char *ptr, char **start) { 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; @@ -654,10 +795,71 @@ major_ptr_is_in_non_pinned_space (char *ptr, char **start) } 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) { @@ -666,7 +868,8 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call 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; @@ -675,14 +878,21 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call 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; @@ -690,7 +900,7 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call if (MS_OBJ_ALLOCED (obj, block)) callback ((char*)obj, block->obj_size, data); } - } END_FOREACH_BLOCK; + } END_FOREACH_BLOCK_NO_LOCK; } static gboolean @@ -698,7 +908,7 @@ major_is_valid_object (char *object) { MSBlockInfo *block; - FOREACH_BLOCK (block) { + FOREACH_BLOCK_NO_LOCK (block) { int idx; char *obj; @@ -710,7 +920,7 @@ major_is_valid_object (char *object) if (obj != object) return FALSE; return MS_OBJ_ALLOCED (obj, block); - } END_FOREACH_BLOCK; + } END_FOREACH_BLOCK_NO_LOCK; return FALSE; } @@ -721,7 +931,7 @@ major_describe_pointer (char *ptr) { MSBlockInfo *block; - FOREACH_BLOCK (block) { + FOREACH_BLOCK_NO_LOCK (block) { int idx; char *obj; gboolean live; @@ -759,7 +969,7 @@ major_describe_pointer (char *ptr) SGEN_LOG (0, " marked %d)\n", marked ? 1 : 0); return vtable; - } END_FOREACH_BLOCK; + } END_FOREACH_BLOCK_NO_LOCK; return NULL; } @@ -780,7 +990,7 @@ major_dump_heap (FILE *heap_dump_file) 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; @@ -789,7 +999,7 @@ major_dump_heap (FILE *heap_dump_file) 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, "\n"); for (i = 0; i < num_block_obj_sizes; ++i) { @@ -798,7 +1008,7 @@ major_dump_heap (FILE *heap_dump_file) } fprintf (heap_dump_file, "\n"); - FOREACH_BLOCK (block) { + FOREACH_BLOCK_NO_LOCK (block) { int count = MS_BLOCK_FREE / block->obj_size; int i; int start = -1; @@ -818,7 +1028,7 @@ major_dump_heap (FILE *heap_dump_file) } fprintf (heap_dump_file, "\n"); - } END_FOREACH_BLOCK; + } END_FOREACH_BLOCK_NO_LOCK; } #define LOAD_VTABLE SGEN_LOAD_VTABLE @@ -866,7 +1076,7 @@ static void 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)); @@ -1045,22 +1255,56 @@ sweep_block_for_size (MSBlockInfo *block, int count, int obj_size) } } +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; @@ -1090,7 +1334,11 @@ sweep_block (MSBlockInfo *block, gboolean during_major_collection) } 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 @@ -1112,105 +1360,237 @@ bitcount (mword d) 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", @@ -1220,22 +1600,43 @@ major_sweep (void) 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; @@ -1343,15 +1744,20 @@ major_finish_nursery_collection (void) #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; @@ -1360,21 +1766,21 @@ major_start_major_collection (void) 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 @@ -1404,12 +1810,16 @@ compare_pointers (const void *va, const void *vb) { } #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 { @@ -1460,7 +1870,7 @@ major_free_swept_blocks (void) 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; /* @@ -1476,7 +1886,7 @@ major_free_swept_blocks (void) 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; @@ -1509,9 +1919,9 @@ major_free_swept_blocks (void) } } - 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; } @@ -1520,7 +1930,7 @@ major_free_swept_blocks (void) 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; } @@ -1563,13 +1973,13 @@ major_pin_objects (SgenGrayQueue *queue) { 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 @@ -1589,23 +1999,42 @@ major_get_used_size (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) { @@ -1624,6 +2053,12 @@ 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; @@ -1636,19 +2071,24 @@ major_print_gc_param_usage (void) "" " 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 @@ -1705,146 +2145,154 @@ card_offset (char *obj, char *base) } 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 @@ -1855,7 +2303,13 @@ major_count_cards (long long *num_total_cards, long long *num_marked_cards) 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; @@ -1867,7 +2321,7 @@ major_count_cards (long long *num_total_cards, long long *num_marked_cards) if (cards [i]) ++marked_cards; } - } END_FOREACH_BLOCK; + } END_FOREACH_BLOCK_NO_LOCK; *num_total_cards = total_cards; *num_marked_cards = marked_cards; @@ -1878,14 +2332,14 @@ update_cardtable_mod_union (void) { 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* @@ -1896,20 +2350,13 @@ major_get_cardtable_mod_union_for_object (char *obj) 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 @@ -1927,6 +2374,10 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr 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; @@ -1936,7 +2387,8 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr } */ - 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); @@ -1957,13 +2409,12 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr 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; @@ -1986,7 +2437,8 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr } 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; @@ -1999,6 +2451,7 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr 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; @@ -2015,7 +2468,6 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr } #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; diff --git a/mono/metadata/sgen-memory-governor.c b/mono/metadata/sgen-memory-governor.c index 63b01840674..70cc6f07883 100644 --- a/mono/metadata/sgen-memory-governor.c +++ b/mono/metadata/sgen-memory-governor.c @@ -29,6 +29,7 @@ #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" @@ -57,18 +58,15 @@ static gboolean debug_print_allowance = FALSE; /* 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); @@ -76,26 +74,16 @@ 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; /* @@ -104,47 +92,55 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite) */ 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 @@ -155,32 +151,22 @@ sgen_memgov_minor_collection_end (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 @@ -214,6 +200,12 @@ log_timming (GGTimingInfo *info) 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) { @@ -224,18 +216,6 @@ 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 */ @@ -356,7 +336,7 @@ gboolean 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; } @@ -372,7 +352,7 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance, 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); @@ -396,7 +376,6 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance, if (save_target) save_target_ratio = save_target; - minor_collection_allowance = MIN_MINOR_COLLECTION_ALLOWANCE; } #endif diff --git a/mono/metadata/sgen-memory-governor.h b/mono/metadata/sgen-memory-governor.h index 16b9ac358a9..0115ec6e060 100644 --- a/mono/metadata/sgen-memory-governor.h +++ b/mono/metadata/sgen-memory-governor.h @@ -34,13 +34,11 @@ void sgen_memgov_minor_collection_start (void); 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); diff --git a/mono/metadata/sgen-os-mach.c b/mono/metadata/sgen-os-mach.c index 7d599e20908..403d04c3d9a 100644 --- a/mono/metadata/sgen-os-mach.c +++ b/mono/metadata/sgen-os-mach.c @@ -31,6 +31,7 @@ #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" @@ -116,7 +117,7 @@ sgen_thread_handshake (BOOL suspend) 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; diff --git a/mono/metadata/sgen-pointer-queue.c b/mono/metadata/sgen-pointer-queue.c index e201e12751b..13cb5ee5413 100644 --- a/mono/metadata/sgen-pointer-queue.c +++ b/mono/metadata/sgen-pointer-queue.c @@ -51,10 +51,16 @@ realloc_queue (SgenPointerQueue *queue) 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; diff --git a/mono/metadata/sgen-pointer-queue.h b/mono/metadata/sgen-pointer-queue.h index 303562e974c..2f8b4cc3874 100644 --- a/mono/metadata/sgen-pointer-queue.h +++ b/mono/metadata/sgen-pointer-queue.h @@ -39,5 +39,6 @@ void sgen_pointer_queue_init (SgenPointerQueue *queue, int mem_type); 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 diff --git a/mono/metadata/sgen-protocol-def.h b/mono/metadata/sgen-protocol-def.h index bd449e10dfc..f9196ffe5b9 100644 --- a/mono/metadata/sgen-protocol-def.h +++ b/mono/metadata/sgen-protocol-def.h @@ -71,6 +71,27 @@ MATCH_INDEX (BINARY_PROTOCOL_MATCH) 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) diff --git a/mono/metadata/sgen-protocol.c b/mono/metadata/sgen-protocol.c index 22f70c30417..bbabb8ee36d 100644 --- a/mono/metadata/sgen-protocol.c +++ b/mono/metadata/sgen-protocol.c @@ -27,6 +27,7 @@ #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" @@ -293,7 +294,7 @@ protocol_entry (unsigned char type, gpointer data, int size) 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 (); diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index b994e0bdf48..9078f6bb07a 100644 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -30,12 +30,15 @@ #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 @@ -216,6 +219,8 @@ sgen_stop_world (int generation) 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 ()); @@ -240,6 +245,8 @@ sgen_stop_world (int generation) 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 (); @@ -271,6 +278,8 @@ sgen_restart_world (int generation, GGTimingInfo *timing) 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 ()) @@ -305,6 +314,9 @@ sgen_restart_world (int generation, GGTimingInfo *timing) 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); @@ -340,6 +352,12 @@ sgen_restart_world (int generation, GGTimingInfo *timing) return count; } +gboolean +sgen_is_world_stopped (void) +{ + return world_is_stopped; +} + void sgen_init_stw (void) { @@ -380,7 +398,7 @@ sgen_is_thread_in_current_stw (SgenThreadInfo *info) 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; } diff --git a/mono/metadata/sgen-tagged-pointer.h b/mono/metadata/sgen-tagged-pointer.h index 3d63e94bfcd..2d55abbbcc1 100644 --- a/mono/metadata/sgen-tagged-pointer.h +++ b/mono/metadata/sgen-tagged-pointer.h @@ -37,6 +37,7 @@ #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) diff --git a/mono/metadata/sgen-thread-pool.c b/mono/metadata/sgen-thread-pool.c new file mode 100644 index 00000000000..71d8d70742a --- /dev/null +++ b/mono/metadata/sgen-thread-pool.c @@ -0,0 +1,245 @@ +/* + * 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 diff --git a/mono/metadata/sgen-thread-pool.h b/mono/metadata/sgen-thread-pool.h new file mode 100644 index 00000000000..e0673f04a7b --- /dev/null +++ b/mono/metadata/sgen-thread-pool.h @@ -0,0 +1,54 @@ +/* + * 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 diff --git a/mono/metadata/sgen-workers.c b/mono/metadata/sgen-workers.c index 9920845e468..1c68dfc5212 100644 --- a/mono/metadata/sgen-workers.c +++ b/mono/metadata/sgen-workers.c @@ -24,196 +24,108 @@ #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 @@ -223,117 +135,45 @@ collection_needs_workers (void) } 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 @@ -373,66 +213,59 @@ init_private_gray_queue (WorkerData *data) 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; } @@ -440,19 +273,21 @@ init_distribute_gray_queue (gboolean locked) 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); @@ -461,111 +296,39 @@ sgen_workers_init (int 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, @@ -573,20 +336,14 @@ sgen_workers_join (void) * 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)); @@ -595,29 +352,20 @@ sgen_workers_join (void) 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* @@ -626,10 +374,4 @@ sgen_workers_get_distribute_section_gray_queue (void) 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 diff --git a/mono/metadata/sgen-workers.h b/mono/metadata/sgen-workers.h index 5c509de6128..7211b6551d9 100644 --- a/mono/metadata/sgen-workers.h +++ b/mono/metadata/sgen-workers.h @@ -21,38 +21,25 @@ #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); diff --git a/mono/metadata/socket-io.c b/mono/metadata/socket-io.c index a3c2ac0c336..a84fcd771a1 100644 --- a/mono/metadata/socket-io.c +++ b/mono/metadata/socket-io.c @@ -633,8 +633,8 @@ static gint32 get_family_hint(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); @@ -1406,7 +1406,7 @@ gint32 ves_icall_System_Net_Sockets_Socket_Receive_array_internal(SOCKET sock, M 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; @@ -1573,7 +1573,7 @@ static SOCKET Socket_to_SOCKET(MonoObject *sockobj) 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) @@ -2198,7 +2198,7 @@ void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock, } 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) { @@ -2467,7 +2467,7 @@ extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_ } 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; diff --git a/mono/metadata/socket-io.h b/mono/metadata/socket-io.h index 3f2dd85a5ad..6eda7248c61 100644 --- a/mono/metadata/socket-io.h +++ b/mono/metadata/socket-io.h @@ -204,7 +204,7 @@ extern void ves_icall_System_Net_Sockets_Socket_Bind_internal(SOCKET sock, MonoO 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); @@ -213,13 +213,13 @@ extern void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock, g 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); diff --git a/mono/metadata/threadpool-ms-io.c b/mono/metadata/threadpool-ms-io.c index 5bc9830d515..772a2fe5c6c 100644 --- a/mono/metadata/threadpool-ms-io.c +++ b/mono/metadata/threadpool-ms-io.c @@ -259,7 +259,7 @@ epoll_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 @@ -1062,43 +1062,39 @@ ensure_cleanedup (void) 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; @@ -1237,17 +1233,16 @@ mono_threadpool_ms_io_remove_domain_jobs (MonoDomain *domain) 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); diff --git a/mono/metadata/threadpool-ms.c b/mono/metadata/threadpool-ms.c index 529f46e5911..7f45061e935 100644 --- a/mono/metadata/threadpool-ms.c +++ b/mono/metadata/threadpool-ms.c @@ -21,16 +21,15 @@ #include #include +#include +#include -#ifdef PLATFORM_ANDROID +#if !defined (HAVE_COMPLEX_H) #include <../../support/libm/complex.h> #else #include #endif -#include -#include - #include #include #include @@ -1521,3 +1520,24 @@ ves_icall_System_Threading_Microsoft_ThreadPool_RequestWorkerThread (void) { 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; +} diff --git a/mono/metadata/threadpool-ms.h b/mono/metadata/threadpool-ms.h index cac0ce7c5d5..4b91cd85449 100644 --- a/mono/metadata/threadpool-ms.h +++ b/mono/metadata/threadpool-ms.h @@ -78,26 +78,14 @@ ves_icall_System_Threading_Microsoft_ThreadPool_ReportThreadStatus (gboolean is_ 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 */ diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index c32a0700a72..3de93ca49e2 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -213,16 +213,6 @@ is_corlib_type (MonoDomain *domain, MonoClass *klass) 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; \ @@ -235,8 +225,6 @@ is_socket_type (MonoDomain *domain, MonoClass *klass) #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 @@ -245,26 +233,18 @@ is_corlib_asyncresult (MonoDomain *domain, MonoClass *klass) 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 diff --git a/mono/mini/README b/mono/mini/README deleted file mode 100644 index 7a64e0aae0e..00000000000 --- a/mono/mini/README +++ /dev/null @@ -1 +0,0 @@ -Mini is the new JIT compiler for Mono. diff --git a/mono/mini/TODO b/mono/mini/TODO deleted file mode 100644 index d214318c813..00000000000 --- a/mono/mini/TODO +++ /dev/null @@ -1,77 +0,0 @@ -* 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. - - diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 3e57a1c1f74..dab91d79442 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -137,7 +137,7 @@ typedef struct MonoAotOptions { 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]; @@ -2505,6 +2505,19 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui 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); @@ -3093,6 +3106,8 @@ static MonoPltEntry* 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; @@ -3108,6 +3123,7 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info) * wrapper. */ res = NULL; + synchronized = TRUE; } if (!res) { @@ -3121,6 +3137,13 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info) 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 @@ -5261,6 +5284,10 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint 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 (); @@ -7890,7 +7917,7 @@ emit_exception_info (MonoAotCompile *acfg) // 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); @@ -9175,7 +9202,8 @@ int 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]; @@ -9235,7 +9263,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) 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"); @@ -9562,14 +9590,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) 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, diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index c4047274cbf..4fa4c6dcef8 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -469,6 +469,7 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf) 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); @@ -492,6 +493,15 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf) } } 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); @@ -507,6 +517,8 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf) // 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 @@ -860,7 +872,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod 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: @@ -3422,6 +3437,17 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin 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 (); diff --git a/mono/mini/cpu-s390x.md b/mono/mini/cpu-s390x.md index bc1a513d40b..091c6b1103d 100644 --- a/mono/mini/cpu-s390x.md +++ b/mono/mini/cpu-s390x.md @@ -132,9 +132,9 @@ float_rem_un: dest:f src1:f src2:f len:16 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 diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index fbc149244f0..6e07d05e5da 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -1032,7 +1032,7 @@ mono_debugger_agent_init (void) 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. */ @@ -2309,7 +2309,7 @@ decode_ptr_id (guint8 *buf, guint8 **endbuf, guint8 *limit, IdType type, MonoDom 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; } @@ -5324,6 +5324,18 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI 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) { diff --git a/mono/mini/exceptions-mips.c b/mono/mini/exceptions-mips.c index 8ab97bf5a30..f0158e5b7a9 100644 --- a/mono/mini/exceptions-mips.c +++ b/mono/mini/exceptions-mips.c @@ -77,6 +77,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) 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; } @@ -168,6 +169,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) 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; } @@ -281,6 +283,7 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboo 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; } @@ -348,6 +351,7 @@ mono_arch_get_throw_exception_by_name (void) 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; } diff --git a/mono/mini/exceptions-ppc.c b/mono/mini/exceptions-ppc.c index aa0b3f778cc..4b8d1642c16 100644 --- a/mono/mini/exceptions-ppc.c +++ b/mono/mini/exceptions-ppc.c @@ -218,6 +218,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) 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); @@ -306,6 +307,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) 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); @@ -434,6 +436,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli 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); diff --git a/mono/mini/exceptions-s390x.c b/mono/mini/exceptions-s390x.c index 9c2cfc932d5..78fd645c785 100644 --- a/mono/mini/exceptions-s390x.c +++ b/mono/mini/exceptions-s390x.c @@ -210,6 +210,9 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) 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, @@ -357,6 +360,9 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, 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" diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index bfd42414e0b..03e7aec44a0 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -109,6 +109,9 @@ mono_win32_get_handle_stackoverflow (void) /* 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; } @@ -354,6 +357,9 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) 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; } @@ -431,6 +437,9 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) 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; } @@ -653,6 +662,9 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea 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; } @@ -943,6 +955,9 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot) 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; } diff --git a/mono/mini/generics.cs b/mono/mini/generics.cs index 98b743b0132..4cc033d59a6 100644 --- a/mono/mini/generics.cs +++ b/mono/mini/generics.cs @@ -1140,6 +1140,56 @@ class Tests MyClass.foo (); return 0; } + + enum AnEnum { + A, + B + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static string constrained_tostring (T t) { + return t.ToString (); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static bool constrained_equals (T t1, T t2) { + var c = EqualityComparer.Default; + + return c.Equals (t1, t2); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static int constrained_gethashcode (T t) { + return t.GetHashCode (); + } + + public static int test_0_constrained_partial_sharing () { + string s; + + s = constrained_tostring (5); + if (s != "5") + return 1; + s = constrained_tostring (AnEnum.B); + if (s != "B") + return 2; + + if (!constrained_equals (1, 1)) + return 3; + if (constrained_equals (1, 2)) + return 4; + if (!constrained_equals (AnEnum.A, AnEnum.A)) + return 5; + if (constrained_equals (AnEnum.A, AnEnum.B)) + return 6; + + int i = constrained_gethashcode (5); + if (i != 5) + return 7; + i = constrained_gethashcode (AnEnum.B); + if (i != 1) + return 8; + return 0; + } } #if !MOBILE diff --git a/mono/mini/ir-emit.h b/mono/mini/ir-emit.h index 67d073448d3..fe05ecca2d3 100644 --- a/mono/mini/ir-emit.h +++ b/mono/mini/ir-emit.h @@ -408,7 +408,7 @@ handle_gsharedvt_ldaddr (MonoCompile *cfg) } 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) diff --git a/mono/mini/liveness.c b/mono/mini/liveness.c index 85b6ba04001..a3bd43d3a41 100644 --- a/mono/mini/liveness.c +++ b/mono/mini/liveness.c @@ -812,7 +812,7 @@ update_liveness2 (MonoCompile *cfg, MonoInst *ins, gboolean set_volatile, int in } 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; diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index e5310e2544a..6bce61df376 100755 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -407,7 +407,7 @@ static MONO_NEVER_INLINE void 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); } @@ -2990,7 +2990,7 @@ direct_icalls_enabled (MonoCompile *cfg) 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; } @@ -3506,6 +3506,28 @@ emit_get_rgctx_gsharedvt_call (MonoCompile *cfg, int context_used, 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, @@ -7790,16 +7812,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b 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; @@ -8841,6 +8860,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b gboolean skip_ret = FALSE; gboolean delegate_invoke = FALSE; gboolean direct_icall = FALSE; + gboolean constrained_partial_call = FALSE; MonoMethod *cil_method; CHECK_OPSIZE (5); @@ -8855,10 +8875,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b 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; } } @@ -8998,7 +9016,69 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* * 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 @@ -13065,7 +13145,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } /* 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); diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index cd1070c42f0..f43fe603302 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -52,7 +52,7 @@ static gboolean optimize_for_xen = TRUE; #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 @@ -526,7 +526,7 @@ typedef struct { #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 }; @@ -554,7 +554,7 @@ add_general (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo) } } -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 #define FLOAT_PARAM_REGS 4 #else #define FLOAT_PARAM_REGS 8 @@ -618,7 +618,7 @@ merge_argument_class_from_type (MonoGenericSharingContext *gsctx, MonoType *type break; case MONO_TYPE_R4: case MONO_TYPE_R8: -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 class2 = ARG_CLASS_INTEGER; #else class2 = ARG_CLASS_SSE; @@ -751,7 +751,7 @@ add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgIn 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)) { @@ -833,7 +833,7 @@ add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgIn 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); @@ -1006,7 +1006,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign 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 @@ -1115,7 +1115,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign 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; @@ -1540,7 +1540,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) #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 @@ -2008,7 +2008,7 @@ mono_arch_create_vars (MonoCompile *cfg) } } - if (cfg->gen_seq_points_debug_data) { + if (cfg->gen_sdb_seq_points) { MonoInst *ins; if (cfg->compile_aot) { @@ -2031,7 +2031,7 @@ mono_arch_create_vars (MonoCompile *cfg) 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 @@ -3002,12 +3002,12 @@ emit_call_body (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointe 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 @@ -3347,7 +3347,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) 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) @@ -3591,7 +3591,7 @@ mono_amd64_get_tls_gs_offset (void) 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); @@ -3657,7 +3657,7 @@ emit_tls_get_reg (guint8* code, int dreg, int offset_reg) 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); @@ -3674,7 +3674,7 @@ static guint8* 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); @@ -6774,7 +6774,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) 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 */ @@ -6783,7 +6783,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) 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 } @@ -6824,7 +6824,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* 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*/ @@ -6844,7 +6844,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) 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 @@ -6859,7 +6859,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) 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 @@ -7213,7 +7213,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) } } - 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 */ @@ -7953,7 +7953,7 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod /* 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 diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 1b48c14caa6..92917877e2a 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -213,7 +213,7 @@ typedef struct MonoCompileArch { -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 #define PARAM_REGS 4 #else #define PARAM_REGS 6 @@ -287,7 +287,7 @@ typedef struct { #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 @@ -410,7 +410,7 @@ typedef struct { 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 ); diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 3a12ed0329f..4ed7342572c 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -2154,7 +2154,7 @@ mono_arch_create_vars (MonoCompile *cfg) } } - 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; diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 276df0f69d6..52ffc899a7d 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -2656,7 +2656,9 @@ mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx) 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"); diff --git a/mono/mini/mini-generic-sharing.c b/mono/mini/mini-generic-sharing.c index 4a0947fc2b5..a780e2b40bc 100644 --- a/mono/mini/mini-generic-sharing.c +++ b/mono/mini/mini-generic-sharing.c @@ -15,8 +15,8 @@ #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__ @@ -662,7 +662,25 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co 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 (); } @@ -1262,6 +1280,57 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti 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)); @@ -1548,6 +1617,8 @@ mono_rgctx_info_type_to_str (MonoRgctxInfoType type) 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 ""; } @@ -1643,6 +1714,13 @@ info_equal (gpointer data1, gpointer data2, MonoRgctxInfoType 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 (); } diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index faf1de75321..277e2296ac9 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -1106,6 +1106,8 @@ emit_volatile_load (EmitContext *ctx, int vreg) */ 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 (), ""); } @@ -2573,11 +2575,6 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder * 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, @@ -2697,6 +2694,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) } emit_handler_start (ctx, bb, builder); + CHECK_FAILURE (ctx); builder = ctx->builder; } diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index bd8605a5fa8..c0943117994 100755 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -1107,6 +1107,16 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info) //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; } @@ -1179,6 +1189,11 @@ mono_patch_info_hash (gconstpointer data) 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"); @@ -1236,6 +1251,8 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb) 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; @@ -1573,6 +1590,15 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, 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; @@ -2663,7 +2689,7 @@ mini_parse_debug_options (void) 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")) diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 51d7e12dca0..7dc0b105666 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -1879,12 +1879,12 @@ mini_get_single_step_trampoline (void) 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 @@ -1911,12 +1911,12 @@ mini_get_breakpoint_trampoline (void) 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 diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 7b36bf8d457..1a0ac0139df 100755 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -2412,7 +2412,7 @@ mono_codegen (MonoCompile *cfg) 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); } @@ -2464,7 +2464,7 @@ mono_codegen (MonoCompile *cfg) #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); @@ -3119,8 +3119,16 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl 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; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index eb4a5f102ac..d195176c84c 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -105,7 +105,7 @@ #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)) @@ -1122,6 +1122,14 @@ typedef enum { /* The address of Nullable.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 { @@ -1215,6 +1223,17 @@ typedef struct MonoJumpInfoImtTramp { 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; @@ -1251,10 +1270,16 @@ struct MonoJumpInfo { 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; @@ -1517,7 +1542,7 @@ typedef struct { 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; @@ -1540,6 +1565,8 @@ typedef struct { 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; @@ -1883,7 +1910,7 @@ typedef struct { * 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; /* diff --git a/mono/mini/mini.prj b/mono/mini/mini.prj deleted file mode 100644 index b9bd7c25f61..00000000000 --- a/mono/mini/mini.prj +++ /dev/null @@ -1,28 +0,0 @@ -;; -*- 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) diff --git a/mono/mini/patch-info.h b/mono/mini/patch-info.h index 063ebe7c7c1..f2cd3c7d4f7 100644 --- a/mono/mini/patch-info.h +++ b/mono/mini/patch-info.h @@ -54,4 +54,5 @@ PATCH_INFO(OBJC_SELECTOR_REF, "objc_selector_ref") 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") diff --git a/mono/mini/seq-points.c b/mono/mini/seq-points.c index 26ac63986a3..c0dcd6da7da 100644 --- a/mono/mini/seq-points.c +++ b/mono/mini/seq-points.c @@ -49,7 +49,7 @@ mono_save_seq_point_info (MonoCompile *cfg) 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; diff --git a/mono/mini/simd-intrinsics.c b/mono/mini/simd-intrinsics.c index bf1e37d31b1..0f484a98758 100644 --- a/mono/mini/simd-intrinsics.c +++ b/mono/mini/simd-intrinsics.c @@ -61,7 +61,16 @@ The advantage of this change is that it could have a _membase version and promot 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) @@ -1673,4 +1682,5 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign return NULL; } -#endif +#endif /* DISABLE_JIT */ +#endif /* MONO_ARCH_SIMD_INTRINSICS */ diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index 6e95ad6e5d5..17bf3ad8962 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -68,16 +68,11 @@ static int map_hw_reg_to_dwarf_reg [] = { 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) diff --git a/mono/profiler/Makefile.am b/mono/profiler/Makefile.am index 63c62f015b2..115232490c3 100644 --- a/mono/profiler/Makefile.am +++ b/mono/profiler/Makefile.am @@ -18,11 +18,10 @@ if HAVE_VTUNE 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 @@ -56,12 +55,8 @@ else 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 @@ -96,5 +91,5 @@ else 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 diff --git a/mono/profiler/log-profiler.txt b/mono/profiler/log-profiler.txt deleted file mode 100644 index 10140c6b3bb..00000000000 --- a/mono/profiler/log-profiler.txt +++ /dev/null @@ -1,411 +0,0 @@ -# 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 -` - diff --git a/mono/profiler/mono-cov.c b/mono/profiler/mono-cov.c deleted file mode 100644 index 9860dd8ee1d..00000000000 --- a/mono/profiler/mono-cov.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * mono-co.c: Coverage profiler - * - - * Copyright 2008-2009 Novell, Inc (http://www.novell.com) - */ -#include -#include -#include -#include -#include -#include -#include - -/* - * 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); -} - - diff --git a/mono/profiler/mono-profiler-logging.c b/mono/profiler/mono-profiler-logging.c deleted file mode 100644 index 194bc9368d8..00000000000 --- a/mono/profiler/mono-profiler-logging.c +++ /dev/null @@ -1,5883 +0,0 @@ -/* - * mono-profiler-logging.c: Logging profiler for Mono. - * - * Author: - * Massimiliano Mantione (massi@ximian.com) - * - * Copyright 2008-2009 Novell, Inc (http://www.novell.com) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define HAS_OPROFILE 0 - -#if (HAS_OPROFILE) -#include -#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<>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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#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 - -#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 = ""; - } - - 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;\ -} 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)) : "", - (event->data.address != NULL) ? mono_class_get_name (mono_method_get_class ((MonoMethod*) event->data.address)) : "", - (event->data.address != NULL) ? mono_method_get_name ((MonoMethod*) event->data.address) : ""); - } 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); -} - diff --git a/mono/profiler/proflog.h b/mono/profiler/proflog.h index 3ea6a8d2382..ea3b267dab3 100644 --- a/mono/profiler/proflog.h +++ b/mono/profiler/proflog.h @@ -5,7 +5,7 @@ #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 @@ -14,6 +14,7 @@ * 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 { diff --git a/mono/utils/mono-codeman.c b/mono/utils/mono-codeman.c index 5c2a83b1189..08b8226f61b 100644 --- a/mono/utils/mono-codeman.c +++ b/mono/utils/mono-codeman.c @@ -96,6 +96,7 @@ struct _CodeChunck { struct _MonoCodeManager { int dynamic; int read_only; + int bind_size; CodeChunk *current; CodeChunk *full; CodeChunk *last; @@ -365,14 +366,17 @@ mono_code_manager_new (void) * 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; } @@ -492,11 +496,11 @@ mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void #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; @@ -529,15 +533,25 @@ new_codechunk (CodeChunk *last, int dynamic, int size) } } #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 @@ -616,7 +630,7 @@ mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment) } 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; @@ -649,7 +663,7 @@ mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment) 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; diff --git a/mono/utils/mono-codeman.h b/mono/utils/mono-codeman.h index 17d53b3b032..fb3e5ea6803 100644 --- a/mono/utils/mono-codeman.h +++ b/mono/utils/mono-codeman.h @@ -6,7 +6,7 @@ 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); diff --git a/mono/utils/mono-filemap.c b/mono/utils/mono-filemap.c index 36c7fd6df93..895e7e7355d 100644 --- a/mono/utils/mono-filemap.c +++ b/mono/utils/mono-filemap.c @@ -35,7 +35,10 @@ mono_file_map_open (const char* name) 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 } @@ -43,7 +46,7 @@ guint64 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; } @@ -51,13 +54,21 @@ mono_file_map_size (MonoFileMap *fmap) 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) diff --git a/mono/utils/mono-proclib.c b/mono/utils/mono-proclib.c index 38dea0d5111..de6dd666c48 100644 --- a/mono/utils/mono-proclib.c +++ b/mono/utils/mono-proclib.c @@ -207,57 +207,67 @@ get_pid_status_item_buf (int pid, const char *item, char *rbuf, int blen, MonoPr 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]; @@ -282,11 +292,42 @@ mono_process_get_name (gpointer pid, char *buf, int len) #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 */ @@ -521,7 +562,7 @@ mono_process_get_data_with_error (gpointer pid, MonoProcessData data, MonoProces 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: @@ -581,8 +622,8 @@ mono_cpu_count (void) 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 diff --git a/mono/utils/mono-proclib.h b/mono/utils/mono-proclib.h index 48144a00613..67db3f3f317 100644 --- a/mono/utils/mono-proclib.h +++ b/mono/utils/mono-proclib.h @@ -58,6 +58,8 @@ struct _MonoCpuUsageState { 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); diff --git a/mono/utils/mono-time.c b/mono/utils/mono-time.c index cd347546c20..3c940e73ddf 100644 --- a/mono/utils/mono-time.c +++ b/mono/utils/mono-time.c @@ -4,10 +4,17 @@ * Copyright (C) 2008 Novell, Inc. */ -#include +#include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include + + #define MTICKS_PER_SEC 10000000 #ifdef HOST_WIN32 @@ -56,9 +63,6 @@ mono_100ns_datetime (void) #else -#ifdef HAVE_SYS_TIME_H -#include -#endif #if defined (HAVE_SYS_PARAM_H) #include @@ -168,9 +172,15 @@ mono_100ns_datetime (void) { 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 diff --git a/mono/utils/mono-time.h b/mono/utils/mono-time.h index 6961306c290..95bda8e5309 100644 --- a/mono/utils/mono-time.h +++ b/mono/utils/mono-time.h @@ -4,15 +4,23 @@ #include #include +#ifdef HAVE_SYS_TIME_H +#include +#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; diff --git a/notes/cil b/notes/cil deleted file mode 100644 index 458aca543ba..00000000000 --- a/notes/cil +++ /dev/null @@ -1,13 +0,0 @@ -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. - diff --git a/runtime/Makefile.am b/runtime/Makefile.am index b021efeec4d..415c21b1cb3 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -34,7 +34,7 @@ else 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 @@ -108,11 +108,11 @@ 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 \ diff --git a/samples/profiler/sample.c b/samples/profiler/sample.c index 49af781a55a..45c46da07d9 100644 --- a/samples/profiler/sample.c +++ b/samples/profiler/sample.c @@ -2,10 +2,15 @@ /* * 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 { diff --git a/scripts/mono-find-provides.in b/scripts/mono-find-provides.in index c9210060c26..155690d75ad 100644 --- a/scripts/mono-find-provides.in +++ b/scripts/mono-find-provides.in @@ -33,7 +33,7 @@ fi # 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 ' diff --git a/scripts/mono-find-requires.in b/scripts/mono-find-requires.in index f0ad60bb8a2..d7b6a325bc3 100644 --- a/scripts/mono-find-requires.in +++ b/scripts/mono-find-requires.in @@ -50,7 +50,7 @@ esac # 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 diff --git a/support/zlib-helper.c b/support/zlib-helper.c index 83455413b36..38696260a09 100644 --- a/support/zlib-helper.c +++ b/support/zlib-helper.c @@ -90,6 +90,8 @@ CreateZStream (gint compress, guchar gzip, read_write_func func, void *gchandle) 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; } @@ -148,7 +150,7 @@ flush_internal (ZStream *stream, gboolean is_final) 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;