scheduling for ppc

Josh DuBois duboisj at codeweavers.com
Sat Mar 10 16:56:15 CST 2001


Hi - 
  These two patches make the scheduler work on PPC.
  
  ChangeLog:
     scheduler/sysdeps.c
       provide thread switching for PPC
     scheduler/critsection.c
       provide Interlocked* functions for ppc
       
     include/thread.h
       add a field for unix thread ID to TEB block.


-- 
Josh DuBois
654 SW Grant #103, Portland, OR 97201
(503)-827-4818
duboisj at codeweavers.com

-------------- next part --------------
Index: include/thread.h
===================================================================
RCS file: /home/cvs/wine/wine/include/thread.h,v
retrieving revision 1.50
diff -u -r1.50 thread.h
--- include/thread.h	2001/03/08 01:16:41	1.50
+++ include/thread.h	2001/03/10 22:13:54
@@ -100,10 +100,13 @@
     int          wait_fd[2];     /* --3 214 fd for sleeping server requests */
     void        *debug_info;     /* --3 21c Info for debugstr functions */
     void        *pthread_data;   /* --3 220 Data for pthread emulation */
+
+    int          utid;           /* --3 224 Unix Thread ID */
+
     /* here is plenty space for wine specific fields (don't forget to change pad6!!) */
 
     /* the following are nt specific fields */
-    DWORD        pad6[629];                  /* --n 224 */
+    DWORD        pad6[628];                  /* --n 228 */
     UNICODE_STRING StaticUnicodeString;      /* -2- bf8 used by advapi32 */
     USHORT       StaticUnicodeBuffer[261];   /* -2- c00 used by advapi32 */
     DWORD        pad7;                       /* --n e0c */
-------------- next part --------------
Index: scheduler/critsection.c
===================================================================
RCS file: /home/cvs/wine/wine/scheduler/critsection.c,v
retrieving revision 1.25
diff -u -r1.25 critsection.c
--- scheduler/critsection.c	2000/11/25 01:31:18	1.25
+++ scheduler/critsection.c	2001/03/10 22:15:16
@@ -226,6 +226,121 @@
     return retv;
 }
 
+#elif defined (__PPC__)
+
+PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
+{
+    int ret;
+    int scratch;
+
+    __asm__ __volatile__(
+			 "sync; "
+			 "0:    lwarx %0,0,%2 ;"
+			 "      xor. %1,%4,%0;"
+			 "      bne 1f;"
+			 "      stwcx. %3,0,%2;"
+			 "      bne- 0b;"
+			 "1:    "
+			 "sync; "
+			 : "=&r"(ret), "=&r"(scratch)
+			 : "r"(dest), "r"(xchg), "r"(compare)
+			 : "cr0", "memory");
+
+    return (PVOID)ret;
+}
+
+/***********************************************************************
+ *              InterlockedExchange (KERNEL32.@)
+ */
+LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
+{
+    void *ret __attribute__ ((aligned (4))) = &ret;
+    int zero = 0;
+
+    __asm__ __volatile__(
+			 "sync; "
+			 "0:    lwarx %0,0,%1 ;"
+			 "      stwcx. %2,0,%1;"
+			 "      bne- 0b;"
+			 "sync; "
+			 : "=&r"(ret)
+			 : "r"(dest), "r"(val)
+			 : "cr0", "memory");
+
+
+    return ret;
+}
+
+/***********************************************************************
+ *              InterlockedExchangeAdd (KERNEL32.@)
+ */
+LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
+{
+    void *ret __attribute__ ((aligned (4))) = &ret;
+    int inc = incr;
+    int zero = 0;
+
+    __asm__ __volatile__(
+			 "sync; "
+                         "0:    lwarx %0, %3, %1;"
+                         "      add %0, %2, %0;"
+                         "      stwcx. %0, %3, %1;"
+                         "      bne- 0b;"
+			 "sync; "
+                         : "=&r"(ret)
+                         : "r"(dest), "r"(inc), "r"(zero)
+                         : "cr0", "memory");
+
+    return (LONG)ret;
+}
+
+/***********************************************************************
+ *              InterlockedIncrement (KERNEL32.@)
+ */
+LONG WINAPI InterlockedIncrement( PLONG dest )
+{
+    void *ret __attribute__ ((aligned (4))) = &ret;
+    int inc = 1;
+    int zero = 0;
+
+    __asm__ __volatile__(
+			 "sync; "
+                         "0:    lwarx %0, %3, %1;"
+                         "      add %0, %2, %0;"
+                         "      stwcx. %0, %3, %1;"
+                         "      bne- 0b;"
+			 "sync; "
+                         : "=&r"(ret)
+                         : "r"(dest), "r"(inc), "r"(zero)
+                         : "cr0", "memory");
+
+    return (LONG)ret;
+}
+
+/***********************************************************************
+ *              InterlockedDecrement (KERNEL32.@)
+ */
+LONG WINAPI InterlockedDecrement( PLONG dest )
+{
+    void *ret __attribute__ ((aligned (4))) = &ret;
+    int inc = 1;
+    int zero = 0;
+
+    __asm__ __volatile__(
+			 "sync; "
+                         "0:    lwarx %0, %3, %1;"
+                         "      subf %0, %2, %0;"
+                         "      stwcx. %0, %3 ,%1;"
+                         "      bne- 0b;"
+			 "sync; "
+                         : "=&r"(ret)
+                         : "r"(dest), "r"(inc), "r"(zero)
+                         : "cr0", "memory");
+
+    return (LONG)ret;
+}
+
+
 #else
 #error You must implement the Interlocked* functions for your CPU
 #endif
