mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			170 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
// natThreadLocal.cc - Native part of ThreadLocal class.
 | 
						|
 | 
						|
// Fast thread local storage for systems that support the __thread
 | 
						|
// variable attribute.
 | 
						|
   
 | 
						|
/* Copyright (C) 2006  Free Software Foundation
 | 
						|
 | 
						|
   This file is part of libgcj.
 | 
						|
 | 
						|
This software is copyrighted work licensed under the terms of the
 | 
						|
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
						|
details.  */
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#include <gcj/cni.h>
 | 
						|
#include <jvm.h>
 | 
						|
#include <java-threads.h>
 | 
						|
 | 
						|
#include <gnu/gcj/RawDataManaged.h>
 | 
						|
#include <java/lang/ThreadLocal.h>
 | 
						|
#include <java/lang/IllegalArgumentException.h>
 | 
						|
#include <java/lang/IllegalThreadStateException.h>
 | 
						|
#include <java/lang/InterruptedException.h>
 | 
						|
#include <java/util/Map.h>
 | 
						|
 | 
						|
#include <jni.h>
 | 
						|
 | 
						|
/* We would like to have fast thread local variables that behave in
 | 
						|
   the same way as C and C++ thread local variables.  This would mean
 | 
						|
   having an field attribute "thread" (like static, final, etc.).
 | 
						|
   However, this is not compatible with java semantics, which we wish
 | 
						|
   to support transparently.  The problems we must overcome are:
 | 
						|
 | 
						|
   * In Java, ThreadLocal variables are not statically allocated: they
 | 
						|
     are objects, created at runtime.
 | 
						|
 | 
						|
   * Class ThreadLocal is not final and neither are its methods, so it
 | 
						|
     is possible to create a subclass of ThreadLocal that overrides
 | 
						|
     any method.
 | 
						|
 | 
						|
   * __thread variables in DSOs are not visible to the garbage
 | 
						|
     collector, so we must ensure that we keep a copy of every thread
 | 
						|
     local variable somewhere on the heap.
 | 
						|
 | 
						|
   * Once a ThreadLocal instance has been created and assigned to a
 | 
						|
     static field, that field may be reassigned to a different
 | 
						|
     ThreadLocal instance or null.  
 | 
						|
 | 
						|
   So, we can't simply replace get() and set() with accesses of a
 | 
						|
   __thread variable.
 | 
						|
 | 
						|
   So, we create a pthread_key in each ThreadLocal object and use that
 | 
						|
   as a kind of "look-aside cache".  When a ThreadLocal is set, we
 | 
						|
   also set the corresponding thread-specific value.  When the
 | 
						|
   ThreadLocal is collected, we delete the key.
 | 
						|
 | 
						|
   This scheme is biased towards efficiency when get() is called much
 | 
						|
   more frequently than set().  It is slightly internaler than the
 | 
						|
   all-Java solution using the underlying map in the set() case.
 | 
						|
   However, get() is very much more frequently invoked than set().
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
#ifdef _POSIX_PTHREAD_SEMANTICS
 | 
						|
 | 
						|
class tls_t
 | 
						|
{
 | 
						|
public:
 | 
						|
  pthread_key_t key;
 | 
						|
};
 | 
						|
 | 
						|
void
 | 
						|
java::lang::ThreadLocal::constructNative (void)
 | 
						|
{
 | 
						|
  tls_t *tls = (tls_t *)_Jv_Malloc (sizeof (tls_t));
 | 
						|
  if (pthread_key_create (&tls->key, NULL) == 0)
 | 
						|
    TLSPointer = (::gnu::gcj::RawData *)tls;
 | 
						|
  else
 | 
						|
    _Jv_Free (tls);
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
java::lang::ThreadLocal::set (::java::lang::Object *value)
 | 
						|
{
 | 
						|
  if (TLSPointer != NULL)
 | 
						|
    {
 | 
						|
      tls_t* tls = (tls_t*)TLSPointer;
 | 
						|
      pthread_setspecific (tls->key, value);
 | 
						|
    } 
 | 
						|
 | 
						|
  internalSet (value);
 | 
						|
}
 | 
						|
 | 
						|
::java::lang::Object *
 | 
						|
java::lang::ThreadLocal::get (void)
 | 
						|
{
 | 
						|
  if (TLSPointer == NULL)
 | 
						|
    return internalGet ();
 | 
						|
 | 
						|
  tls_t* tls = (tls_t*)TLSPointer;
 | 
						|
  void *obj = pthread_getspecific(tls->key);
 | 
						|
 | 
						|
  if (obj)
 | 
						|
    return (::java::lang::Object *)obj;
 | 
						|
 | 
						|
  ::java::lang::Object *value = internalGet ();
 | 
						|
  pthread_setspecific (tls->key, value);
 | 
						|
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
java::lang::ThreadLocal::remove (void)
 | 
						|
{
 | 
						|
  if (TLSPointer != NULL)
 | 
						|
    {
 | 
						|
      tls_t* tls = (tls_t*)TLSPointer;
 | 
						|
      pthread_setspecific (tls->key, NULL);
 | 
						|
    }
 | 
						|
 | 
						|
  internalRemove ();
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
java::lang::ThreadLocal::finalize (void)
 | 
						|
{
 | 
						|
  if (TLSPointer != NULL)
 | 
						|
    {
 | 
						|
      tls_t* tls = (tls_t*)TLSPointer;
 | 
						|
      pthread_key_delete (tls->key);
 | 
						|
      _Jv_Free (tls);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
void
 | 
						|
java::lang::ThreadLocal::constructNative (void)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
java::lang::ThreadLocal::set (::java::lang::Object *value)
 | 
						|
{
 | 
						|
  internalSet (value);
 | 
						|
}
 | 
						|
 | 
						|
::java::lang::Object *
 | 
						|
java::lang::ThreadLocal::get (void)
 | 
						|
{
 | 
						|
  return internalGet ();
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
java::lang::ThreadLocal::remove (void)
 | 
						|
{
 | 
						|
  internalRemove ();
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
java::lang::ThreadLocal::finalize (void)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |