Annotation of embedaddon/strongswan/src/libstrongswan/threading/windows/thread_value.c, revision 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>