>> However, I do not know if we can have additional threads at all in a
>> Win32 process without confusing the win32 processes, or if this needs
>> to be solved differently (APC?).
>>
> 
> A previous version of my patch used NtTimer/APC:
> 

I'm attaching a cleaned up version of my APC code.  It does get called
regularly:

000f:fixme:thread:update_shared_data_time 129768277137647820
0041:fixme:win:GetWindowPlacement not supported on other process window
0x90076
0036:fixme:d3d:query_init Unhandled query type 0xc.
000f:fixme:thread:update_shared_data_time 129768277137814980

Though the interval is not exactly 15.600 ms, as it is with a separate
thread and nanosleep.

And most importantly, it does not allow SW:TOR to make it to the
character selection screen.

Could I have initialized the timer with different values to make it more
precise?

thanks,

Joey
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index e328c5f..a4cbdc3 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -23,6 +23,7 @@
 
 #include <assert.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <sys/types.h>
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
@@ -67,6 +68,103 @@ static RTL_BITMAP fls_bitmap;
 static LIST_ENTRY tls_links;
 static int nb_threads = 1;
 
+static void CALLBACK shared_data_timer_apc(void* TimerContext, uint32_t TimerLowValue, int32_t TimerHighValue);
+static HANDLE create_shared_data_timer(void);
+static NTSTATUS set_shared_data_timer(HANDLE handle);
+
+static void update_shared_data_time(void)
+{
+    LARGE_INTEGER now, start, irq;
+
+    NtQuerySystemTime( &now );
+
+    FIXME("%lld\n", now.QuadPart);
+
+    irq.QuadPart = (now.QuadPart - server_start_time);
+
+    user_shared_data->InterruptTime.High2Time = irq.HighPart;
+    user_shared_data->InterruptTime.LowPart = irq.LowPart;
+    user_shared_data->InterruptTime.High1Time = irq.HighPart;
+
+    user_shared_data->SystemTime.High2Time = now.HighPart;
+    user_shared_data->SystemTime.LowPart = now.LowPart;
+    user_shared_data->SystemTime.High1Time = now.HighPart;
+
+    start.QuadPart = irq.QuadPart / 10000;
+
+    user_shared_data->u.TickCount.High2Time = start.HighPart;
+    user_shared_data->u.TickCount.LowPart = start.LowPart;
+    user_shared_data->u.TickCount.High1Time = start.HighPart;
+    user_shared_data->TickCountLowDeprecated = start.LowPart;
+}
+
+static void CALLBACK shared_data_timer_apc(void* ctx, uint32_t low, int32_t high)
+{
+    update_shared_data_time();
+    set_shared_data_timer((HANDLE)ctx);
+}
+
+static HANDLE create_shared_data_timer(void)
+{
+    HANDLE handle;
+    NTSTATUS status;
+    OBJECT_ATTRIBUTES attr;
+
+    //FIXME("enter\n");
+
+    attr.Length                   = sizeof(attr);
+    attr.RootDirectory            = 0;
+    attr.ObjectName               = NULL;
+    attr.Attributes               = OBJ_OPENIF;
+    attr.SecurityDescriptor       = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    status = NtCreateTimer( &handle, TIMER_ALL_ACCESS, &attr, NotificationTimer);
+
+    if (status == STATUS_OBJECT_NAME_EXISTS)
+        SetLastError( ERROR_ALREADY_EXISTS );
+    else
+        SetLastError( RtlNtStatusToDosError(status) );
+
+    return handle;
+}
+
+static NTSTATUS set_shared_data_timer(HANDLE handle)
+{
+    LARGE_INTEGER when;
+    NTSTATUS status;
+
+    //FIXME("enter\n");
+
+    NtQuerySystemTime( &when );
+    when.QuadPart += 156000;
+
+    status = NtSetTimer(handle, &when, (PTIMER_APC_ROUTINE)shared_data_timer_apc, handle, 0, 0, NULL);
+    if (status != STATUS_SUCCESS)
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+    }
+
+    return status;
+}
+
+
+static void* shared_data_thread(void *arg) 
+{
+    struct timespec req, rem;
+
+    req.tv_sec = 0;
+    req.tv_nsec = 15600000;
+
+    while(1) {
+        update_shared_data_time();
+        nanosleep(&req, &rem);
+    }
+
+    return NULL;
+}
+
+
 /***********************************************************************
  *           get_unicode_string
  *
@@ -196,9 +294,10 @@ HANDLE thread_init(void)
     void *addr;
     SIZE_T size, info_size;
     HANDLE exe_file = 0;
-    LARGE_INTEGER now;
     struct ntdll_thread_data *thread_data;
     static struct debug_info debug_info;  /* debug info for initial thread */
+    pthread_t thread;
+    int s;
 
     virtual_init();
 
@@ -288,16 +387,24 @@ HANDLE thread_init(void)
     }
 
     /* initialize time values in user_shared_data */
-    NtQuerySystemTime( &now );
-    user_shared_data->SystemTime.LowPart = now.u.LowPart;
-    user_shared_data->SystemTime.High1Time = user_shared_data->SystemTime.High2Time = now.u.HighPart;
-    user_shared_data->u.TickCountQuad = (now.QuadPart - server_start_time) / 10000;
-    user_shared_data->u.TickCount.High2Time = user_shared_data->u.TickCount.High1Time;
-    user_shared_data->TickCountLowDeprecated = user_shared_data->u.TickCount.LowPart;
     user_shared_data->TickCountMultiplier = 1 << 24;
 
+    update_shared_data_time();
+
     fill_cpu_info();
 
+    HANDLE timer = create_shared_data_timer();
+    set_shared_data_timer(timer);
+
+    /*
+    if(!(s = pthread_create(&thread, NULL, &shared_data_thread, NULL))) {
+        if(pthread_detach(thread))
+            FIXME("Unable to detach thread\n");
+    } else {
+        FIXME("unable to spawn thread: %s (%d)\n", strerror(s), s);
+    }
+    */
+
     return exe_file;
 }
 


Reply via email to