Logo Search packages:      
Sourcecode: sablevm version File versions  Download package

java_lang_VMThread.c

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This source file is part of SableVM.                            *
 *                                                                 *
 * See the file "LICENSE" for the copyright information and for    *
 * the terms and conditions for copying, distribution and          *
 * modification of this source file.                               *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_yield
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    yield
 * Signature: ()V
 */

JNIEXPORT static void JNICALL
Java_java_lang_VMThread_yield (JNIEnv *_env, jclass _class SVM_UNUSED)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  _svmm_resuming_java (env);

  if (sched_yield () != 0)
    {
      /* Should we really really throw an error on failure? Maybe we
         could simply ignore the return value, if no harm is implied.
         Suggestions are welcome.  Etienne */

      _svmf_error_InternalError (env);
      goto end;
    }

end:
  _svmm_stopping_java (env);

  return;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_sleep
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    sleep
 * Signature: ()Z
 */
JNIEXPORT static void JNICALL
Java_java_lang_VMThread_sleep (JNIEnv *_env, jclass this SVM_UNUSED, jlong ms,
                         jint ns)
{

  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  struct timespec timeout;
  _svmt_word old_interrupted_status, new_interrupted_status;

  do
    {
      old_interrupted_status = env->thread.interrupted_status;
      new_interrupted_status = old_interrupted_status;

      new_interrupted_status |= SVM_THREAD_INTERRUPTIBLE_BY_SIGNAL;
      new_interrupted_status &= ~SVM_THREAD_THROW_INTERRUPTED;
    }
  while (!_svmm_compare_and_swap
       (env->thread.interrupted_status, old_interrupted_status,
        new_interrupted_status));

  timeout.tv_sec = ms / 1000;
  timeout.tv_nsec = (ms % 1000) * 1000 * 1000 + ns;

  /* Watch for overflow of timeout.tv_nsec...
     OK; I assume that tv_nsec has at least 32 bits (signed or
     not, I don't care), a reasonable assumption given that it
     must be able to hold the value 999999999.
   */
  if (timeout.tv_nsec >= 1000000000L)
    {
      timeout.tv_sec++;
      timeout.tv_nsec -= 1000000000L;
    }

  /* we don't check the return value, as in case of interrupt() that
   * caused a signal that woke us up, we'll have interrupted_status
   * flag set accordingly */
  nanosleep (&timeout, NULL);

  do
    {
      old_interrupted_status = env->thread.interrupted_status;
      new_interrupted_status = old_interrupted_status;

      if (old_interrupted_status & SVM_THREAD_THROW_INTERRUPTED)
      {
        new_interrupted_status &= ~SVM_THREAD_INTERRUPTIBLE_ON_FAT_LOCK;
        new_interrupted_status &= ~SVM_THREAD_THROW_INTERRUPTED;
      }
      else
      {
        break;
      }
    }
  while (!_svmm_compare_and_swap
       (env->thread.interrupted_status,
        old_interrupted_status, new_interrupted_status));

  if (old_interrupted_status & SVM_THREAD_THROW_INTERRUPTED)
    {
      _svmm_resuming_java (env);
      _svmf_error_InterruptedException (env);
      _svmm_stopping_java (env);
    }
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_nativeIsAlive
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    nativeIsAlive
 * Signature: ([B)Z
 */

JNIEXPORT static jboolean JNICALL
Java_java_lang_VMThread_nativeIsAlive (JNIEnv *_env, jobject this SVM_UNUSED,
                               jbyteArray vmData)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  jboolean result;

  _svmm_resuming_java (env);

  result = ((_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData))->is_alive;

  _svmm_stopping_java (env);

  return result;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_nativeStart
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    nativeStart
 * Signature: ()[B
 */

JNIEXPORT static jbyteArray JNICALL
Java_java_lang_VMThread_nativeStart (JNIEnv *_env, jobject this SVM_UNUSED,
                             jobject threadInstance)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  jbyteArray result = NULL;

  _svmm_resuming_java (env);

  {
    _svmt_JNIEnv *new_env = _svmf_thread_native_start (env, threadInstance);

    if (new_env != NULL)
      {
      result = _svmf_get_jni_frame_native_local_array (env);
      if (_svmf_wrap_pointer (env, new_env, result) != JNI_OK)
        {
          result = NULL;
          goto end;
        }
      }
  }

end:
  _svmm_stopping_java (env);

  return result;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_currentThread
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    currentThread
 * Signature: ()Ljava/lang/Thread;
 */

JNIEXPORT static jobject JNICALL
Java_java_lang_VMThread_currentThread (JNIEnv *_env, jclass _class SVM_UNUSED)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  jobject result = NULL;

  _svmm_resuming_java (env);

  {
    if (env->thread.thread_instance == NULL)
      {
      jobject thread;
      jbyteArray wrapper;

      if (_svmm_new_native_local (env, thread) != JNI_OK)
        {
          goto end;
        }

      if (_svmm_local_wrap_pointer (env, env, wrapper) != JNI_OK)
        {
          _svmm_free_native_local (env, thread);
          goto end;
        }

      if (_svmm_invoke_static_virtualmachine_createrootthread
          (env, _svmf_cast_jobject (wrapper), thread) != JNI_OK)
        {
          _svmm_free_native_local_array (env, wrapper);
          _svmm_free_native_local (env, thread);
          goto end;
        }

      _svmm_free_native_local_array (env, wrapper);
      env->thread.thread_instance = thread;
      }

    result = _svmf_get_jni_frame_native_local (env);
    *result = *(env->thread.thread_instance);
  }

end:
  _svmm_stopping_java (env);

  return result;
}


/*
----------------------------------------------------------------------
Java_java_lang_VMThread_nativeInterrupt
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    interrupt
 * Signature: ()V
 */
JNIEXPORT static void JNICALL
Java_java_lang_VMThread_nativeInterrupt (JNIEnv *_env,
                               jobject this SVM_UNUSED,
                               jbyteArray vmData)
{

  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  _svmt_JNIEnv *target_env = (_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData);
  _svmt_fat_lock *sleeping_on_fat_lock;
  _svmt_word old_interrupted_status, new_interrupted_status;

  _svmm_resuming_java (env);

again:

  /* where is the target thread possibly sleeping? */
  do
    {
      old_interrupted_status = target_env->thread.interrupted_status;
      new_interrupted_status = old_interrupted_status;

      if (old_interrupted_status & SVM_THREAD_INTERRUPTIBLE_BY_SIGNAL)
      {
        new_interrupted_status |= SVM_THREAD_THROW_INTERRUPTED;
        new_interrupted_status &= ~SVM_THREAD_INTERRUPTED;
      }
      else if (old_interrupted_status & SVM_THREAD_INTERRUPTIBLE_ON_FAT_LOCK)
      {
        /* do nothing, we're not sure yet what the target thread is doing */
      }
      else
      {
        new_interrupted_status |= SVM_THREAD_INTERRUPTED;
      }

    }
  while (!_svmm_compare_and_swap
       (target_env->thread.interrupted_status, old_interrupted_status,
        new_interrupted_status));

  if (old_interrupted_status & SVM_THREAD_INTERRUPTIBLE_ON_FAT_LOCK)
    {
      /* the target thread is probably sleeping on a fat lock */
      sleeping_on_fat_lock = target_env->thread.sleeping_on_fat_lock;
      if (sleeping_on_fat_lock != NULL)
      {
        if (_svmm_mutex_trylock (sleeping_on_fat_lock->mutex) == 0)
          {
            /* make sure the thread is _still_ sleeping on this lock! */
            if (sleeping_on_fat_lock ==
              target_env->thread.sleeping_on_fat_lock)
            {
              /* Only now we can be sure that the target thread is sleeping and we can
               * effectively interrupt him and tell him to throw InterruptedException */
              do
                {
                  old_interrupted_status =
                  target_env->thread.interrupted_status;
                  new_interrupted_status = old_interrupted_status;

                  new_interrupted_status |= SVM_THREAD_THROW_INTERRUPTED;
                  new_interrupted_status &= ~SVM_THREAD_INTERRUPTED;
                }
              while (!_svmm_compare_and_swap
                   (target_env->thread.interrupted_status,
                    old_interrupted_status, new_interrupted_status));

              /* free the sleeping/target thread */
              _svmm_cond_broadcast (sleeping_on_fat_lock->
                              notification_cond);
              _svmm_mutex_unlock_after_try (sleeping_on_fat_lock->mutex);
            }
            else
            {
              _svmm_mutex_unlock_after_try (sleeping_on_fat_lock->mutex);
              /* We haven't managed to block&interrupt the target thread - trying again. */
              goto again;
            }
          }
        else
          goto again;
      }
      else
      goto again;

    }
  else if (old_interrupted_status & SVM_THREAD_INTERRUPTIBLE_BY_SIGNAL)
    {
      _svmm_kill (target_env->thread.pthread, SVM_INTERRUPT_SIGNAL);
    }

  _svmm_stopping_java (env);

  return;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_nativeIsInterrupted
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    isInterrupted
 * Signature: ()Z
 */
JNIEXPORT static jboolean JNICALL
Java_java_lang_VMThread_nativeIsInterrupted (JNIEnv *_env,
                                   jobject this SVM_UNUSED,
                                   jbyteArray vmData)
{
  jboolean result;
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);

  _svmm_resuming_java (env);

  result =
    (((_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData))->thread.
     interrupted_status) & SVM_THREAD_INTERRUPTED;

  _svmm_stopping_java (env);

  return result;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_interrupted
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    interrupted
 * Signature: ()Z
 */
JNIEXPORT static jboolean JNICALL
Java_java_lang_VMThread_interrupted (JNIEnv *_env, jclass this SVM_UNUSED)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  _svmt_word old_interrupted_status, new_interrupted_status;
  jboolean result;

  _svmm_resuming_java (env);

  /* this is static method that refers to the _current_ thread only,
     so no need to search which thread is referred to by "this"
   */

  do
    {
      old_interrupted_status = env->thread.interrupted_status;
      new_interrupted_status = old_interrupted_status;

      new_interrupted_status &= ~SVM_THREAD_INTERRUPTED;
    }
  while (!_svmm_compare_and_swap (env->thread.interrupted_status,
                          old_interrupted_status,
                          new_interrupted_status));

  result = old_interrupted_status & SVM_THREAD_INTERRUPTED;

  _svmm_stopping_java (env);

  return result;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_holdsLock
----------------------------------------------------------------------
*/

/* 
 * Class:     java_lang_VMThread 
 * Method:    holdsLock 
 * Signature: (Ljava/lang/Object;)Z 
 */
JNIEXPORT static jboolean JNICALL
Java_java_lang_VMThread_holdsLock (JNIEnv *_env, jclass class SVM_UNUSED,
                           jobject o)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  _svmt_JavaVM *vm = env->vm;
  jboolean result = JNI_TRUE;

  _svmm_resuming_java (env);

  {
    /* Note: the case where o == NULL should be handled before calling this function */
    _svmt_object_instance *instance = *o;
    _svmt_word lockword = instance->lockword;

    if (_svmf_lockword_is_thin (lockword))
      {
      if (_svmf_lockword_get_thinlock_id (lockword) !=
          env->thread.thinlock_id)
        {
          result = JNI_FALSE;
        }
      goto end;
      }

    /* It's a fat lock. */
    {
      _svmt_word fat_index = _svmf_lockword_get_fatlock_index (lockword);
      _svmt_fat_lock *fat_lock = vm->fat_locks.array[fat_index];

      if (fat_lock->owner != env)
      {
        result = JNI_FALSE;
      }
    }

  }

end:
  _svmm_stopping_java (env);

  return result;
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_suspend
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    suspend
 * Signature: ()V
 */

JNIEXPORT static void JNICALL
Java_java_lang_VMThread_suspend (JNIEnv *_env, jclass class SVM_UNUSED,
                         jbyteArray vmData)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  _svmt_JavaVM *vm = env->vm;

  _svmm_resuming_java (env);

  {
    _svmt_JNIEnv *target;

    target = _svmf_unwrap_pointer (*vmData);

    _svmm_mutex_lock (vm->global_mutex);

    _svmf_suspend_thread (env, target);

    _svmm_mutex_unlock ();
  }

  _svmm_stopping_java (env);
}

/*
----------------------------------------------------------------------
Java_java_lang_VMThread_resume
----------------------------------------------------------------------
*/

/*
 * Class:     java_lang_VMThread
 * Method:    resume
 * Signature: ()V
 */

JNIEXPORT static void JNICALL
Java_java_lang_VMThread_resume (JNIEnv *_env, jclass class SVM_UNUSED,
                        jbyteArray vmData)
{
  _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env);
  _svmt_JavaVM *vm = env->vm;

  _svmm_resuming_java (env);

  {
    _svmt_JNIEnv *target;

    target = _svmf_unwrap_pointer (*vmData);

    _svmm_mutex_lock (vm->global_mutex);

    _svmf_resume_thread (env, target);

    _svmm_mutex_unlock ();
  }

  _svmm_stopping_java (env);
}

Generated by  Doxygen 1.6.0   Back to index