Index: scheduler/sysdeps.c
===================================================================
RCS file: /home/cvs/wine/wine/scheduler/sysdeps.c,v
retrieving revision 1.33
diff -u -r1.33 sysdeps.c
--- scheduler/sysdeps.c	2001/03/01 22:13:49	1.33
+++ scheduler/sysdeps.c	2001/03/10 22:15:16
@@ -20,6 +20,7 @@
 #ifdef HAVE_UCONTEXT_H
 # include <ucontext.h>
 #endif
+#include <assert.h>
 #include "wine/port.h"
 #include "thread.h"
 #include "server.h"
@@ -40,8 +41,24 @@
 #  define CLONE_SIGHAND 0x00000800
 #  define CLONE_PID     0x00001000
 # endif  /* CLONE_VM */
+
+#ifdef __PPC__
+#define USE_GENERIC_LINUX_THREADING
+#endif
+
 #endif  /* linux */
 
+#ifdef USE_GENERIC_LINUX_THREADING
+
+#include <linux/tasks.h>
+
+void GLT_RemoveCurrentTEB();
+void GLT_LockTEBList();
+void GLT_UnlockTEBList();
+int GLT_TEBListLock = 0;
+static TEB* GLT_TEBList[MAX_TASKS_PER_USER];
+#endif
+
 /***********************************************************************
  *           SYSDEPS_SetCurThread
  *
@@ -55,6 +72,47 @@
 #elif defined(HAVE__LWP_CREATE)
     /* On non-i386 Solaris, we use the LWP private pointer */
     _lwp_setprivate( teb );
+#elif defined(USE_GENERIC_LINUX_THREADING)
+
+    int j;
+    int found = 0;
+
+    GLT_LockTEBList();
+
+    for(j = 0; j < MAX_TASKS_PER_USER; j++)
+    {
+	if(GLT_TEBList[j] == teb)
+	{
+	    found = 1;
+	    break;
+	}
+    }
+
+    /* -----------------------------------------------------------
+    **   If the TEB isn't in the list already, we have to insert it.
+    ** ----------------------------------------------------------- */
+    if(!found)
+    {
+	for(j = 0; j < MAX_TASKS_PER_USER; j++)
+	{
+	    if(!GLT_TEBList[j])
+	    {
+		GLT_TEBList[j] = teb;
+		
+		/* -----------------------------------------------
+		**   Record the pid so we can find this TEB
+		**   later on.
+		** ----------------------------------------------- */
+		teb->utid = getpid();
+		break;
+	    }
+	}
+    }
+
+    GLT_UnlockTEBList();
+
+#else
+#error "SYSDEPS_SetCurThread isn't defined for this platform."
 #endif
 }
 
