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>