@@ -47,7 +47,7 @@ int pthread_key_create(pthread_key_t* key, void (*destructor)(void*))
4747 if (!key )
4848 return -1 ;
4949
50- DWORD k = FlsAlloc ((PFLS_CALLBACK_FUNCTION )destructor );
50+ DWORD k = FlsAlloc ((PFLS_KEY_FUNCTION )destructor );
5151
5252 if (k == FLS_OUT_OF_INDEXES )
5353 return -1 ;
@@ -122,69 +122,108 @@ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
122122
123123#include "common/htable.h"
124124
125- typedef struct FLS_KEY FLS_KEY ;
126- typedef struct TLS_KEY TLS_KEY ;
127-
128- struct FLS_KEY {
129- HTABLE * keys ;
130- };
131-
132- struct TLS_KEY {
125+ typedef struct TLS_KEY {
133126 pthread_key_t key ;
134127 void (* destructor )(void * );
135- FIFO * objs ;
136- };
128+ } TLS_KEY ;
129+
130+ typedef struct TLS_OBJ {
131+ pthread_key_t key ;
132+ void * value ;
133+ } TLS_OBJ ;
137134
138- static pthread_key_t __tls_key = TLS_OUT_OF_INDEXES ;
139- static pthread_key_t __fls_key = FLS_OUT_OF_INDEXES ;
135+ typedef struct FLS_KEY {
136+ FIFO * locals ; // Hold TLS_OBJ
137+ } FLS_KEY ;
138+
139+ typedef struct PROC_KEYS {
140+ HTABLE * keys ; // tkey => TLS_KEY
141+ } PROC_KEYS ;
142+
143+ static pthread_key_t __tls_key = TLS_OUT_OF_INDEXES ;
144+ static pthread_key_t __fls_key = FLS_OUT_OF_INDEXES ;
145+ static PROC_KEYS * __pkeys = NULL ;
146+ static pthread_mutex_t __lock ;
140147
141148extern int acl_fiber_scheduled (void );
142149
150+ static void hash_key (pthread_key_t key , char * buf , size_t n )
151+ {
152+ assert (n > 10 );
153+ _snprintf (buf , n , "%d" , key );
154+ buf [n - 1 ] = '\0' ;
155+ }
156+
143157static void thread_exit (void * ctx )
144158{
145159 FLS_KEY * fkey = (FLS_KEY * ) ctx ;
146- void * ctx ;
160+ assert (fkey && fkey -> locals );
161+
162+ // The first one is set in thread_init() in fiber.c, it should be called
163+ // in the end, because the original fiber will be freed that it means
164+ // the current thread will be end and the thread context will freed.
165+ TLS_OBJ * first = fifo_pop_front (fkey -> locals ), * obj ;
166+ assert (first );
147167
148- assert (fkey );
149- assert (fkey -> keys );
168+ char key [32 ];
150169
151- ITER iter ;
152- foreach (iter , fkey -> keys ) {
153- TLS_KEY * tkey = (TLS_KEY * ) iter .data ;
154- assert (tkey );
170+ pthread_mutex_lock (& __lock );
155171
156- if (tkey -> destructor == NULL ) {
172+ while ((obj = fifo_pop_front (fkey -> locals ))) {
173+ hash_key (obj -> key , key , sizeof (key ));
174+ TLS_KEY * tkey = (TLS_KEY * ) htable_find (__pkeys -> keys , key );
175+ if (tkey == NULL || tkey -> destructor == NULL ) {
157176 continue ;
158177 }
178+ tkey -> destructor (obj -> value );
179+ mem_free (obj );
180+ }
159181
160- while ((ctx = tkey -> objs -> pop_front (tkey -> objs ))) {
161- tkey -> destructor (ctx );
162- }
182+ fifo_free (fkey -> locals , NULL );
183+ mem_free (fkey );
163184
164- fifo_free (tkey -> objs , NULL );
165- }
185+ hash_key (first -> key , key , sizeof (key ));
186+ TLS_KEY * tkey = (TLS_KEY * ) htable_find (__pkeys -> keys , key );
187+ assert (tkey );
166188
167- htable_free (tkey -> keys , mem_free );
168- mem_free (tkey );
169- }
189+ pthread_mutex_unlock (& __lock );
190+
191+ void * value = first -> value ;
192+ mem_free (first );
170193
171- /* 每个进程的唯一初始化函数 */
194+ // Must the __fls_key's value to NULL to avoid the thread_exit
195+ // to be triggered again for the current thread when the original
196+ // fiber is deleted.
197+ FlsSetValue (__fls_key , NULL );
198+ tkey -> destructor (value );
199+ }
172200
173201static void thread_once (void )
174202{
175203 __tls_key = TlsAlloc ();
176204 __fls_key = FlsAlloc (thread_exit );
205+ __pkeys = (PROC_KEYS * ) mem_calloc (1 , sizeof (PROC_KEYS ));
206+ __pkeys -> keys = htable_create (10 );
207+ pthread_mutex_init (& __lock , NULL );
177208}
178209
179- static void hash_key ( pthread_key_t key , char * buf , size_t n )
210+ void pthread_fkey_create ( void )
180211{
181- assert (n > 10 );
182- _snprintf (buf , n , "%d" , key );
183- buf [n - 1 ] = '\0' ;
212+ pthread_once (& __control_once , thread_once );
213+
214+ FLS_KEY * fkey = (FLS_KEY * ) TlsGetValue (__tls_key );
215+ if (fkey == NULL ) {
216+ assert (!acl_fiber_scheduled ());
217+ fkey = (FLS_KEY * ) mem_calloc (sizeof (FLS_KEY ), 1 );
218+ fkey -> locals = fifo_new ();
219+ FlsSetValue (__fls_key , fkey );
220+ TlsSetValue (__tls_key , fkey );
221+ }
184222}
185223
186224int pthread_key_create (pthread_key_t * key_ptr , void (* destructor )(void * ))
187225{
226+ char kbuf [32 ];
188227 pthread_once (& __control_once , thread_once );
189228
190229 assert (__tls_key != TLS_OUT_OF_INDEXES );
@@ -193,73 +232,72 @@ int pthread_key_create(pthread_key_t *key_ptr, void (*destructor)(void*))
193232 if (* key_ptr <= 0 && * key_ptr != TLS_OUT_OF_INDEXES ) {
194233 * key_ptr = TlsAlloc ();
195234 assert (* key_ptr != TLS_OUT_OF_INDEXES );
235+ } else {
236+ hash_key (* key_ptr , kbuf , sizeof (kbuf ));
237+ pthread_mutex_lock (& __lock );
238+ if (htable_find (__pkeys -> keys , kbuf )) {
239+ pthread_mutex_unlock (& __lock );
240+ return 0 ;
241+ }
242+ * key_ptr = TlsAlloc ();
243+ assert (* key_ptr != TLS_OUT_OF_INDEXES );
196244 }
197245
198- TLS_KEY * tkey = (TLS_KEY * ) mem_calloc (sizeof (TLS_KEY ), 1 );
246+ TLS_KEY * tkey = (TLS_KEY * ) mem_calloc (sizeof (TLS_KEY ), 1 );
199247 tkey -> key = * key_ptr ;
200248 tkey -> destructor = destructor ;
201- tkey -> objs = fifo_new ();
202249
203- char kbuf [32 ];
204250 hash_key (* key_ptr , kbuf , sizeof (kbuf ));
205- FLS_KEY * fkey ;
206-
207- if ((fkey = (FLS_KEY * ) TlsGetValue (__tls_key )) == NULL ) {
208- if (acl_fiber_scheduled ()) {
209- msg_fatal ("%s(%d): should be in thread mode" ,
210- __FUNCTION__ , __LINE__ );
211- }
212251
213- fkey = (FLS_KEY * ) mem_calloc (sizeof (FLS_KEY ), 1 );
214- fkey -> keys = htable_create (10 );
215-
216- TlsSetValue (__tls_key , fkey );
217- FlsSetValue (__fls_key , fkey );
218- }
219-
220- htable_enter (fkey -> keys , kbuf , tkey );
252+ pthread_mutex_lock (& __lock );
253+ htable_enter (__pkeys -> keys , kbuf , tkey );
254+ pthread_mutex_unlock (& __lock );
221255 return 0 ;
222256}
223257
224- void * pthread_getspecific (pthread_key_t key )
225- {
226- return TlsGetValue (key );
227- }
228-
229258int pthread_setspecific (pthread_key_t key , void * value )
230259{
231260 if (key < 0 || key == TLS_OUT_OF_INDEXES ) {
232261 msg_error ("%s(%d): key(%d) invalid" , __FUNCTION__ , __LINE__ , key );
233262 return EINVAL ;
234263 }
235264
236- FLS_KEY * fkey = (FLS_KEY * ) TlsGetValue (__tls_key );
237- if (fkey == NULL ) {
238- msg_error ("%s(%d): no FLS_KEY for __tls_key=%d" ,
239- __FUNCTION__ , __LINE__ , __fls_key );
240- return EINVAL ;
241- }
265+ assert (__tls_key != TLS_OUT_OF_INDEXES );
266+ assert (__pkeys );
242267
243268 char kbuf [32 ];
244269 hash_key (key , kbuf , sizeof (kbuf ));
245270
246- TLS_KEY * tkey = (TLS_KEY * ) htable_find (fkey -> keys , kbuf );
271+ pthread_mutex_lock (& __lock );
272+ TLS_KEY * tkey = (TLS_KEY * ) htable_find (__pkeys -> keys , kbuf );
273+ pthread_mutex_unlock (& __lock );
274+
247275 if (tkey == NULL ) {
248- msg_error ("%s(%d): no TLS_KEY for key=%d, __tls_key=%d" ,
249- __FUNCTION__ , __LINE__ , key , __tls_key );
276+ msg_error ("%s(%d): no TLS_KEY for key=%d" , __FUNCTION__ , __LINE__ , key );
250277 return EINVAL ;
251278 }
252279
280+ FLS_KEY * fkey = (FLS_KEY * ) TlsGetValue (__tls_key );
281+ assert (fkey && fkey -> locals );
282+ TLS_OBJ * obj = (TLS_OBJ * ) mem_calloc (1 , sizeof (TLS_OBJ ));
283+ obj -> key = key ;
284+ obj -> value = value ;
285+ fkey -> locals -> push_back (fkey -> locals , obj );
286+
253287 if (!TlsSetValue (key , value )) {
254288 msg_error ("%s(%d): TlsSetValue(key=%d) error(%s)" ,
255289 __FUNCTION__ , __LINE__ , key , last_serror ());
256290 return -1 ;
257291 }
258292
259- tkey -> objs -> push_back (tkey -> objs , value );
260293 return 0 ;
261294}
262295
296+ void * pthread_getspecific (pthread_key_t key )
297+ {
298+ return TlsGetValue (key );
299+ }
300+
263301#endif /* USE_FLS */
264302
265303/* Free the mutex */
0 commit comments