@@ -148,7 +206,13 @@
 {
     int fd = NtCurrentTeb()->request_fd;
     NtCurrentTeb()->request_fd = -1;
+
+#ifdef USE_GENERIC_LINUX_THREADING
+    GLT_RemoveCurrentTEB();
+#endif
+
     close( fd );
+
 #ifdef HAVE__LWP_CREATE
     _lwp_exit();
 #endif
@@ -202,12 +266,29 @@
                    ".byte 0x64; popl 0x04\n\t"
                    "popl %ebp\n\t"
                    "ret" );
-#else
+#elif defined(__PPC__)
+int SYSDEPS_CallOnStack( LPVOID stackTop, LPVOID stackLow,
+                         int (*func)(LPVOID), LPVOID arg )
+{
+    TEB *curTeb = NtCurrentTeb();
+
+    curTeb->stack_top = stackTop;
+    curTeb->stack_low = stackLow;
+
+    __asm__ __volatile__("mr 1, %0"
+			 : 
+			 : "r"(stackTop) );
+    
+    return SYSDEPS_DoCallOnStack( func, arg );
+}
+#elif defined (__sparc__)
 int SYSDEPS_CallOnStack( LPVOID stackTop, LPVOID stackLow,
                          int (*func)(LPVOID), LPVOID arg )
 {
     return SYSDEPS_DoCallOnStack( func, arg );
 }
+#else
+#error "You need to define stack-switching code for your architecture."
 #endif
 
 /***********************************************************************
@@ -250,6 +331,92 @@
     extern void *_lwp_getprivate(void);
     return (struct _TEB *)_lwp_getprivate();
 }
+
+#elif defined(USE_GENERIC_LINUX_THREADING)
+
+struct _TEB * WINAPI NtCurrentTeb(void)
+{
+    TEB *teb = NULL;
+    int pid = getpid();
+    int j;
+
+    GLT_LockTEBList();    
+
+    for(j = 0; j < MAX_TASKS_PER_USER; j++)
+    {
+        if(GLT_TEBList[j] != NULL)
+        {
+            if(GLT_TEBList[j]->utid == pid)
+            {
+                teb = GLT_TEBList[j];
+                break;
+            }
+        }
+    }
+
+    GLT_UnlockTEBList();
+
+    assert(teb);
+    return teb;
+}
 #else
 # error NtCurrentTeb not defined for this architecture
 #endif  /* __i386__ */
+
+#ifdef USE_GENERIC_LINUX_THREADING
+
+/* ---------------------------------------------------------------
+**       GLT_RemoveCurrentTEB()
+** remove the current TEB from the teb list
+** --------------------------------------------------------------- */
+void GLT_RemoveCurrentTEB()
+{
+    TEB *teb = NtCurrentTeb();
+    int j;
+
+    GLT_LockTEBList();
+    
+    for(j = 0; j < MAX_TASKS_PER_USER; j++)
+    {
+	if(GLT_TEBList[j] == teb)
+	{
+	    GLT_TEBList[j] = NULL;
+	    break;
+	}
+    }
+
+    GLT_UnlockTEBList();
+}
+
+void GLT_LockTEBList()
+{
+    int oldVal;
+    int pid = getpid();
+
+    do
+    {
+        oldVal = (int)InterlockedCompareExchange((void*)&GLT_TEBListLock,
+                                                 (void*)pid,
+                                                 (void*)0);
+    } while(oldVal != 0);
+
+    return;
+}
+
+void GLT_UnlockTEBList()
+{
+    int oldVal;
+    int pid = getpid();
+
+    oldVal = (int)InterlockedCompareExchange((void *)&GLT_TEBListLock,
+                                             (void*)0,
+                                             (void*)pid);
+    if(oldVal != pid)
+    {
+        _exit(-1);
+    }
+
+    return;
+}
+
+#endif /* USE_GENERIC_LINUX_THREADING  */


More information about the wine-patches mailing list