On Saturday 28 May 2005 06:19, Chuck Hall wrote:
> > Chuck Hall wrote:
> >> Well it looks good.  I did get a few failures on the patching, but it
> >> wnet
> >> through 'make depend' without a problem.
> >>
> >> Now I run into the problem in kthread.c:
> >> sed -e 's,@bindir\@,/usr/local/bin,g' -e
> >> 's,@dlldir\@,/usr/local/lib/wine,g' -e 's,@PACKAGE_STRING\@,Wine
> >> 20050524,g' ./wine.man.in >wine.man || (rm -f wine.man && false)
> >> gcc -c -I. -I. -I../include -I../include    -Wall -pipe
> >> -fno-strict-aliasing -gstabs+ -Wpointer-arith  -g -O2 -o kthread.o
> >> kthread.c
> >> kthread.c:322:3: #error You must implement wine_pthread_init_current_teb
> >> for your platform
> >> kthread.c:361:3: #error wine_pthread_get_current_teb not defined for
> >> this
> >> architecture
> >> kthread.c: In function `wine_pthread_get_current_teb':
> >> kthread.c:340: warning: 'ret' might be used uninitialized in this
> >> function
> >> *** Error code 1
> >> make: Fatal error: Command failed for target `kthread.o'
> >> Current working directory /tmp/wine-20050524/loader
> >> *** Error code 1
> >> The following command caused the error:
> >> cd loader && make
> >> make: Fatal error: Command failed for target `loader'
> >>
> >> Guess this is the next problem to work on :)
> >
> > Sounds like configure isn't detecting things properly.  It should be
> > detecting '_lwp_create' and '_lwp_self', thus defining HAVE__LWP_CREATE
> > and HAVE__LWP_SELF (in addition to HAVE_SYS_LWP_H).  Check your
> > config.log to see what's going on.
> >
> > I did have problems with this stuff in older versions of wine, and I
> > actually hacked the configure scripts to use wine-pthread instead of
> > wine-kthread.  I don't recall the exact reasons, but it wine-kthread
> > seems to be working fine for me now.
>
> Started to go through this and found something intresting.  lwp.h does
> exist and is found, so HAVE_SYS_LWP_H is defined.  The test for
> _lwp_create fails.  Looking a bit deeper I found that the lwp.h for
> Solaris 9 is different from the one in Solaris 10 (which is what I am
> using).  Based on this and something I read awhile ago, I belive that Sun
> is attempting to phase out the lwp stuff on Solaris.
>
> It looks like a workaround will need to be created for _lwp_create.  I
> will look into this and see what is the "official" way to write the code
> now, if any.  Also a workaround will need to be made for all other _lwp_*
> calls that no longer exist.
>
> Have Fun!
> Chuck Hall

Chuck, didn't I send you the full kit of changes for Solaris ? You can usually 
find them on members.optushome.com.au/bobl, get the Solaris 10 patch-kit, 
though they are  little dated there at the moment (Mostly because wine had a 
regression last weekend that prevents it working properly, and I don't 
publish non-working binaries)

Anyway, you are re-inventing the wheel here, you will need the attached patch 
which will allow you to use either sysv native threads or lwp's if you like. 
LWPs are not supported post Solaris 9, but there are other problems to 
overcome, particularly ptrace and the debugger. This implementation is pretty 
well tested, event if not ready for primetime (Ugly debugging code is still 
in there).

Bob

Index: loader/kthread.c
===================================================================
RCS file: /home/wine/wine/loader/kthread.c,v
retrieving revision 1.11
diff -u -3 -p -r1.11 kthread.c
--- loader/kthread.c	2 Dec 2004 18:19:25 -0000	1.11
+++ loader/kthread.c	18 May 2005 08:20:36 -0000
@@ -68,6 +68,16 @@ struct _pthread_cleanup_buffer;
 #include <sched.h>
 #endif
 
+#ifdef HAVE_THREAD_H
+
+/* Fixme: Wine creates a namespace problem since it has it's own thread.h,
++for the time being explicitly load the system header"
+*/
+
+#include <errno.h>
+#include </usr/include/thread.h>
+#endif
+
 #include "wine/library.h"
 #include "wine/pthread.h"
 
@@ -83,6 +93,31 @@ static struct wine_pthread_functions fun
 #define MAX_KEYS 16 /* libc6 doesn't use that many, but... */
 #define MAX_TSD  16
 
+#define THREADS_SYSV 1
+#define THREADS_LWP 2
+#define THREADS_PTHREAD 3
+#define THREADS_CLONE 4
+#define THREADS_RFORK 5
+#define THREADS_NONE 6
+
+#if defined (HAVE_NPTL) || defined (HAVE_PTHREAD)
+#define THREADS_DEFAULT THREADS_PTHREAD
+#elif defined( HAVE_CLONE)
+#define THREADS_DEFAULT THREADS_CLONE
+#elif defined (HAVE_RFORK)
+#define THREADS_DEFAULT THREADS_RFORK
+#elif defined (HAVE_THR)
+#define THREADS_DEFAULT THREADS_SYSV
+#elif defined (HAVE__LWP_CREATE)
+#define THREADS_DEFAULT THREADS_LWP
+#else
+#define THREADS_DEFAULT THREADS_NONE
+#endif
+
+#define TRACE printf
+#define ERR printf
+
+int threadmode =0;
 struct pthread_descr_struct
 {
     char               dummy[2048];
@@ -123,7 +158,7 @@ int *__errno_location(void)             
 }
 int *__error(void)     { return __errno_location(); }  /* FreeBSD */
 int *__errno(void)     { return __errno_location(); }  /* NetBSD */
-int *___errno(void)    { return __errno_location(); }  /* Solaris */
+//int *___errno(void)    { return __errno_location(); }  /* Solaris */
 int *__thr_errno(void) { return __errno_location(); }  /* UnixWare */
 
 /***********************************************************************
@@ -179,6 +214,44 @@ inline static char *get_temp_stack(void)
     return temp_stacks[next % NB_TEMP_STACKS] + TEMP_STACK_SIZE;
 }
 
+#ifdef HAVE_THR
+/*
+ * THR library specific, store thread specific data
+*/
+#define THREAD_GET_DATA 0
+#define THREAD_SET_DATA 1
+void * solaris_thread_data(int op, void *data)
+{
+       static mutex_t keylock; /* static ensures only one copy of keylock */
+       static thread_key_t key;
+       static int once_per_keyname = 0;
+       void *tsd = NULL;
+
+       if (!once_per_keyname) {
+            mutex_lock(&keylock);
+            if (!once_per_keyname)  {
+                  thr_keycreate(&key, free);
+                  once_per_keyname++;
+       }
+            mutex_unlock(&keylock);
+       }
+       
+       thr_getspecific(key, &tsd);
+       if(op==THREAD_GET_DATA) return(tsd);
+       if (tsd == NULL) {
+            thr_setspecific(key, data);
+              }
+	      else
+	      ERR("Thread private data already set !\n");
+        thr_getspecific(key, &tsd);
+	return((void *) tsd);
+}  
+     /* end thread_specific_data */
+#endif
+ 
+     
+
+
 
 /***********************************************************************
  *           cleanup_thread
@@ -192,9 +265,18 @@ static void cleanup_thread( void *ptr )
     wine_ldt_free_fs( info.teb_sel );
     munmap( info.stack_base, info.stack_size );
     munmap( info.teb_base, info.teb_size );
-#ifdef HAVE__LWP_CREATE
-    _lwp_exit();
+#ifdef HAVE_THR
+    if (threadmode==THREADS_SYSV) {
+       thr_exit((void * ) &info.exit_status);
+    }
 #endif
+#ifdef  HAVE__LWP_CREATE
+    if(threadmode==THREADS_LWP)
+    {
+     _lwp_exit();
+    }
+#endif
+if((threadmode!=THREADS_SYSV) && (threadmode!=THREADS_LWP))
     _exit( info.exit_status );
 }
 
@@ -235,7 +317,9 @@ void wine_pthread_init_thread( struct wi
     }
     descr->cancel_state = PTHREAD_CANCEL_ENABLE;
     descr->cancel_type  = PTHREAD_CANCEL_ASYNCHRONOUS;
+#ifndef sun
     if (libc_uselocale) libc_uselocale( -1 /*LC_GLOBAL_LOCALE*/ );
+#endif
 }
 
 
@@ -244,6 +328,48 @@ void wine_pthread_init_thread( struct wi
  */
 int wine_pthread_create_thread( struct wine_pthread_thread_info *info )
 {
+    
+    /*   Runtime Threadmode support, initially set shared threadmode
+     *  
+     *  Implementation note, 
+      * we determine the threadmode from the environment variable WINE_THREADMODE
+     */
+    char *env;
+
+ TRACE("Starting New Thread stack base = %lx size =%d\n",info->stack_base, (char *)info->stack_size);
+ if(!threadmode)
+    {
+     	env=getenv("WINE_THREADMODE");
+	threadmode=THREADS_DEFAULT;
+
+     	if(env)
+	{
+#ifdef HAVE_THR
+     		if(!strcasecmp(env,"SYSV") ) threadmode=THREADS_SYSV;
+#endif
+#ifdef HAVE__LWP_CREATE
+     		if(!strcasecmp(env,"LWP") ) threadmode=THREADS_LWP;
+#endif
+     		if(!strcasecmp(env,"PTHREAD"))  threadmode=THREADS_PTHREAD;
+#ifdef HAVE_RFORK
+     		if(!strcasecmp(env,"RFORK") ) threadmode=THREADS_RFORK;
+#endif
+#ifdef HAVE_CLONE
+     		if(!strcasecmp(env,"CLONE") ) threadmode=THREADS_CLONE;
+#endif
+      		if(!strcasecmp(env,"NONE") ) threadmode=THREADS_NONE;
+
+TRACE("Setting Threading mode to %d (%s)\n",threadmode,env);
+     	}//env
+  } //! threaadmode
+
+
+if (threadmode == THREADS_NONE)
+{   	TRACE("Threads disabled - Returning an error");
+	return -1;
+ }
+    
+
     if (!info->stack_base)
     {
         info->stack_base = wine_anon_mmap( NULL, info->stack_size,
@@ -251,11 +377,17 @@ int wine_pthread_create_thread( struct w
         if (info->stack_base == (void *)-1) return -1;
     }
 #ifdef HAVE_CLONE
-    if (clone( (int (*)(void *))info->entry, (char *)info->stack_base + info->stack_size,
+    if(threadmode==THREADS_CLONE)
+    {
+      if (clone( (int (*)(void *))info->entry, (char *)info->stack_base + info->stack_size,
                CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, info ) < 0)
         return -1;
     return 0;
-#elif defined(HAVE_RFORK)
+    }
+#endif
+
+#ifdef HAVE_RFORK
+    if(threadmode==THREADS_RFORK)
     {
         void **sp = (void **)((char *)info->stack_base + info->stack_size);
         *--sp = info;
@@ -276,15 +408,78 @@ int wine_pthread_create_thread( struct w
             : "eax", "edx");
         return 0;
     }
-#elif defined(HAVE__LWP_CREATE)
-    {
+
+#endif
+#ifdef HAVE_THR
+ 	if(threadmode==THREADS_SYSV)
+	{
+ 		thread_t tid;
+		int err;
+
+		TRACE("Starting New Thread Via thr_create\n");
+ 	err=thr_create(info->stack_base, ( int )info->stack_size,  (void * (*) (void*)) info->entry, info,THR_BOUND|THR_DETACHED,&tid) ;
+ 		if(err)
+ 		{
+   			switch(err)
+   			{
+      			case EAGAIN:
+        			ERR("Thread creation failed EAGAIN - System is out of threads or lwps\n");
+        			break;
+      			case EINVAL:
+        			ERR("Thread creation failed EINVAL - The stack_base argument is not NULL and stack_size  is  less  than the value returned by thr_min_stack,  or the stack_base argument is NULL and  stack_size  is   not   0  and  is  less  than  the  value  returned  by          thr_min_stack\n");
+        			break;
+      			case ENOMEM:
+        			ERR("Thread creation failed ENOMEM - here is not enough memory to allocate the stack for the thread\n");
+        			break;
+       			case -1:
+        			ERR("Thread creation failed (-1) - Application is not linked with threading libraryn");
+        			break;
+      			default:
+        			ERR("Thread creation failed Unknown %d - Possible mmap failure check mmap results\n",err);
+        			break;
+   			}
+    			return -1;
+ 		}
+		else
+    			TRACE("Started New Thread Via thr_create\n");
+    		return 0;
+	} /* threadmode*/
+#endif
+
+#ifdef HAVE__LWP_CREATE
+  if(threadmode==THREADS_LWP)
+  {
+      int err;
+
         ucontext_t context;
         _lwp_makecontext( &context, (void(*)(void *))info->entry, info,
                           NULL, info->stack_base, info->stack_size );
-        if ( _lwp_create( &context, 0, NULL ) )
-            return -1;
-        return 0;
-    }
+        if ( (err=_lwp_create( &context, 0, NULL )) )
+	{
+
+  		switch (err)
+		{
+      		case EFAULT:
+        		ERR("lwp_create: Either the context parameter or the new_lwp  parameter  point to invalid addresses.");
+        		break;
+      		case EAGAIN:
+        		ERR("lwp_create: Resources depleted, probably too many lwps");
+        		break;
+      		case EINVAL:
+        		ERR("lwp_create: FLAGS argument invalid\n");
+        		break;
+       		case -1:
+        		ERR("Thread creation failed\n");
+        		break;
+      		default:
+        		ERR("Thread creation failed Unknown %d \n",err);
+        		break;
+   		}
+           return -1;
+        } /* if err*/
+	return 0;
+    } /* Threadmode = THREADS_LWP */
+
 #endif
     return -1;
 }
@@ -305,9 +500,19 @@ void wine_pthread_init_current_teb( stru
     wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
     wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
     wine_ldt_init_fs( info->teb_sel, &fs_entry );
-#elif defined(HAVE__LWP_CREATE)
-    /* On non-i386 Solaris, we use the LWP private pointer */
-    _lwp_setprivate( info->teb_base );
+
+#elif defined(HAVE__LWP_CREATE) || defined (HAVE_THR)
+
+#ifdef HAVE__LWP_CREATE
+   /* On non-i386 Solaris, we use the LWP private pointer */
+ if(threadmode==THREADS_LWP)    ret = _lwp_setprivate(info->teb_base);
+#endif
+
+#ifdef HAVE_THR
+   /* On non-i386 Solaris, we can also use the threads private pointer */
+   if(threadmode==THREADS_SYSV) ret=solaris_thread_data(THREAD_SET_DATA,info->teb_base);
+#endif
+
 #elif defined(__powerpc__)
     /* On PowerPC, the current TEB is in the gpr13 register */
 # ifdef __APPLE__
@@ -324,8 +529,21 @@ void wine_pthread_init_current_teb( stru
 
     /* set pid and tid */
     info->pid = getpid();
-#ifdef HAVE__LWP_SELF
-    info->tid = _lwp_self();
+
+
+
+#if defined ( HAVE__LWP_SELF ) || defined (HAVE_THR)
+ 	info->tid = -1;
+#if defined ( HAVE__LWP_SELF )
+	if(threadmode==THREADS_LWP)   info->tid = _lwp_self();
+#endif
+
+#if defined (HAVE_THR)
+	if(threadmode==THREADS_SYSV)  info->tid=thr_self();
+#endif
+    
+
+
 #else
     info->tid = -1;
 #endif
@@ -341,8 +559,18 @@ void *wine_pthread_get_current_teb(void)
 
 #ifdef __i386__
     __asm__( ".byte 0x64\n\tmovl 0x18,%0" : "=r" (ret) );
-#elif defined(HAVE__LWP_CREATE)
-    ret = _lwp_getprivate();
+#elif defined(HAVE__LWP_CREATE) || defined (HAVE_THR)
+
+#ifdef HAVE__LWP_CREATE
+if(threadmode==THREADS_LWP)    ret = _lwp_getprivate();
+#endif
+
+#ifdef HAVE_THR
+ if(threadmode==THREADS_SYSV) ret=solaris_thread_data(THREAD_GET_DATA,NULL);
+#endif
+   
+    
+    
 #elif defined(__powerpc__)
 # ifdef __APPLE__
     __asm__( "mr %0,r13" : "=r" (ret) );
@@ -379,9 +607,20 @@ void wine_pthread_exit_thread( struct wi
  */
 void wine_pthread_abort_thread( int status )
 {
-#ifdef HAVE__LWP_CREATE
-    _lwp_exit();
+
+#ifdef HAVE_THR
+if (threadmode==THREADS_SYSV) {
+    thr_exit((void * ) &status);
+}
+#endif
+#ifdef  HAVE__LWP_CREATE
+  if(threadmode==THREADS_LWP)
+  {
+     _lwp_exit();
+ }
 #endif
+
+
     _exit( status );
 }
 

Reply via email to