[Wine-patches] [PATCH 1/4] Get time from server.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Вт Апр 7 16:54:15 MSD 2009


---
 dlls/ntdll/loader.c     |    8 ++++++-
 dlls/ntdll/ntdll_misc.h |    4 +++
 dlls/ntdll/time.c       |   51 ++++++++++++++++++++++++++++++++++++++++++++++
 server/fd.c             |   52 ++++++++++++++++++++++++++++++++++++++++++++++-
 server/object.h         |    5 ++++
 server/request.c        |    1 +
 server/signal.c         |    1 +
 7 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index c6e1cea..fa474f8 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2609,7 +2609,13 @@ NTSTATUS WINAPI NtUnloadDriver( const UNICODE_STRING *DriverServiceName )
  */
 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
 {
-    if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
+    if (reason == DLL_PROCESS_ATTACH)
+    {
+        LdrDisableThreadCalloutsForDll( inst );
+        map_shared_time();
+    }
+    if (reason == DLL_PROCESS_DETACH)
+        unmap_shared_time();
     return TRUE;
 }
 
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 7fc48f9..1205c22 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -162,6 +162,10 @@ extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst,
 extern int CDECL NTDLL__vsnprintf( char *str, SIZE_T len, const char *format, __ms_va_list args );
 extern int CDECL NTDLL__vsnwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, __ms_va_list args );
 
+/* shared time */
+extern void map_shared_time(void);
+extern void unmap_shared_time(void);
+
 /* load order */
 
 enum loadorder
diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c
index e6e4ed2..90cf7e0 100644
--- a/dlls/ntdll/time.c
+++ b/dlls/ntdll/time.c
@@ -38,6 +38,9 @@
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
 
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
@@ -45,6 +48,7 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winternl.h"
+#include "wine/library.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
 #include "ntdll_misc.h"
@@ -95,6 +99,11 @@ static const int MonthLengths[2][MONSPERYEAR] =
 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
 };
 
+#ifdef HAVE_SYS_MMAN_H
+static timeout_t *server_time = MAP_FAILED;
+static int time_fd = -1;
+#endif
+
 static inline int IsLeapYear(int Year)
 {
 	return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
@@ -432,6 +441,41 @@ void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS
     TimeFields->Hour = rem / 60;
 }
 
+#ifdef HAVE_MMAP
+
+void map_shared_time(void)
+{
+    char *name;
+
+    name = RtlAllocateHeap( GetProcessHeap(), 0, strlen(wine_get_server_dir()) + 6 );
+    if (name == NULL) return;
+    strcpy( name, wine_get_server_dir() );
+    strcat( name, "/time" );
+    time_fd = open( name, O_RDWR );
+    RtlFreeHeap( GetProcessHeap(), 0, name );
+    if (time_fd < 0) return;
+    server_time = mmap( NULL, sizeof(*server_time), PROT_READ|PROT_WRITE,
+                        MAP_SHARED, time_fd, 0 );
+}
+
+void unmap_shared_time(void)
+{
+    munmap( server_time, sizeof(*server_time) );
+    close( time_fd );
+}
+
+#else
+
+void map_shared_time(void)
+{
+}
+
+void unmap_shared_time(void)
+{
+}
+
+#endif  /* HAVE_MMAP */
+
 /***********************************************************************
  *       NtQuerySystemTime [NTDLL.@]
  *       ZwQuerySystemTime [NTDLL.@]
@@ -449,6 +493,13 @@ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
 {
     struct timeval now;
 
+#ifdef HAVE_SYS_MMAN_H
+    if (server_time != MAP_FAILED)
+    {
+        Time->QuadPart = interlocked_cmpxchg64( server_time, 0, 0 );
+        return STATUS_SUCCESS;
+    }
+#endif
     gettimeofday( &now, 0 );
     Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
     Time->QuadPart += now.tv_usec * 10;
diff --git a/server/fd.c b/server/fd.c
index 1aa53b3..2b77106 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -97,6 +97,9 @@ inline void dummy_trace(void *f, ...) { }
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -375,6 +378,10 @@ struct timeout_user
     void                 *private;    /* callback private data */
 };
 
