[BACK]Return to specific.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc / include / private

Annotation of OpenXM_contrib2/asir2000/gc/include/private/specific.h, Revision 1.1

1.1     ! noro        1: /*
        !             2:  * This is a reimplementation of a subset of the pthread_getspecific/setspecific
        !             3:  * interface. This appears to outperform the standard linuxthreads one
        !             4:  * by a significant margin.
        !             5:  * The major restriction is that each thread may only make a single
        !             6:  * pthread_setspecific call on a single key.  (The current data structure
        !             7:  * doesn't really require that.  The restriction should be easily removable.)
        !             8:  * We don't currently support the destruction functions, though that
        !             9:  * could be done.
        !            10:  * We also currently assume that only one pthread_setspecific call
        !            11:  * can be executed at a time, though that assumption would be easy to remove
        !            12:  * by adding a lock.
        !            13:  */
        !            14:
        !            15: #include <errno.h>
        !            16:
        !            17: /* Called during key creation or setspecific.          */
        !            18: /* For the GC we already hold lock.                    */
        !            19: /* Currently allocated objects leak on thread exit.    */
        !            20: /* That's hard to fix, but OK if we allocate garbage   */
        !            21: /* collected memory.                                   */
        !            22: #define MALLOC_CLEAR(n) GC_INTERNAL_MALLOC(n, NORMAL)
        !            23: #define PREFIXED(name) GC_##name
        !            24:
        !            25: #define TS_CACHE_SIZE 1024
        !            26: #define CACHE_HASH(n) (((((long)n) >> 8) ^ (long)n) & (TS_CACHE_SIZE - 1))
        !            27: #define TS_HASH_SIZE 1024
        !            28: #define HASH(n) (((((long)n) >> 8) ^ (long)n) & (TS_HASH_SIZE - 1))
        !            29:
        !            30: typedef struct thread_specific_entry {
        !            31:        unsigned long qtid;     /* quick thread id, only for cache */
        !            32:        void * value;
        !            33:        pthread_t thread;
        !            34:        struct thread_specific_entry *next;
        !            35: } tse;
        !            36:
        !            37:
        !            38: /* We represent each thread-specific datum as two tables.  The first is        */
        !            39: /* a cache, index by a "quick thread identifier".  The "quick" thread  */
        !            40: /* identifier is an easy to compute value, which is guaranteed to      */
        !            41: /* determine the thread, though a thread may correspond to more than   */
        !            42: /* one value.  We typically use the address of a page in the stack.    */
        !            43: /* The second is a hash table, indexed by pthread_self().  It is used  */
        !            44: /* only as a backup.                                                   */
        !            45:
        !            46: /* Return the "quick thread id".  Default version.  Assumes page size, */
        !            47: /* or at least thread stack separation, is at least 4K.                        */
        !            48: static __inline__ long quick_thread_id() {
        !            49:     int dummy;
        !            50:     return (long)(&dummy) >> 12;
        !            51: }
        !            52:
        !            53: #define INVALID_QTID ((unsigned long)(-1))
        !            54:
        !            55: typedef struct thread_specific_data {
        !            56:     tse * volatile cache[TS_CACHE_SIZE];
        !            57:                        /* A faster index to the hash table */
        !            58:     tse * hash[TS_HASH_SIZE];
        !            59:     pthread_mutex_t lock;
        !            60: } tsd;
        !            61:
        !            62: typedef tsd * PREFIXED(key_t);
        !            63:
        !            64: extern int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *));
        !            65:
        !            66: extern int PREFIXED(setspecific) (tsd * key, void * value);
        !            67:
        !            68: extern void PREFIXED(remove_specific) (tsd * key);
        !            69:
        !            70: /* An internal version of getspecific that assumes a cache miss.       */
        !            71: void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid,
        !            72:                                   tse * volatile * cache_entry);
        !            73:
        !            74: static __inline__ void * PREFIXED(getspecific) (tsd * key) {
        !            75:     long qtid = quick_thread_id();
        !            76:     unsigned hash_val = CACHE_HASH(qtid);
        !            77:     tse * volatile * entry_ptr = key -> cache + hash_val;
        !            78:     tse * entry = *entry_ptr;   /* Must be loaded only once.   */
        !            79:     if (entry -> qtid == qtid) return entry -> value;
        !            80:     return PREFIXED(slow_getspecific) (key, qtid, entry_ptr);
        !            81: }
        !            82:
        !            83:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>