Merge pull request #2831 from razzfazz/fix_dllimport
[mono.git] / mcs / class / System / System.IO / KeventWatcher.cs
index 27f61b35d0ea775478f504f0b288e67620fa7559..8078964da30ea9f5e252b24e710e5131ea7de5b5 100644 (file)
@@ -150,7 +150,7 @@ namespace System.IO {
        [StructLayout(LayoutKind.Sequential)]
        struct timespec {
                public IntPtr tv_sec;
-               public IntPtr tv_usec;
+               public IntPtr tv_nsec;
        }
 
        class PathData
@@ -162,6 +162,8 @@ namespace System.IO {
 
        class KqueueMonitor : IDisposable
        {
+               static bool initialized;
+               
                public int Connection
                {
                        get { return conn; }
@@ -171,6 +173,13 @@ namespace System.IO {
                {
                        this.fsw = fsw;
                        this.conn = -1;
+                       if (!initialized){
+                               int t;
+                               initialized = true;
+                               var maxenv = Environment.GetEnvironmentVariable ("MONO_DARWIN_WATCHER_MAXFDS");
+                               if (maxenv != null && Int32.TryParse (maxenv, out t))
+                                       maxFds = t;
+                       }
                }
 
                public void Dispose ()
@@ -304,7 +313,7 @@ namespace System.IO {
 
                        Scan (fullPathNoLastSlash, false, ref initialFds);
 
-                       var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 };
+                       var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_nsec = (IntPtr)0 };
                        var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point
                        var changes = CreateChangeList (ref initialFds);
 
@@ -355,7 +364,21 @@ namespace System.IO {
                        while (!requestStop) {
                                var changes = CreateChangeList (ref newFds);
 
-                               int numEvents = kevent_notimeout (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, IntPtr.Zero);
+                               // We are calling an icall, so have to marshal manually
+                               // Marshal in
+                               int ksize = Marshal.SizeOf<kevent> ();
+                               var changesNative = Marshal.AllocHGlobal (ksize * changes.Length);
+                               for (int i = 0; i < changes.Length; ++i)
+                                       Marshal.StructureToPtr (changes [i], changesNative + (i * ksize), false);
+                               var eventBufferNative = Marshal.AllocHGlobal (ksize * eventBuffer.Length);
+
+                               int numEvents = kevent_notimeout (ref conn, changesNative, changes.Length, eventBufferNative, eventBuffer.Length);
+
+                               // Marshal out
+                               Marshal.FreeHGlobal (changesNative);
+                               for (int i = 0; i < numEvents; ++i)
+                                       eventBuffer [i] = Marshal.PtrToStructure<kevent> (eventBufferNative + (i * ksize));
+                               Marshal.FreeHGlobal (eventBufferNative);
 
                                if (numEvents == -1) {
                                        // Stop () signals us to stop by closing the connection
@@ -367,7 +390,6 @@ namespace System.IO {
 
                                        continue;
                                }
-
                                retries = 0;
 
                                for (var i = 0; i < numEvents; i++) {
@@ -625,7 +647,7 @@ namespace System.IO {
                const int F_GETPATH = 50;
                const int __DARWIN_MAXPATHLEN = 1024;
                static readonly kevent[] emptyEventList = new System.IO.kevent[0];
-               const int maxFds = 200;
+               int maxFds = Int32.MaxValue;
 
                FileSystemWatcher fsw;
                int conn;
@@ -643,23 +665,23 @@ namespace System.IO {
                string fixupPath = null;
                string fullPathNoLastSlash = null;
 
-               [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)]
+               [DllImport ("libc", CharSet=CharSet.Auto, SetLastError=true)]
                static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb);
 
-               [DllImport ("libc")]
+               [DllImport ("libc", SetLastError=true)]
                extern static int open (string path, int flags, int mode_t);
 
                [DllImport ("libc")]
                extern static int close (int fd);
 
-               [DllImport ("libc")]
+               [DllImport ("libc", SetLastError=true)]
                extern static int kqueue ();
 
-               [DllImport ("libc")]
+               [DllImport ("libc", SetLastError=true)]
                extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time);
 
-               [DllImport ("libc", EntryPoint="kevent")]
-               extern static int kevent_notimeout (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr ptr);
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static int kevent_notimeout (ref int kq, IntPtr ev, int nchanges, IntPtr evtlist, int nevents);
        }
 
        class KeventWatcher : IFileWatcher