Annotation of embedaddon/strongswan/src/libstrongswan/threading/windows/thread_value.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Martin Willi
                      3:  * Copyright (C) 2013 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "thread.h"
                     17: 
                     18: #include <threading/thread_value.h>
                     19: 
                     20: 
                     21: typedef struct private_thread_value_t private_thread_value_t;
                     22: 
                     23: /**
                     24:  * Unified thread_value_t implementation
                     25:  */
                     26: struct private_thread_value_t {
                     27: 
                     28:        /**
                     29:         * Public interface.
                     30:         */
                     31:        thread_value_t public;
                     32: 
                     33:        union {
                     34: 
                     35:                /**
                     36:                 * Cleanup function
                     37:                 */
                     38:                thread_cleanup_t cleanup;
                     39: 
                     40:                /**
                     41:                 * Windows TLS index, if used
                     42:                 */
                     43:                DWORD index;
                     44:        };
                     45: };
                     46: 
                     47: /**
                     48:  * TLS entry
                     49:  */
                     50: typedef struct {
                     51:        /** TLS value */
                     52:        void *value;
                     53:        /** cleanup handler function */
                     54:        thread_cleanup_t cleanup;
                     55: } entry_t;
                     56: 
                     57: /**
                     58:  * See windows/thread.h
                     59:  */
                     60: void thread_tls_cleanup(void *value)
                     61: {
                     62:        entry_t *entry = (entry_t*)value;
                     63: 
                     64:        if (entry->cleanup)
                     65:        {
                     66:                entry->cleanup(entry->value);
                     67:        }
                     68:        free(entry);
                     69: }
                     70: 
                     71: METHOD(thread_value_t, tls_set, void,
                     72:        private_thread_value_t *this, void *val)
                     73: {
                     74:        entry_t *entry;
                     75: 
                     76:        if (val)
                     77:        {
                     78:                INIT(entry,
                     79:                        .cleanup = this->cleanup,
                     80:                        .value = val,
                     81:                );
                     82: 
                     83:                free(thread_tls_put(this, entry));
                     84:        }
                     85:        else
                     86:        {
                     87:                free(thread_tls_remove(this));
                     88:        }
                     89: }
                     90: 
                     91: METHOD(thread_value_t, tls_get, void*,
                     92:        private_thread_value_t *this)
                     93: {
                     94:        entry_t *entry;
                     95: 
                     96:        entry = thread_tls_get(this);
                     97:        if (entry)
                     98:        {
                     99:                return entry->value;
                    100:        }
                    101:        return NULL;
                    102: }
                    103: 
                    104: METHOD(thread_value_t, tls_destroy, void,
                    105:        private_thread_value_t *this)
                    106: {
                    107:        entry_t *entry;
                    108: 
                    109:        entry = thread_tls_remove(this);
                    110:        if (entry)
                    111:        {
                    112:                thread_tls_cleanup(entry);
                    113:        }
                    114:        free(this);
                    115: }
                    116: 
                    117: METHOD(thread_value_t, tls_set_index, void,
                    118:        private_thread_value_t *this, void *val)
                    119: {
                    120:        TlsSetValue(this->index, val);
                    121: }
                    122: 
                    123: METHOD(thread_value_t, tls_get_index, void*,
                    124:        private_thread_value_t *this)
                    125: {
                    126:        return TlsGetValue(this->index);
                    127: }
                    128: 
                    129: METHOD(thread_value_t, tls_destroy_index, void,
                    130:        private_thread_value_t *this)
                    131: {
                    132:        TlsFree(this->index);
                    133:        free(this);
                    134: }
                    135: 
                    136: /**
                    137:  * Described in header.
                    138:  */
                    139: thread_value_t *thread_value_create(thread_cleanup_t cleanup)
                    140: {
                    141:        private_thread_value_t *this;
                    142:        DWORD index = TLS_OUT_OF_INDEXES;
                    143: 
                    144:        /* we have two implementations: Windows Tls* functions do not support
                    145:         * callbacks and has limited instances. We use it nonetheless if possible,
                    146:         * especially as leak detective relies on TLS, but we have to mangle
                    147:         * leak detective state for TLS storage. */
                    148: 
                    149:        if (!cleanup)
                    150:        {
                    151:                index = TlsAlloc();
                    152:        }
                    153: 
                    154:        if (index == TLS_OUT_OF_INDEXES)
                    155:        {
                    156:                INIT(this,
                    157:                        .public = {
                    158:                                .set = _tls_set,
                    159:                                .get = _tls_get,
                    160:                                .destroy = _tls_destroy,
                    161:                        },
                    162:                        .cleanup = cleanup,
                    163:                );
                    164:        }
                    165:        else
                    166:        {
                    167:                INIT(this,
                    168:                        .public = {
                    169:                                .set = _tls_set_index,
                    170:                                .get = _tls_get_index,
                    171:                                .destroy = _tls_destroy_index,
                    172:                        },
                    173:                        .index = index,
                    174:                );
                    175:        }
                    176: 
                    177:        return &this->public;
                    178: }

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