LCOV - code coverage report
Current view: top level - threads/posix - thread-posix.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 184 315 58.4 %
Date: 2015-06-10 18:10:59 Functions: 19 29 65.5 %

          Line data    Source code
       1             : /* src/threads/posix/thread-posix.cpp - POSIX thread functions
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       8             :    This program is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU General Public License as
      10             :    published by the Free Software Foundation; either version 2, or (at
      11             :    your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : #define __STDC_LIMIT_MACROS
      26             : 
      27             : #include "threads/thread.hpp"           // for threadobject, etc
      28             : #include <assert.h>                     // for assert
      29             : #include <errno.h>                      // for errno, EINTR
      30             : #include <pthread.h>                    // for pthread_attr_init, etc
      31             : #include <sched.h>                      // for sched_param, sched_yield, etc
      32             : #if !defined(__DARWIN__)
      33             : #include <semaphore.h>                  // for sem_t, sem_destroy, etc
      34             : #endif
      35             : #include <signal.h>                     // for pthread_kill, SIGUSR1
      36             : #include <stdint.h>                     // for INT32_MAX
      37             : #include <stdlib.h>                     // for NULL
      38             : #include <string.h>                     // for strerror
      39             : #include <sys/time.h>                   // for timeval, gettimeofday
      40             : #include <sys/types.h>                  // for int32_t, int64_t
      41             : #include <time.h>                       // for timespec
      42             : #include "config.h"                     // for ENABLE_GC_BOEHM, etc
      43             : #include "native/llni.hpp"              // for LLNI_class_get, LLNI_WRAP
      44             : #include "threads/condition.hpp"        // for Condition
      45             : #include "threads/lock.hpp"             // for lock_monitor_enter, etc
      46             : #include "threads/mutex.hpp"            // for Mutex
      47             : #include "threads/thread.hpp"           // for DEBUGTHREADS, etc
      48             : #include "threads/threadlist.hpp"       // for ThreadList
      49             : #include "threads/ThreadRuntime.hpp"    // for ThreadRuntime
      50             : #include "vm/class.hpp"                 // for class_resolveclassmethod, etc
      51             : #include "vm/exceptions.hpp"            // for exceptions_get_exception, etc
      52             : #include "vm/global.hpp"                // for java_handle_t, functionptr
      53             : #include "vm/hook.hpp"                  // for thread_end, thread_start
      54             : #include "vm/javaobjects.hpp"           // for java_lang_Thread
      55             : #include "vm/options.hpp"               // for opt_stacksize
      56             : #include "vm/os.hpp"                    // for os
      57             : #include "vm/signallocal.hpp"
      58             : #include "vm/types.hpp"                 // for s4, s8, u2
      59             : #include "vm/utf8.hpp"
      60             : #include "vm/vm.hpp"                    // for vm_abort, vm_call_method
      61             : 
      62             : #if defined(ENABLE_GC_CACAO)
      63             : # include "mm/cacao-gc/gc.h"
      64             : #endif
      65             : 
      66             : #if defined(__DARWIN__)
      67             : 
      68             : typedef struct {
      69             :         Mutex* mutex;
      70             :         Condition* cond;
      71             :         int value;
      72             : } sem_t;
      73             : 
      74             : #else
      75             : # include <semaphore.h>
      76             : #endif
      77             : 
      78             : #include "mm/gc-boehm.hpp"
      79             : 
      80             : struct methodinfo;
      81             : 
      82             : using namespace cacao;
      83             : 
      84             : #if defined(__DARWIN__)
      85             : /* Darwin has no working semaphore implementation.  This one is taken
      86             :    from Boehm-GC. */
      87             : 
      88             : /*
      89             :    This is a very simple semaphore implementation for Darwin. It
      90             :    is implemented in terms of pthreads calls so it isn't async signal
      91             :    safe. This isn't a problem because signals aren't used to
      92             :    suspend threads on Darwin.
      93             : */
      94             :    
      95             : static int sem_init(sem_t *sem, int pshared, int value)
      96             : {
      97             :         if (pshared)
      98             :                 assert(0);
      99             : 
     100             :         sem->mutex = new Mutex();
     101             :         sem->cond  = new Condition();
     102             :         sem->value = value;
     103             : 
     104             :         return 0;
     105             : }
     106             : 
     107             : static int sem_post(sem_t *sem)
     108             : {
     109             :         sem->mutex->lock();
     110             :         sem->value++;
     111             :         sem->cond->signal();
     112             :         sem->mutex->unlock();
     113             : 
     114             :         return 0;
     115             : }
     116             : 
     117             : static int sem_wait(sem_t *sem)
     118             : {
     119             :         sem->mutex->lock();
     120             : 
     121             :         while (sem->value == 0) {
     122             :                 sem->cond->wait(sem->mutex);
     123             :         }
     124             : 
     125             :         sem->value--;
     126             :         sem->mutex->unlock();
     127             : 
     128             :         return 0;
     129             : }
     130             : 
     131             : static int sem_destroy(sem_t *sem)
     132             : {
     133             :         delete sem->cond;
     134             :         delete sem->mutex;
     135             : 
     136             :         return 0;
     137             : }
     138             : #endif /* defined(__DARWIN__) */
     139             : 
     140             : 
     141             : /* startupinfo *****************************************************************
     142             : 
     143             :    Struct used to pass info from threads_start_thread to 
     144             :    threads_startup_thread.
     145             : 
     146             : ******************************************************************************/
     147             : 
     148             : typedef struct {
     149             :         threadobject *thread;      /* threadobject for this thread             */
     150             :         functionptr   function;    /* function to run in the new thread        */
     151             :         sem_t        *psem;        /* signals when thread has been entered     */
     152             :                                    /* in the thread list                       */
     153             :         sem_t        *psem_first;  /* signals when pthread_create has returned */
     154             : } startupinfo;
     155             : 
     156             : 
     157             : /* prototypes *****************************************************************/
     158             : 
     159             : static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
     160             : static void threads_set_thread_priority(pthread_t tid, int priority);
     161             : 
     162             : 
     163             : /******************************************************************************/
     164             : /* GLOBAL VARIABLES                                                           */
     165             : /******************************************************************************/
     166             : 
     167             : /* the thread object of the current thread                                    */
     168             : /* This is either a thread-local variable defined with __thread, or           */
     169             : /* a thread-specific value stored with key threads_current_threadobject_key.  */
     170             : #if defined(HAVE___THREAD)
     171             : __thread threadobject *thread_current;
     172             : #else
     173             : pthread_key_t thread_current_key;
     174             : #endif
     175             : 
     176             : /* global mutex for stop-the-world                                            */
     177             : static Mutex* stopworldlock;
     178             : 
     179             : #if defined(ENABLE_GC_CACAO)
     180             : /* global mutex for the GC */
     181             : static Mutex* mutex_gc;
     182             : #endif
     183             : 
     184             : /* global mutex and condition for joining threads on exit */
     185             : static Condition* cond_join;
     186             : 
     187             : #if defined(ENABLE_GC_CACAO)
     188             : /* semaphore used for acknowleding thread suspension                          */
     189             : static sem_t suspend_ack;
     190             : #endif
     191             : 
     192             : 
     193             : /* threads_sem_init ************************************************************
     194             :  
     195             :    Initialize a semaphore. Checks against errors and interruptions.
     196             : 
     197             :    IN:
     198             :        sem..............the semaphore to initialize
     199             :            shared...........true if this semaphore will be shared between processes
     200             :            value............the initial value for the semaphore
     201             :    
     202             : *******************************************************************************/
     203             : 
     204         998 : void threads_sem_init(sem_t *sem, bool shared, int value)
     205             : {
     206             :         int r;
     207             : 
     208         998 :         assert(sem);
     209             : 
     210           0 :         do {
     211         998 :                 r = sem_init(sem, shared, value);
     212         998 :                 if (r == 0)
     213         998 :                         return;
     214             :         } while (errno == EINTR);
     215             : 
     216           0 :         vm_abort("sem_init failed: %s", strerror(errno));
     217             : }
     218             : 
     219             : 
     220             : /* threads_sem_wait ************************************************************
     221             :  
     222             :    Wait for a semaphore, non-interruptible.
     223             : 
     224             :    IMPORTANT: Always use this function instead of `sem_wait` directly, as
     225             :               `sem_wait` may be interrupted by signals!
     226             :   
     227             :    IN:
     228             :        sem..............the semaphore to wait on
     229             :    
     230             : *******************************************************************************/
     231             : 
     232         998 : void threads_sem_wait(sem_t *sem)
     233             : {
     234             :         int r;
     235             : 
     236         998 :         assert(sem);
     237             : 
     238           0 :         do {
     239         998 :                 r = sem_wait(sem);
     240         998 :                 if (r == 0)
     241         998 :                         return;
     242             :         } while (errno == EINTR);
     243             : 
     244           0 :         vm_abort("sem_wait failed: %s", strerror(errno));
     245             : }
     246             : 
     247             : 
     248             : /* threads_sem_post ************************************************************
     249             :  
     250             :    Increase the count of a semaphore. Checks for errors.
     251             : 
     252             :    IN:
     253             :        sem..............the semaphore to increase the count of
     254             :    
     255             : *******************************************************************************/
     256             : 
     257         998 : void threads_sem_post(sem_t *sem)
     258             : {
     259             :         int r;
     260             : 
     261         998 :         assert(sem);
     262             : 
     263             :         /* unlike sem_wait, sem_post is not interruptible */
     264             : 
     265         998 :         r = sem_post(sem);
     266         998 :         if (r == 0)
     267         998 :                 return;
     268             : 
     269           0 :         vm_abort("sem_post failed: %s", strerror(errno));
     270             : }
     271             : 
     272             : 
     273             : /* threads_stopworld ***********************************************************
     274             : 
     275             :    Stops the world from turning. All threads except the calling one
     276             :    are suspended. The function returns as soon as all threads have
     277             :    acknowledged their suspension.
     278             : 
     279             : *******************************************************************************/
     280             : 
     281             : #if defined(ENABLE_GC_CACAO)
     282             : void threads_stopworld(void)
     283             : {
     284             : #if !defined(__DARWIN__) && !defined(__CYGWIN__)
     285             :         threadobject *t;
     286             :         threadobject *self;
     287             :         bool result;
     288             :         s4 count, i;
     289             : #endif
     290             : 
     291             :         stopworldlock->lock();
     292             : 
     293             :         /* lock the threads lists */
     294             : 
     295             :         threadlist_lock();
     296             : 
     297             : #if defined(__DARWIN__)
     298             :         /*threads_cast_darwinstop();*/
     299             :         assert(0);
     300             : #elif defined(__CYGWIN__)
     301             :         /* TODO */
     302             :         assert(0);
     303             : #else
     304             :         self = THREADOBJECT;
     305             : 
     306             :         DEBUGTHREADS("stops World", self);
     307             : 
     308             :         count = 0;
     309             : 
     310             :         /* suspend all running threads */
     311             :         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
     312             :                 /* don't send the signal to ourself */
     313             : 
     314             :                 if (t == self)
     315             :                         continue;
     316             : 
     317             :                 /* don't send the signal to NEW threads (because they are not
     318             :                    completely initialized) */
     319             : 
     320             :                 if (t->state == THREAD_STATE_NEW)
     321             :                         continue;
     322             : 
     323             :                 /* send the signal */
     324             : 
     325             :                 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
     326             :                 assert(result);
     327             : 
     328             :                 /* increase threads count */
     329             : 
     330             :                 count++;
     331             :         }
     332             : 
     333             :         /* wait for all threads signaled to suspend */
     334             :         for (i = 0; i < count; i++)
     335             :                 threads_sem_wait(&suspend_ack);
     336             : #endif
     337             : 
     338             :         /* ATTENTION: Don't unlock the threads-lists here so that
     339             :            non-signaled NEW threads can't change their state and execute
     340             :            code. */
     341             : }
     342             : #endif
     343             : 
     344             : 
     345             : /* threads_startworld **********************************************************
     346             : 
     347             :    Starts the world again after it has previously been stopped. 
     348             : 
     349             : *******************************************************************************/
     350             : 
     351             : #if defined(ENABLE_GC_CACAO)
     352             : void threads_startworld(void)
     353             : {
     354             : #if !defined(__DARWIN__) && !defined(__CYGWIN__)
     355             :         threadobject *t;
     356             :         threadobject *self;
     357             :         bool result;
     358             :         s4 count, i;
     359             : #endif
     360             : 
     361             : #if defined(__DARWIN__)
     362             :         /*threads_cast_darwinresume();*/
     363             :         assert(0);
     364             : #elif defined(__IRIX__)
     365             :         threads_cast_irixresume();
     366             : #elif defined(__CYGWIN__)
     367             :         /* TODO */
     368             :         assert(0);
     369             : #else
     370             :         self = THREADOBJECT;
     371             : 
     372             :         DEBUGTHREADS("starts World", self);
     373             : 
     374             :         count = 0;
     375             : 
     376             :         /* resume all thread we haltet */
     377             :         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
     378             :                 /* don't send the signal to ourself */
     379             : 
     380             :                 if (t == self)
     381             :                         continue;
     382             : 
     383             :                 /* don't send the signal to NEW threads (because they are not
     384             :                    completely initialized) */
     385             : 
     386             :                 if (t->state == THREAD_STATE_NEW)
     387             :                         continue;
     388             : 
     389             :                 /* send the signal */
     390             : 
     391             :                 result = threads_resume_thread(t);
     392             :                 assert(result);
     393             : 
     394             :                 /* increase threads count */
     395             : 
     396             :                 count++;
     397             :         }
     398             : 
     399             :         /* wait for all threads signaled to suspend */
     400             :         for (i = 0; i < count; i++)
     401             :                 threads_sem_wait(&suspend_ack);
     402             : 
     403             : #endif
     404             : 
     405             :         /* unlock the threads lists */
     406             : 
     407             :         threadlist_unlock();
     408             : 
     409             :         stopworldlock->unlock();
     410             : }
     411             : #endif
     412             : 
     413             : 
     414             : /* threads_impl_thread_clear ***************************************************
     415             : 
     416             :    Clears all fields in threadobject the way an MZERO would have
     417             :    done. MZERO cannot be used anymore because it would mess up the
     418             :    pthread_* bits.
     419             : 
     420             :    IN:
     421             :       t....the threadobject
     422             : 
     423             : *******************************************************************************/
     424             : 
     425           0 : void threads_impl_thread_clear(threadobject *t)
     426             : {
     427           0 :         t->object = NULL;
     428             : 
     429           0 :         t->thinlock = 0;
     430             : 
     431           0 :         t->index             = 0;
     432           0 :         t->flags             = 0;
     433           0 :         t->state             = THREAD_STATE_NEW;
     434           0 :         t->is_in_active_list = false;
     435             : 
     436           0 :         t->impl.tid = 0;
     437             : 
     438             : #if defined(__DARWIN__)
     439             :         t->impl.mach_thread = 0;
     440             : #endif
     441             : 
     442           0 :         t->interrupted = false;
     443           0 :         t->signaled    = false;
     444             : 
     445           0 :         t->suspended      = false;
     446           0 :         t->suspend_reason = SUSPEND_REASON_NONE;
     447             : 
     448           0 :         t->pc = NULL;
     449             : 
     450           0 :         t->_exceptionptr   = NULL;
     451           0 :         t->_stackframeinfo = NULL;
     452           0 :         t->_localref_table = NULL;
     453             : 
     454             : #if defined(ENABLE_INTRP)
     455             :         t->_global_sp = NULL;
     456             : #endif
     457             : 
     458             : #if defined(ENABLE_GC_CACAO)
     459             :         t->gc_critical = false;
     460             : 
     461             :         t->ss = NULL;
     462             :         t->es = NULL;
     463             : #endif
     464             : 
     465             :         // Simply reuse the existing dump memory.
     466           0 : }
     467             : 
     468             : /* threads_impl_thread_reuse ***************************************************
     469             : 
     470             :    Resets some implementation fields in threadobject. This was
     471             :    previously done in threads_impl_thread_new.
     472             : 
     473             :    IN:
     474             :       t....the threadobject
     475             : 
     476             : *******************************************************************************/
     477             : 
     478         793 : void threads_impl_thread_reuse(threadobject *t)
     479             : {
     480             :         /* get the pthread id */
     481             : 
     482         793 :         t->impl.tid = pthread_self();
     483         793 : }
     484             : 
     485         282 : void threads_impl_clear_heap_pointers(threadobject *t)
     486             : {
     487         282 :         t->object     = 0;
     488         282 :         t->flc_object = 0;
     489         282 : }
     490             : 
     491             : /* threads_impl_preinit ********************************************************
     492             : 
     493             :    Do some early initialization of stuff required.
     494             : 
     495             :    ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
     496             :    is called AFTER this function!
     497             : 
     498             : *******************************************************************************/
     499             : 
     500         163 : void threads_impl_preinit(void)
     501             : {
     502         163 :         stopworldlock = new Mutex();
     503             : 
     504             :         /* initialize exit mutex and condition (on exit we join all
     505             :            threads) */
     506             : 
     507         163 :         cond_join = new Condition();
     508             : 
     509             : #if defined(ENABLE_GC_CACAO)
     510             :         /* initialize the GC mutex & suspend semaphore */
     511             : 
     512             :         mutex_gc = new Mutex();
     513             :         threads_sem_init(&suspend_ack, 0, 0);
     514             : #endif
     515             : 
     516             : #if !defined(HAVE___THREAD)
     517             :         int result = pthread_key_create(&thread_current_key, NULL);
     518             :         if (result != 0)
     519             :                 os::abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
     520             : #endif
     521         163 : }
     522             : 
     523             : 
     524             : /* threads_mutex_gc_lock *******************************************************
     525             : 
     526             :    Enter the global GC mutex.
     527             : 
     528             : *******************************************************************************/
     529             : 
     530             : #if defined(ENABLE_GC_CACAO)
     531             : void threads_mutex_gc_lock(void)
     532             : {
     533             :         mutex_gc->lock();
     534             : }
     535             : #endif
     536             : 
     537             : 
     538             : /* threads_mutex_gc_unlock *****************************************************
     539             : 
     540             :    Leave the global GC mutex.
     541             : 
     542             : *******************************************************************************/
     543             : 
     544             : #if defined(ENABLE_GC_CACAO)
     545             : void threads_mutex_gc_unlock(void)
     546             : {
     547             :         mutex_gc->unlock();
     548             : }
     549             : #endif
     550             : 
     551             : /* threads_impl_init ***********************************************************
     552             : 
     553             :    Initializes the implementation specific bits.
     554             : 
     555             : *******************************************************************************/
     556             : 
     557         163 : void threads_impl_init(void)
     558             : {
     559             :         pthread_attr_t attr;
     560             :         int            result;
     561             : 
     562         163 :         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
     563             : 
     564             :         /* Initialize the thread attribute object. */
     565             : 
     566         163 :         result = pthread_attr_init(&attr);
     567             : 
     568         163 :         if (result != 0)
     569           0 :                 os::abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
     570             : 
     571         163 :         result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     572             : 
     573         163 :         if (result != 0)
     574           0 :                 os::abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
     575         163 : }
     576             : 
     577             : 
     578             : /* threads_startup_thread ******************************************************
     579             : 
     580             :    Thread startup function called by pthread_create.
     581             : 
     582             :    Thread which have a startup.function != NULL are marked as internal
     583             :    threads. All other threads are threated as normal Java threads.
     584             : 
     585             :    NOTE: This function is not called directly by pthread_create. The Boehm GC
     586             :          inserts its own GC_start_routine in between, which then calls
     587             :                  threads_startup.
     588             : 
     589             :    IN:
     590             :       arg..........the argument passed to pthread_create, ie. a pointer to
     591             :                        a startupinfo struct. CAUTION: When the `psem` semaphore
     592             :                                    is posted, the startupinfo struct becomes invalid! (It
     593             :                                    is allocated on the stack of threads_start_thread.)
     594             : 
     595             : ******************************************************************************/
     596             : 
     597         499 : static void *threads_startup_thread(void *arg)
     598             : {
     599             :         startupinfo  *startup;
     600             :         threadobject *t;
     601             :         sem_t        *psem;
     602             :         classinfo    *c;
     603             :         methodinfo   *m;
     604             :         functionptr   function;
     605             : 
     606             : #if defined(ENABLE_GC_BOEHM)
     607             : # if !defined(__DARWIN__)
     608             :         struct GC_stack_base sb;
     609             :         int result;
     610             : # endif
     611             : #endif
     612             : 
     613             : #if defined(ENABLE_INTRP)
     614             :         u1 *intrp_thread_stack;
     615             : #endif
     616             : 
     617             : #if defined(ENABLE_INTRP)
     618             :         /* create interpreter stack */
     619             : 
     620             :         if (opt_intrp) {
     621             :                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
     622             :                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
     623             :         }
     624             :         else
     625             :                 intrp_thread_stack = NULL;
     626             : #endif
     627             : 
     628             :         /* get passed startupinfo structure and the values in there */
     629             : 
     630         499 :         startup = (startupinfo*) arg;
     631             : 
     632         499 :         t        = startup->thread;
     633         499 :         function = startup->function;
     634         499 :         psem     = startup->psem;
     635             : 
     636             :         /* Seems like we've encountered a situation where thread->tid was
     637             :            not set by pthread_create. We alleviate this problem by waiting
     638             :            for pthread_create to return. */
     639             : 
     640         499 :         threads_sem_wait(startup->psem_first);
     641             : 
     642             : #if defined(__DARWIN__)
     643             :         t->impl.mach_thread = mach_thread_self();
     644             : #endif
     645             : 
     646             :         /* Now that we are in the new thread, we can store the internal
     647             :            thread data-structure in the TSD. */
     648             : 
     649         499 :         thread_set_current(t);
     650             : 
     651             : #if defined(ENABLE_GC_BOEHM)
     652             : # if defined(__DARWIN__)
     653             :         // This is currently not implemented in Boehm-GC.  Just fail silently.
     654             : # else
     655             :         /* Register the thread with Boehm-GC.  This must happen before the
     656             :            thread allocates any memory from the GC heap.*/
     657             : 
     658         499 :         result = GC_get_stack_base(&sb);
     659             : 
     660         499 :         if (result != 0)
     661           0 :                 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
     662             : 
     663         499 :         GC_register_my_thread(&sb);
     664             : # endif
     665             : #endif
     666             : 
     667             :         // Get the java.lang.Thread object for this thread.
     668         499 :         java_handle_t* object = LLNI_WRAP(t->object);
     669         499 :         java_lang_Thread jlt(object);
     670             : 
     671             :         /* set our priority */
     672             : 
     673         499 :         threads_set_thread_priority(t->impl.tid, jlt.get_priority());
     674             : 
     675             :         /* tell threads_startup_thread that we registered ourselves */
     676             :         /* CAUTION: *startup becomes invalid with this!             */
     677             : 
     678         499 :         startup = NULL;
     679         499 :         threads_sem_post(psem);
     680             : 
     681             : #if defined(ENABLE_INTRP)
     682             :         /* set interpreter stack */
     683             : 
     684             :         if (opt_intrp)
     685             :                 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
     686             : #endif
     687             : 
     688             :         // Hook point just before the threads initial method is executed.
     689         499 :         Hook::thread_start(t);
     690             : 
     691         499 :         DEBUGTHREADS("starting", t);
     692             : 
     693             :         /* find and run the Thread.run()V method if no other function was passed */
     694             : 
     695         499 :         if (function == NULL) {
     696          10 :                 c = ThreadRuntime::get_thread_class_from_object(object);
     697             : 
     698          10 :                 m = class_resolveclassmethod(c, utf8::run, utf8::void__void, c, true);
     699             : 
     700          10 :                 if (m == NULL)
     701           0 :                         vm_abort("threads_startup_thread: run() method not found in class");
     702             : 
     703          10 :                 java_handle_t *h = ThreadRuntime::get_vmthread_handle(jlt);
     704             : 
     705             :                 /* Run the thread. */
     706             : 
     707          10 :                 (void) vm_call_method(m, h);
     708             :         }
     709             :         else {
     710             :                 /* call passed function, e.g. finalizer_thread */
     711             : 
     712         489 :                 (function)();
     713             :         }
     714             : 
     715         151 :         DEBUGTHREADS("stopping", t);
     716             : 
     717             :         // Hook point just after the threads initial method returned.
     718         151 :         Hook::thread_end(t);
     719             : 
     720             :         /* We ignore the return value. */
     721             : 
     722         151 :         (void) thread_detach_current_thread();
     723             : 
     724         151 :         return NULL;
     725             : }
     726             : 
     727             : 
     728             : /* threads_impl_thread_start ***************************************************
     729             : 
     730             :    Start a thread in the JVM.  Both (vm internal and java) thread
     731             :    objects exist.
     732             : 
     733             :    IN:
     734             :       thread....the thread object
     735             :           f.........function to run in the new thread. NULL means that the
     736             :                     "run" method of the object `t` should be called
     737             : 
     738             : ******************************************************************************/
     739             : 
     740         499 : void threads_impl_thread_start(threadobject *thread, functionptr f)
     741             : {
     742             :         sem_t          sem;
     743             :         sem_t          sem_first;
     744             :         pthread_attr_t attr;
     745             :         startupinfo    startup;
     746             :         int            result;
     747             : 
     748             :         /* fill startupinfo structure passed by pthread_create to
     749             :          * threads_startup_thread */
     750             : 
     751         499 :         startup.thread     = thread;
     752         499 :         startup.function   = f;              /* maybe we don't call Thread.run()V */
     753         499 :         startup.psem       = &sem;
     754         499 :         startup.psem_first = &sem_first;
     755             : 
     756         499 :         threads_sem_init(&sem, 0, 0);
     757         499 :         threads_sem_init(&sem_first, 0, 0);
     758             : 
     759             :         /* Initialize thread attributes. */
     760             : 
     761         499 :         result = pthread_attr_init(&attr);
     762             : 
     763         499 :         if (result != 0)
     764           0 :                 os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
     765             : 
     766         499 :     result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     767             : 
     768         499 :     if (result != 0)
     769           0 :                 os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
     770             : 
     771             :         /* initialize thread stacksize */
     772             : 
     773         499 :         result = pthread_attr_setstacksize(&attr, opt_stacksize);
     774             : 
     775         499 :         if (result != 0)
     776           0 :                 os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
     777             : 
     778             :         /* create the thread */
     779             : 
     780         499 :         result = pthread_create(&(thread->impl.tid), &attr, threads_startup_thread, &startup);
     781             : 
     782         499 :         if (result != 0)
     783           0 :                 os::abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
     784             : 
     785             :         /* destroy the thread attributes */
     786             : 
     787         499 :         result = pthread_attr_destroy(&attr);
     788             : 
     789         499 :         if (result != 0)
     790           0 :                 os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
     791             : 
     792             :         /* signal that pthread_create has returned, so thread->tid is valid */
     793             : 
     794         499 :         threads_sem_post(&sem_first);
     795             : 
     796             :         /* wait here until the thread has entered itself into the thread list */
     797             : 
     798         499 :         threads_sem_wait(&sem);
     799             : 
     800             :         /* cleanup */
     801             : 
     802         499 :         sem_destroy(&sem);
     803         499 :         sem_destroy(&sem_first);
     804         499 : }
     805             : 
     806             : 
     807             : /* threads_set_thread_priority *************************************************
     808             : 
     809             :    Set the priority of the given thread.
     810             : 
     811             :    IN:
     812             :       tid..........thread id
     813             :           priority.....priority to set
     814             : 
     815             : ******************************************************************************/
     816             : 
     817           0 : void threads_set_thread_priority(threadobject *t, int priority)
     818             : {
     819           0 :         threads_set_thread_priority(t->impl.tid, priority);
     820           0 : }
     821             : 
     822             : 
     823         662 : static void threads_set_thread_priority(pthread_t tid, int priority)
     824             : {
     825             :         struct sched_param schedp;
     826             :         int policy;
     827             : 
     828         662 :         pthread_getschedparam(tid, &policy, &schedp);
     829         662 :         schedp.sched_priority = priority;
     830         662 :         pthread_setschedparam(tid, policy, &schedp);
     831         662 : }
     832             : 
     833             : 
     834             : /**
     835             :  * Detaches the current thread from the VM.
     836             :  *
     837             :  * @return true on success, false otherwise
     838             :  */
     839         282 : bool thread_detach_current_thread(void)
     840             : {
     841         282 :         threadobject* t = thread_get_current();
     842             : 
     843             :         /* Sanity check. */
     844             : 
     845         282 :         assert(t != NULL);
     846             : 
     847             :     /* If the given thread has already been detached, this operation
     848             :            is a no-op. */
     849             : 
     850         282 :         if (thread_is_attached(t) == false)
     851           0 :                 return true;
     852             : 
     853         282 :         DEBUGTHREADS("detaching", t);
     854             : 
     855         282 :         java_handle_t* object = LLNI_WRAP(t->object);
     856         282 :         java_lang_Thread jlt(object);
     857             : 
     858             : #if defined(ENABLE_JAVASE)
     859         282 :         java_handle_t* group = jlt.get_group();
     860             : 
     861             :     /* If there's an uncaught exception, call uncaughtException on the
     862             :        thread's exception handler, or the thread's group if this is
     863             :        unset. */
     864             : 
     865         282 :         java_handle_t* e = exceptions_get_and_clear_exception();
     866             : 
     867         282 :     if (e != NULL) {
     868             :                 /* We use the type void* for handler here, as it's not trivial
     869             :                    to build the java_lang_Thread_UncaughtExceptionHandler
     870             :                    header file with cacaoh. */
     871             : 
     872           0 :                 java_handle_t *handler = ThreadRuntime::get_thread_exception_handler(jlt);
     873             : 
     874             :                 classinfo*     c;
     875             :                 java_handle_t* h;
     876             : 
     877           0 :                 if (handler != NULL) {
     878           0 :                         LLNI_class_get(handler, c);
     879           0 :                         h = (java_handle_t *) handler;
     880             :                 }
     881             :                 else {
     882           0 :                         LLNI_class_get(group, c);
     883           0 :                         h = (java_handle_t *) group;
     884             :                 }
     885             : 
     886             :                 methodinfo* m = class_resolveclassmethod(c,
     887             :                                                                                                  utf8::uncaughtException,
     888             :                                                                                                  utf8::java_lang_Thread_java_lang_Throwable__V,
     889             :                                                                                                  NULL,
     890           0 :                                                                                                  true);
     891             : 
     892           0 :                 if (m == NULL)
     893           0 :                         return false;
     894             : 
     895           0 :                 (void) vm_call_method(m, h, object, e);
     896             : 
     897           0 :                 if (exceptions_get_exception())
     898           0 :                         return false;
     899             :     }
     900             : 
     901             :         /* XXX TWISTI: should all threads be in a ThreadGroup? */
     902             : 
     903             :         /* Remove thread from the thread group. */
     904             : 
     905         282 :         if (group != NULL) {
     906             :                 classinfo* c;
     907         272 :                 LLNI_class_get(group, c);
     908             : 
     909         272 :                 methodinfo *m = ThreadRuntime::get_threadgroup_remove_method(c);
     910             : 
     911         272 :                 if (m == NULL)
     912           0 :                         return false;
     913             : 
     914         272 :                 (void) vm_call_method(m, group, object);
     915             : 
     916         272 :                 if (exceptions_get_exception())
     917           0 :                         return false;
     918             : 
     919             :                 // Clear the ThreadGroup in the Java thread object (Mauve
     920             :                 // test: gnu/testlet/java/lang/Thread/getThreadGroup).
     921         272 :                 jlt.set_group(NULL);
     922             :         }
     923             : #endif
     924             : 
     925             :         /* Thread has terminated. */
     926             : 
     927         282 :         thread_set_state_terminated(t);
     928             : 
     929             :         /* Notify all threads waiting on this thread.  These are joining
     930             :            this thread. */
     931             : 
     932             :         /* XXX Care about exceptions? */
     933         282 :         (void) lock_monitor_enter(jlt.get_handle());
     934             :         
     935         282 :         lock_notify_all_object(jlt.get_handle());
     936             : 
     937             :         /* XXX Care about exceptions? */
     938         282 :         (void) lock_monitor_exit(jlt.get_handle());
     939             : 
     940         282 :         t->waitmutex->lock();
     941         282 :         t->impl.tid = 0;
     942         282 :         t->waitmutex->unlock();
     943             : 
     944             :         {
     945         282 :                 MutexLocker lock(ThreadList::get()->mutex());
     946             : 
     947             :                 /* Free the internal thread data-structure. */
     948             : 
     949         282 :                 thread_free(t);
     950             : 
     951             :                 /* Signal that this thread has finished and leave the mutex. */
     952             : 
     953         282 :                 cond_join->signal();
     954             :         }
     955             : 
     956         282 :         t->suspendmutex->lock();
     957         282 :         t->suspendmutex->unlock();
     958             : 
     959         282 :         return true;
     960             : }
     961             : 
     962             : 
     963             : /**
     964             :  * Internal helper function which suspends the current thread. This is
     965             :  * the core method of the suspension mechanism actually blocking the
     966             :  * execution until the suspension reason is cleared again. Note that
     967             :  * the current thread needs to hold the suspension mutex while calling
     968             :  * this function.
     969             :  */
     970           0 : static void threads_suspend_self()
     971             : {
     972           0 :         threadobject* thread = THREADOBJECT;
     973             : 
     974           0 :         DEBUGTHREADS("suspending", thread);
     975             : 
     976             :         // Mark thread as suspended.
     977           0 :         assert(!thread->suspended);
     978           0 :         assert(thread->suspend_reason != SUSPEND_REASON_NONE);
     979           0 :         thread->suspended = true;
     980             : 
     981             :         // Acknowledge the suspension.
     982           0 :         thread->suspendcond->broadcast();
     983             : 
     984             : #if defined(ENABLE_GC_CACAO)
     985             :         // If we are stopping the world, we should send a global ack.
     986             :         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD)
     987             :                 threads_sem_post(&suspend_ack);
     988             : #endif
     989             : 
     990             :         // Release the suspension mutex and wait till we are resumed.
     991           0 :         while (thread->suspend_reason != SUSPEND_REASON_NONE)
     992           0 :                 thread->suspendcond->wait(thread->suspendmutex);
     993             : 
     994             : #if defined(ENABLE_GC_CACAO)
     995             :         // XXX This is propably not ok!
     996             :         // If we are starting the world, we should send a global ack.
     997             :         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD)
     998             :                 threads_sem_post(&suspend_ack);
     999             : #endif
    1000             : 
    1001             :         // Mark thread as not suspended.
    1002           0 :         assert(thread->suspended);
    1003           0 :         assert(thread->suspend_reason == SUSPEND_REASON_NONE);
    1004           0 :         thread->suspended = false;
    1005             : 
    1006           0 :         DEBUGTHREADS("resuming", thread);
    1007           0 : }
    1008             : 
    1009             : 
    1010             : /**
    1011             :  * Suspend the passed thread. Execution of that thread stops until the thread
    1012             :  * is explicitly resumed again.
    1013             :  *
    1014             :  * @param thread The thread to be suspended.
    1015             :  * @param reason Reason for suspending the given thread.
    1016             :  * @return True of operation was successful, false otherwise.
    1017             :  */
    1018           0 : bool threads_suspend_thread(threadobject *thread, SuspendReason reason)
    1019             : {
    1020             :         // Sanity check.
    1021           0 :         assert(reason != SUSPEND_REASON_NONE);
    1022             : 
    1023             :         // Guard this with the suspension mutex.
    1024           0 :         MutexLocker ml(*thread->suspendmutex);
    1025             : 
    1026             :         // Check if thread is already suspended.
    1027           0 :         if (thread->suspended)
    1028           0 :                 return false;
    1029             : 
    1030             :         // Check if thread is in the process of suspending.
    1031           0 :         if (thread->suspend_reason != SUSPEND_REASON_NONE)
    1032           0 :                 return false;
    1033             : 
    1034             :         // Set the reason for suspending the thread.
    1035           0 :         thread->suspend_reason = reason;
    1036             : 
    1037           0 :         if (thread == THREADOBJECT) {
    1038             :                 // We already hold the suspension mutex and can suspend ourselves
    1039             :                 // immediately without using signals at all.
    1040           0 :                 threads_suspend_self();
    1041             :         }
    1042             :         else {
    1043             :                 // Send the suspend signal to the other thread.
    1044           0 :                 if (!thread->impl.tid)
    1045           0 :                         return false;
    1046           0 :                 if (pthread_kill(thread->impl.tid, SIGUSR1) != 0)
    1047           0 :                         os::abort_errno("threads_suspend_thread: pthread_kill failed");
    1048             : 
    1049             :                 // Wait for the thread to acknowledge the suspension.
    1050           0 :                 while (!thread->suspended)
    1051           0 :                         thread->suspendcond->wait(thread->suspendmutex);
    1052             :         }
    1053             : 
    1054           0 :         return true;
    1055             : }
    1056             : 
    1057             : 
    1058             : /**
    1059             :  * Resumes execution of the passed thread.
    1060             :  *
    1061             :  * @param thread The thread to be resumed.
    1062             :  * @param reason Reason for suspending the given thread.
    1063             :  * @return True of operation was successful, false otherwise.
    1064             :  */
    1065           0 : bool threads_resume_thread(threadobject *thread, SuspendReason reason)
    1066             : {
    1067             :         // Sanity check.
    1068           0 :         assert(thread != THREADOBJECT);
    1069           0 :         assert(reason != SUSPEND_REASON_NONE);
    1070             : 
    1071             :         // Guard this with the suspension mutex.
    1072           0 :         MutexLocker ml(*thread->suspendmutex);
    1073             : 
    1074             :         // Check if thread really is suspended.
    1075           0 :         if (!thread->suspended)
    1076           0 :                 return false;
    1077             : 
    1078             :         // Threads can only be resumed for the same reason they were suspended.
    1079           0 :         if (thread->suspend_reason != reason)
    1080           0 :                 return false;
    1081             : 
    1082             :         // Clear the reason for suspending the thread.
    1083           0 :         thread->suspend_reason = SUSPEND_REASON_NONE;
    1084             : 
    1085             :         // Tell everyone that the thread should resume.
    1086           0 :         thread->suspendcond->broadcast();
    1087             : 
    1088           0 :         return true;
    1089             : }
    1090             : 
    1091             : 
    1092             : /**
    1093             :  * Acknowledges the suspension of the current thread.
    1094             :  */
    1095           0 : void threads_suspend_ack()
    1096             : {
    1097           0 :         threadobject* thread = THREADOBJECT;
    1098             : 
    1099             :         // Guard this with the suspension mutex.
    1100           0 :         MutexLocker ml(*thread->suspendmutex);
    1101             : 
    1102             :         // Suspend ourselves while holding the suspension mutex.
    1103           0 :         threads_suspend_self();
    1104           0 : }
    1105             : 
    1106             : 
    1107             : /* threads_join_all_threads ****************************************************
    1108             : 
    1109             :    Join all non-daemon threads.
    1110             : 
    1111             : *******************************************************************************/
    1112             : 
    1113         131 : void threads_join_all_threads(void)
    1114             : {
    1115             :         threadobject *t;
    1116             : 
    1117             :         /* get current thread */
    1118             : 
    1119         131 :         t = THREADOBJECT;
    1120             : 
    1121             :         /* This thread is waiting for all non-daemon threads to exit. */
    1122             : 
    1123         131 :         thread_set_state_waiting(t);
    1124             : 
    1125             :         /* enter join mutex */
    1126             : 
    1127         131 :         MutexLocker lock(ThreadList::get()->mutex());
    1128             : 
    1129             :         /* Wait for condition as long as we have non-daemon threads.  We
    1130             :            compare against 1 because the current (main thread) is also a
    1131             :            non-daemon thread. */
    1132             : 
    1133         262 :         while (ThreadList::get()->get_number_of_non_daemon_threads() > 1)
    1134           0 :                 ThreadList::get()->wait_cond(cond_join);
    1135         131 : }
    1136             : 
    1137             : 
    1138             : /* threads_timespec_earlier ****************************************************
    1139             : 
    1140             :    Return true if timespec tv1 is earlier than timespec tv2.
    1141             : 
    1142             :    IN:
    1143             :       tv1..........first timespec
    1144             :           tv2..........second timespec
    1145             : 
    1146             :    RETURN VALUE:
    1147             :       true, if the first timespec is earlier
    1148             : 
    1149             : *******************************************************************************/
    1150             : 
    1151           8 : static inline bool threads_timespec_earlier(const struct timespec *tv1,
    1152             :                                                                                         const struct timespec *tv2)
    1153             : {
    1154             :         return (tv1->tv_sec < tv2->tv_sec)
    1155             :                                 ||
    1156           8 :                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
    1157             : }
    1158             : 
    1159             : 
    1160             : /* threads_current_time_is_earlier_than ****************************************
    1161             : 
    1162             :    Check if the current time is earlier than the given timespec.
    1163             : 
    1164             :    IN:
    1165             :       tv...........the timespec to compare against
    1166             : 
    1167             :    RETURN VALUE:
    1168             :       true, if the current time is earlier
    1169             : 
    1170             : *******************************************************************************/
    1171             : 
    1172           8 : static bool threads_current_time_is_earlier_than(const struct timespec *tv)
    1173             : {
    1174             :         struct timeval tvnow;
    1175             :         struct timespec tsnow;
    1176             : 
    1177             :         /* get current time */
    1178             : 
    1179           8 :         if (gettimeofday(&tvnow, NULL) != 0)
    1180           0 :                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
    1181             : 
    1182             :         /* convert it to a timespec */
    1183             : 
    1184           8 :         tsnow.tv_sec = tvnow.tv_sec;
    1185           8 :         tsnow.tv_nsec = tvnow.tv_usec * 1000;
    1186             : 
    1187             :         /* compare current time with the given timespec */
    1188             : 
    1189           8 :         return threads_timespec_earlier(&tsnow, tv);
    1190             : }
    1191             : 
    1192             : 
    1193             : /* threads_wait_with_timeout ***************************************************
    1194             : 
    1195             :    Wait until the given point in time on a monitor until either
    1196             :    we are notified, we are interrupted, or the time is up.
    1197             : 
    1198             :    IN:
    1199             :       t............the current thread
    1200             :           wakeupTime...absolute (latest) wakeup time
    1201             :                            If both tv_sec and tv_nsec are zero, this function
    1202             :                                            waits for an unlimited amount of time.
    1203             : 
    1204             : *******************************************************************************/
    1205             : 
    1206       20011 : static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime, bool parking)
    1207             : {
    1208             :         // Acquire the waitmutex.
    1209       20011 :         t->waitmutex->lock();
    1210             : 
    1211             :         /* wait on waitcond */
    1212             : 
    1213       20015 :         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
    1214             :                 /* with timeout */
    1215          12 :                 while (!t->interrupted && !(parking ? t->park_permit : t->signaled)
    1216             :                            && threads_current_time_is_earlier_than(wakeupTime))
    1217             :                 {
    1218           4 :                         if (parking)
    1219           0 :                                 thread_set_state_timed_parked(t);
    1220             :                         else
    1221           4 :                                 thread_set_state_timed_waiting(t);
    1222             : 
    1223           4 :                         t->waitcond->timedwait(t->waitmutex, wakeupTime);
    1224             : 
    1225           4 :                         thread_set_state_runnable(t);
    1226             :                 }
    1227             :         }
    1228             :         else {
    1229             :                 /* no timeout */
    1230       40021 :                 while (!t->interrupted && !(parking ? t->park_permit : t->signaled)) {
    1231           7 :                         if (parking)
    1232           0 :                                 thread_set_state_parked(t);
    1233             :                         else
    1234           7 :                                 thread_set_state_waiting(t);
    1235             : 
    1236           7 :                         t->waitcond->wait(t->waitmutex);
    1237             : 
    1238           7 :                         thread_set_state_runnable(t);
    1239             :                 }
    1240             :         }
    1241             : 
    1242       20011 :         if (parking)
    1243           0 :                 t->park_permit = false;
    1244             : 
    1245             :         // Release the waitmutex.
    1246       20011 :         t->waitmutex->unlock();
    1247       20011 : }
    1248             : 
    1249             : 
    1250             : /* threads_wait_with_timeout_relative ******************************************
    1251             : 
    1252             :    Wait for the given maximum amount of time on a monitor until either
    1253             :    we are notified, we are interrupted, or the time is up.
    1254             : 
    1255             :    IN:
    1256             :       t............the current thread
    1257             :           millis.......milliseconds to wait
    1258             :           nanos........nanoseconds to wait
    1259             : 
    1260             : *******************************************************************************/
    1261             : 
    1262       20010 : void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
    1263             :                                                                                 s4 nanos)
    1264             : {
    1265             :         struct timespec wakeupTime;
    1266             : 
    1267             :         /* calculate the the (latest) wakeup time */
    1268             : 
    1269       20010 :         threads_calc_absolute_time(&wakeupTime, millis, nanos);
    1270             : 
    1271             :         /* wait */
    1272             : 
    1273       20010 :         threads_wait_with_timeout(thread, &wakeupTime, false);
    1274       20010 : }
    1275             : 
    1276             : 
    1277             : /* threads_calc_absolute_time **************************************************
    1278             : 
    1279             :    Calculate the absolute point in time a given number of ms and ns from now.
    1280             : 
    1281             :    IN:
    1282             :       millis............milliseconds from now
    1283             :           nanos.............nanoseconds from now
    1284             : 
    1285             :    OUT:
    1286             :       *tm...............receives the timespec of the absolute point in time
    1287             : 
    1288             : *******************************************************************************/
    1289             : 
    1290       20011 : static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
    1291             : {
    1292             :         // (at least with GNU classpath) we know that 0 <= nanos <= 999999
    1293             :         do {
    1294       20011 :                 if (!millis && !nanos)
    1295       20007 :                         break;
    1296             :                 struct timeval tv;
    1297           4 :                 gettimeofday(&tv, NULL);
    1298           4 :                 s8 secs = tv.tv_sec + millis / 1000;
    1299           4 :                 if (secs > INT32_MAX)        // integer overflow
    1300           0 :                         break;
    1301           4 :                 tv.tv_sec = secs;
    1302           4 :                 millis %= 1000;
    1303           4 :                 long nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
    1304           4 :                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
    1305           4 :                 if (tm->tv_sec < tv.tv_sec) // integer overflow
    1306           0 :                         break;
    1307           4 :                 tm->tv_nsec = nsec % 1000000000;
    1308           4 :                 return;
    1309             :         } while (0);
    1310       20007 :         tm->tv_sec = 0;
    1311       20007 :         tm->tv_nsec = 0;
    1312             : }
    1313             : 
    1314             : 
    1315             : /* threads_thread_interrupt ****************************************************
    1316             : 
    1317             :    Interrupt the given thread.
    1318             : 
    1319             :    The thread gets the "waitcond" signal and 
    1320             :    its interrupted flag is set to true.
    1321             : 
    1322             :    IN:
    1323             :       thread............the thread to interrupt
    1324             : 
    1325             : *******************************************************************************/
    1326             : 
    1327       20000 : void threads_thread_interrupt(threadobject *t)
    1328             : {
    1329             :         /* Signal the thread a "waitcond" and tell it that it has been
    1330             :            interrupted. */
    1331             : 
    1332       20000 :         t->waitmutex->lock();
    1333             : 
    1334       20000 :         DEBUGTHREADS("interrupted", t);
    1335             : 
    1336             :         /* Interrupt blocking system call using a signal. */
    1337             : 
    1338       20000 :         if (t->impl.tid)
    1339       20000 :                 pthread_kill(t->impl.tid, Signal_INTERRUPT_SYSTEM_CALL);
    1340             : 
    1341       20000 :         t->waitcond->signal();
    1342             : 
    1343       20000 :         t->interrupted = true;
    1344             : 
    1345       20000 :         t->waitmutex->unlock();
    1346       20000 : }
    1347             : 
    1348             : 
    1349             : /**
    1350             :  * Sleep the current thread for the specified amount of time.
    1351             :  *
    1352             :  * @param millis Milliseconds to sleep.
    1353             :  * @param nanos  Nanoseconds to sleep.
    1354             :  */
    1355           1 : void threads_sleep(int64_t millis, int32_t nanos)
    1356             : {
    1357             :         threadobject    *t;
    1358             :         struct timespec  wakeupTime;
    1359             :         bool             interrupted;
    1360             : 
    1361           1 :         if (millis < 0) {
    1362             : /*              exceptions_throw_illegalargumentexception(); */
    1363           0 :                 exceptions_throw_illegalargumentexception();
    1364           0 :                 return;
    1365             :         }
    1366             : 
    1367           1 :         t = thread_get_current();
    1368             : 
    1369           1 :         if (thread_is_interrupted(t) && !exceptions_get_exception()) {
    1370             :                 /* Clear interrupted flag (Mauve test:
    1371             :                    gnu/testlet/java/lang/Thread/interrupt). */
    1372             : 
    1373           0 :                 thread_set_interrupted(t, false);
    1374             : 
    1375             : /*              exceptions_throw_interruptedexception("sleep interrupted"); */
    1376           0 :                 exceptions_throw_interruptedexception();
    1377           0 :                 return;
    1378             :         }
    1379             : 
    1380             :         // (Note taken from classpath/vm/reference/java/lang/VMThread.java (sleep))
    1381             :         // Note: JDK treats a zero length sleep is like Thread.yield(),
    1382             :         // without checking the interrupted status of the thread.  It's
    1383             :         // unclear if this is a bug in the implementation or the spec.
    1384             :         // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 */
    1385           1 :         if (millis == 0 && nanos == 0) {
    1386           0 :                 threads_yield();
    1387             :         }
    1388             :         else {
    1389           1 :                 threads_calc_absolute_time(&wakeupTime, millis, nanos);
    1390             : 
    1391           1 :                 threads_wait_with_timeout(t, &wakeupTime, false);
    1392             : 
    1393           1 :                 interrupted = thread_is_interrupted(t);
    1394             : 
    1395           1 :                 if (interrupted) {
    1396           0 :                         thread_set_interrupted(t, false);
    1397             : 
    1398             :                         // An other exception could have been thrown
    1399             :                         // (e.g. ThreadDeathException).
    1400           0 :                         if (!exceptions_get_exception())
    1401           0 :                                 exceptions_throw_interruptedexception();
    1402             :                 }
    1403             :         }
    1404             : }
    1405             : 
    1406             : /**
    1407             :  * Park the current thread for the specified amount of time or until a
    1408             :  * specified deadline.
    1409             :  *
    1410             :  * @param absolute Is the time in nanos a deadline or a duration?
    1411             :  * @param nanos    Nanoseconds to park (absolute=false)
    1412             :  *                 or deadline in milliseconds (absolute=true)
    1413             :  */
    1414           0 : void threads_park(bool absolute, int64_t nanos)
    1415             : {
    1416             :         threadobject    *t;
    1417             :         struct timespec  wakeupTime;
    1418             : 
    1419           0 :         t = thread_get_current();
    1420             : 
    1421           0 :         if (absolute) {
    1422           0 :                 wakeupTime.tv_nsec = 0;
    1423           0 :                 wakeupTime.tv_sec = nanos / 1000; /* milliseconds */
    1424             :         }
    1425             :         else
    1426           0 :                 threads_calc_absolute_time(&wakeupTime, nanos / 1000000, nanos % 1000000);
    1427             : 
    1428           0 :         threads_wait_with_timeout(t, &wakeupTime, true);
    1429           0 : }
    1430             : 
    1431             : /**
    1432             :  * Unpark the specified thread.
    1433             :  *
    1434             :  * @param t The thread to unpark.
    1435             :  */
    1436           0 : void threads_unpark(threadobject *t)
    1437             : {
    1438           0 :         t->waitmutex->lock();
    1439             : 
    1440           0 :         t->waitcond->signal();
    1441             : 
    1442           0 :         t->park_permit = true;
    1443             : 
    1444           0 :         t->waitmutex->unlock();
    1445           0 : }
    1446             : 
    1447             : 
    1448             : /* threads_yield ***************************************************************
    1449             : 
    1450             :    Yield to the scheduler.
    1451             : 
    1452             : *******************************************************************************/
    1453             : 
    1454           0 : void threads_yield(void)
    1455             : {
    1456           0 :         sched_yield();
    1457           0 : }
    1458             : 
    1459             : 
    1460             : /***
    1461             :  * Return the tid of a thread.
    1462             :  */
    1463           0 : intptr_t threads_get_tid(threadobject *t) {
    1464             :         // pthread_t is a pointer type in OS X 
    1465             :         // and a unsigned integer on linux.
    1466             :         // Thus we need different casts
    1467             : #ifdef __DARWIN__
    1468             :         return reinterpret_cast<intptr_t>(t->impl.tid);
    1469             : #else
    1470           0 :         return static_cast<intptr_t>(t->impl.tid);
    1471             : #endif
    1472             : }
    1473             : 
    1474             : 
    1475             : /*
    1476             :  * These are local overrides for various environment variables in Emacs.
    1477             :  * Please do not remove this and leave it at the end of the file, where
    1478             :  * Emacs will automagically detect them.
    1479             :  * ---------------------------------------------------------------------
    1480             :  * Local variables:
    1481             :  * mode: c++
    1482             :  * indent-tabs-mode: t
    1483             :  * c-basic-offset: 4
    1484             :  * tab-width: 4
    1485             :  * End:
    1486             :  * vim:noexpandtab:sw=4:ts=4:
    1487             :  */

Generated by: LCOV version 1.11