123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- // -*- c++ -*-
- // posix-threads.h - Defines for using POSIX threads.
- /* Copyright (C) 1998, 1999, 2001, 2003, 2006 Free Software Foundation
- This file is part of libgcj.
- This software is copyrighted work licensed under the terms of the
- Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
- details. */
- #ifndef __JV_POSIX_THREADS__
- #define __JV_POSIX_THREADS__
- // NOTE: This file may only reference those pthread functions which
- // are known not to be overridden by the Boehm GC. If in doubt, scan
- // boehm-gc/gc.h. This is yucky but lets us avoid including gc.h
- // everywhere (which would be truly yucky).
- #include <pthread.h>
- #include <sched.h>
- #include <sysdep/locks.h>
- //
- // Typedefs.
- //
- typedef struct _Jv_Thread_t
- {
- // Flag values are defined in implementation.
- int flags;
- // Actual thread id.
- pthread_t thread;
-
- // Java Thread object.
- java::lang::Thread *thread_obj;
-
- // Condition variable and corresponding mutex, used to implement the
- // interruptable wait/notify mechanism.
- pthread_cond_t wait_cond;
- pthread_mutex_t wait_mutex;
- // Next thread for Condition Variable wait-list chain.
- _Jv_Thread_t *next;
-
- } _Jv_Thread_t;
- typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
- // Condition Variables used to implement wait/notify/sleep/interrupt.
- typedef struct
- {
- // Linked list of Threads that are waiting to be notified.
- _Jv_Thread_t *first;
- } _Jv_ConditionVariable_t;
- typedef struct
- {
- // For compatibility, simplicity, and correctness, we do not use the native
- // pthreads recursive mutex implementation, but simulate them instead.
- // Mutex the thread holds the entire time this mutex is held.
- pthread_mutex_t mutex;
- // Thread holding this mutex.
- pthread_t owner;
- // Number of times mutex is held (lock depth). If 0, the lock is not held.
- int count;
- } _Jv_Mutex_t;
- // This is a convenience function used only by the pthreads thread
- // implementation. This is slow, but that's too bad -- we need to do
- // the checks for correctness. It might be nice to be able to compile
- // this out. Returns 0 if the lock is held by the current thread, and
- // 1 otherwise.
- inline int
- _Jv_MutexCheckMonitor (_Jv_Mutex_t *mu)
- {
- return (pthread_equal(mu->owner, pthread_self()) == 0);
- }
- // Type identifying a POSIX thread.
- typedef pthread_t _Jv_ThreadDesc_t;
- inline _Jv_ThreadDesc_t
- _Jv_GetPlatformThreadID(_Jv_Thread_t *t)
- {
- return t->thread;
- }
- //
- // Signal helpers.
- //
- void _Jv_BlockSigchld();
- void _Jv_UnBlockSigchld();
- //
- // Condition variables.
- //
- int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
- jlong millis, jint nanos);
-
- int _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
- int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
- inline void
- _Jv_CondInit (_Jv_ConditionVariable_t *cv)
- {
- cv->first = 0;
- }
- //
- // Mutexes.
- //
- #ifdef LOCK_DEBUG
- # include <stdio.h>
- #endif
- inline void
- _Jv_MutexInit (_Jv_Mutex_t *mu)
- {
- # ifdef LOCK_DEBUG /* Assumes Linuxthreads */
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
- pthread_mutex_init (&mu->mutex, &attr);
- # else
- pthread_mutex_init (&mu->mutex, 0);
- # endif
- mu->count = 0;
- mu->owner = 0;
- }
- extern int _Jv_MutexLock (_Jv_Mutex_t *);
- inline int
- _Jv_MutexUnlock (_Jv_Mutex_t *mu)
- {
- if (_Jv_MutexCheckMonitor (mu))
- {
- # ifdef LOCK_DEBUG
- fprintf(stderr, "_Jv_MutexUnlock: Not owner\n");
- for (;;) {}
- # endif
- return 1;
- }
-
- mu->count--;
- if (mu->count == 0)
- {
- mu->owner = 0;
- # ifdef LOCK_DEBUG
- int result = pthread_mutex_unlock (&mu->mutex);
- if (0 != result)
- {
- fprintf(stderr, "Pthread_mutex_unlock returned %d\n", result);
- for (;;) {}
- }
- # else
- pthread_mutex_unlock (&mu->mutex);
- # endif
- }
- return 0;
- }
- #ifndef LINUX_THREADS
- // pthread_mutex_destroy does nothing on Linux and it is a win to avoid
- // defining this macro.
- #define _Jv_HaveMutexDestroy
- inline void
- _Jv_MutexDestroy (_Jv_Mutex_t *mu)
- {
- pthread_mutex_destroy (&mu->mutex);
- }
- #endif /* LINUX_THREADS */
- //
- // Thread creation and manipulation.
- //
- void _Jv_InitThreads (void);
- _Jv_Thread_t *_Jv_ThreadInitData (java::lang::Thread *thread);
- void _Jv_ThreadDestroyData (_Jv_Thread_t *data);
- inline java::lang::Thread *
- _Jv_ThreadCurrent (void)
- {
- extern pthread_key_t _Jv_ThreadKey;
- return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
- }
- #ifdef JV_HASH_SYNCHRONIZATION
- // Should be specialized to just load the "current thread" register
- // on platforms that support it. Speed is of the essence. The value
- // of the descriptor is not, so long as there is a one-to-one correspondence
- // to threads.
- #ifdef __ia64__
- typedef size_t _Jv_ThreadId_t;
- register size_t _Jv_self __asm__("r13");
- // For linux_threads this is really a pointer to its thread data
- // structure. We treat it as opaque. That should also work
- // on other operating systems that follow the ABI standard.
- // This should become the prototype for machines that maintain a thread
- // pointer in a register.
- inline _Jv_ThreadId_t
- _Jv_ThreadSelf (void)
- {
- return _Jv_self;
- }
- #define JV_SELF_DEFINED
- #endif /* __ia64__ */
- #ifdef __alpha__
- typedef void *_Jv_ThreadId_t;
- inline _Jv_ThreadId_t
- _Jv_ThreadSelf (void)
- {
- return __builtin_thread_pointer ();
- }
- #define JV_SELF_DEFINED
- #endif /* __alpha__ */
- #if defined(SLOW_PTHREAD_SELF)
- #include "sysdep/locks.h"
- typedef pthread_t _Jv_ThreadId_t;
- // E.g. on X86 Linux, pthread_self() is too slow for our purpose.
- // Instead we maintain a cache based on the current sp value.
- // This is similar to what's done for thread local allocation in the
- // GC, only far simpler.
- // This code should probably go away when Linux/X86 starts using a
- // segment register to hold the thread id.
- # define LOG_THREAD_SPACING 12
- // If two thread pointer values are closer than
- // 1 << LOG_THREAD_SPACING, we assume they belong
- // to the same thread.
- # define SELF_CACHE_SIZE 1024
- # define SC_INDEX(sp) (((unsigned long)(sp) >> 19) & (SELF_CACHE_SIZE-1))
- // Mapping from sp value to cache index.
- // Note that this is not in any real sense a hash
- // function, since we need to be able to clear
- // all possibly matching slots on thread startup.
- // Thus all entries that might correspond to
- // a given thread are intentionally contiguous.
- // Works well with anything that allocates at least
- // 512KB stacks.
- # define SC_CLEAR_MIN (-16) // When starting a new thread, we clear
- # define SC_CLEAR_MAX 0 // all self cache entries between
- // SC_INDEX(sp)+SC_CLEAR_MIN and
- // SC_INDEX(sp)+SC_CLEAR_MAX to ensure
- // we never see stale values. The
- // current values assume a downward
- // growing stack of size <= 7.5 MB.
- # define BAD_HIGH_SP_VALUE ((size_t)(-1))
- extern volatile
- struct self_cache_entry {
- size_t high_sp_bits; // sp value >> LOG_THREAD_SPACING
- pthread_t self; // Corresponding thread
- } _Jv_self_cache[];
- void _Jv_Self_Cache_Init();
- _Jv_ThreadId_t
- _Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce,
- size_t high_sp_bits);
-
- inline _Jv_ThreadId_t
- _Jv_ThreadSelf (void)
- {
- int dummy;
- size_t sp = (size_t)(&dummy);
- unsigned h = SC_INDEX(sp);
- volatile self_cache_entry *sce = _Jv_self_cache + h;
- pthread_t candidate_self = sce -> self; // Read must precede following one.
- read_barrier();
- if (sce -> high_sp_bits == sp >> LOG_THREAD_SPACING)
- {
- // The sce -> self value we read must be valid. An intervening
- // cache replacement by another thread would have first replaced
- // high_sp_bits by something else, and it can't possibly change
- // back without our intervention.
- return candidate_self;
- }
- else
- return _Jv_ThreadSelf_out_of_line(sce, sp >> LOG_THREAD_SPACING);
- }
- #define JV_SELF_DEFINED
- #endif /* SLOW_PTHREAD_SELF */
- #ifndef JV_SELF_DEFINED /* If all else fails, call pthread_self directly */
- typedef pthread_t _Jv_ThreadId_t;
- inline _Jv_ThreadId_t
- _Jv_ThreadSelf (void)
- {
- return pthread_self();
- }
- #endif /* !JV_SELF_DEFINED */
- #endif /* JV_HASH_SYNCHRONIZATION */
- inline _Jv_Thread_t *
- _Jv_ThreadCurrentData (void)
- {
- extern pthread_key_t _Jv_ThreadDataKey;
- return (_Jv_Thread_t *) pthread_getspecific (_Jv_ThreadDataKey);
- }
- inline void
- _Jv_ThreadYield (void)
- {
- #ifdef HAVE_SCHED_YIELD
- sched_yield ();
- #endif /* HAVE_SCHED_YIELD */
- }
- void _Jv_ThreadRegister (_Jv_Thread_t *data);
- void _Jv_ThreadUnRegister ();
- void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
- void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
- _Jv_ThreadStartFunc *meth);
- void _Jv_ThreadWait (void);
- void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
- // park() / unpark() support
- struct ParkHelper
- {
- volatile obj_addr_t permit;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-
- void init ();
- void deactivate ();
- void destroy ();
- void park (jboolean isAbsolute, jlong time);
- void unpark ();
- };
- inline void
- ParkHelper::destroy ()
- {
- pthread_mutex_destroy (&mutex);
- pthread_cond_destroy (&cond);
- }
- #endif /* __JV_POSIX_THREADS__ */
|