[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, ¤t_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