+#ifdef HAVE_SYS_MMAN_H
+static int time_fd;
+static timeout_t *shared_time = MAP_FAILED;
+#endif
 static struct list timeout_list = LIST_INIT(timeout_list);   /* sorted timeouts list */
 timeout_t current_time;
 
@@ -384,6 +391,15 @@ static inline void set_current_time(void)
     struct timeval now;
     gettimeofday( &now, NULL );
     current_time = (timeout_t)now.tv_sec * TICKS_PER_SEC + now.tv_usec * 10 + ticks_1601_to_1970;
+#ifdef HAVE_SYS_MMAN_H
+    if (shared_time != MAP_FAILED)
+    {
+        timeout_t old_time = current_time;
+        do {
+            old_time = interlocked_cmpxchg64( shared_time, current_time, old_time );
+        } while (current_time != old_time);
+    }
+#endif
 }
 
 /* add a timeout user */
@@ -754,6 +770,7 @@ static void remove_poll_user( struct fd *fd, int user )
 }
 
 /* process pending timeouts and return the time until the next timeout, in milliseconds */
+/* returned time not greater than 10 ms for updating *shared_time */
 static int get_next_timeout(void)
 {
     if (!list_empty( &timeout_list ))
@@ -790,17 +807,50 @@ static int get_next_timeout(void)
             struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
             int diff = (timeout->when - current_time + 9999) / 10000;
             if (diff < 0) diff = 0;
+            if (diff > 10) diff = 10;
             return diff;
         }
     }
-    return -1;  /* no pending timeouts */
+    return 10;  /* no pending timeouts */
+}
+
+#ifdef HAVE_MMAP
+
+void create_time_mapping(void)
+{
+    time_fd = open( "time", O_RDWR|O_CREAT|O_EXCL, 0600 );
+    if (time_fd < 0) return;
+    write( time_fd, &current_time, sizeof(current_time) );
+    shared_time = mmap( NULL, sizeof(*shared_time), PROT_READ | PROT_WRITE,
+            MAP_SHARED, time_fd, 0 );
+}
+
+void destroy_time_mapping(void)
+{
+    munmap( shared_time, sizeof(*shared_time) );
+    close( time_fd );
+    unlink( "time" );
+}
+
+#else
+
+void create_time_mapping(void)
+{
 }
 
+void destroy_time_mapping(void)
+{
+}
+
+#endif  /* HAVE_MMAP */
+
 /* server main poll() loop */
 void main_loop(void)
 {
     int i, ret, timeout;
 
+    create_time_mapping();
+
     set_current_time();
     server_start_time = current_time;
 
diff --git a/server/object.h b/server/object.h
index a5d0ffd..4f55cab 100644
--- a/server/object.h
+++ b/server/object.h
@@ -223,6 +223,11 @@ extern struct symlink *create_symlink( struct directory *root, const struct unic
 extern void create_named_pipe_device( struct directory *root, const struct unicode_str *name );
 extern void create_mailslot_device( struct directory *root, const struct unicode_str *name );
 
+/* shared time */
+
+extern void create_time_mapping(void);
+extern void destroy_time_mapping(void);
+
 /* global variables */
 
   /* command-line options */
diff --git a/server/request.c b/server/request.c
index d2aebb3..4dd6aea 100644
--- a/server/request.c
+++ b/server/request.c
@@ -812,6 +812,7 @@ static void close_socket_timeout( void *arg )
 {
     master_timeout = NULL;
     flush_registry();
+    destroy_time_mapping();
     if (debug_level) fprintf( stderr, "wineserver: exiting (pid=%ld)\n", (long) getpid() );
 
 #ifdef DEBUG_OBJECTS
diff --git a/server/signal.c b/server/signal.c
index 5e4fe33..b10eefd 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -184,6 +184,7 @@ static void sighup_callback(void)
 static void sigterm_callback(void)
 {
     flush_registry();
+    destroy_time_mapping();
     exit(1);
 }
 
-- 
1.6.1.3.GIT



Подробная информация о списке рассылки Wine-patches