OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * Native Client threads library | 8 * Native Client threads library |
9 */ | 9 */ |
10 | 10 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 /* Number of threads currently running in this NaCl module. */ | 87 /* Number of threads currently running in this NaCl module. */ |
88 int __nc_running_threads_counter = 1; | 88 int __nc_running_threads_counter = 1; |
89 | 89 |
90 /* We have two queues of memory blocks - one for each type. */ | 90 /* We have two queues of memory blocks - one for each type. */ |
91 STAILQ_HEAD(tailhead, entry) __nc_thread_memory_blocks[2]; | 91 STAILQ_HEAD(tailhead, entry) __nc_thread_memory_blocks[2]; |
92 /* We need a counter for each queue to keep track of number of blocks. */ | 92 /* We need a counter for each queue to keep track of number of blocks. */ |
93 int __nc_memory_block_counter[2]; | 93 int __nc_memory_block_counter[2]; |
94 | 94 |
95 /* Internal functions */ | 95 /* Internal functions */ |
96 | 96 |
97 static inline nc_thread_descriptor_t *nc_get_tdb(void) { | 97 struct nc_thread_descriptor *__nc_get_tdb(void) { |
98 /* | 98 /* |
99 * Fetch the thread-specific data pointer. This is usually just | 99 * Fetch the thread-specific data pointer. This is usually just |
100 * a wrapper around __libnacl_irt_tls.tls_get() but we don't use | 100 * a wrapper around __libnacl_irt_tls.tls_get() but we don't use |
101 * that here so that the IRT build can override the definition. | 101 * that here so that the IRT build can override the definition. |
102 */ | 102 */ |
103 return (void *) ((char *) __nacl_read_tp_inline() | 103 return (void *) ((char *) __nacl_read_tp_inline() |
104 + __nacl_tp_tdb_offset(TDB_SIZE)); | 104 + __nacl_tp_tdb_offset(TDB_SIZE)); |
105 } | 105 } |
106 | 106 |
107 static void nc_thread_starter(void) { | 107 static void nc_thread_starter(void) { |
108 nc_thread_descriptor_t *tdb = nc_get_tdb(); | 108 nc_thread_descriptor_t *tdb = __nc_get_tdb(); |
109 __newlib_thread_init(); | 109 __newlib_thread_init(); |
110 #if defined(NACL_IN_IRT) | 110 #if defined(NACL_IN_IRT) |
111 g_is_irt_internal_thread = 1; | 111 g_is_irt_internal_thread = 1; |
112 #endif | 112 #endif |
113 void *retval = tdb->start_func(tdb->state); | 113 void *retval = tdb->start_func(tdb->state); |
114 | 114 |
115 /* | 115 /* |
116 * Free handler list to prevent memory leak in case function returns | 116 * Free handler list to prevent memory leak in case function returns |
117 * without calling pthread_cleanup_pop(), although doing that is unspecified | 117 * without calling pthread_cleanup_pop(), although doing that is unspecified |
118 * behaviour. | 118 * behaviour. |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 nc_free_memory_block_mu(TLS_AND_TDB_MEMORY, block); | 236 nc_free_memory_block_mu(TLS_AND_TDB_MEMORY, block); |
237 } | 237 } |
238 } | 238 } |
239 | 239 |
240 /* Initialize a newly allocated TDB to some default values. */ | 240 /* Initialize a newly allocated TDB to some default values. */ |
241 static void nc_tdb_init(nc_thread_descriptor_t *tdb, | 241 static void nc_tdb_init(nc_thread_descriptor_t *tdb, |
242 nc_basic_thread_data_t *basic_data) { | 242 nc_basic_thread_data_t *basic_data) { |
243 tdb->tls_base = tdb; | 243 tdb->tls_base = tdb; |
244 tdb->joinable = PTHREAD_CREATE_JOINABLE; | 244 tdb->joinable = PTHREAD_CREATE_JOINABLE; |
245 tdb->join_waiting = 0; | 245 tdb->join_waiting = 0; |
| 246 tdb->rdlock_count = 0; |
246 tdb->stack_node = NULL; | 247 tdb->stack_node = NULL; |
247 tdb->tls_node = NULL; | 248 tdb->tls_node = NULL; |
248 tdb->start_func = NULL; | 249 tdb->start_func = NULL; |
249 tdb->state = NULL; | 250 tdb->state = NULL; |
250 tdb->irt_thread_data = NULL; | 251 tdb->irt_thread_data = NULL; |
251 tdb->basic_data = basic_data; | 252 tdb->basic_data = basic_data; |
252 | 253 |
253 basic_data->retval = NULL; | 254 basic_data->retval = NULL; |
254 basic_data->status = THREAD_RUNNING; | 255 basic_data->status = THREAD_RUNNING; |
255 if (pthread_cond_init(&basic_data->join_condvar, NULL) != 0) | 256 if (pthread_cond_init(&basic_data->join_condvar, NULL) != 0) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 | 298 |
298 #else | 299 #else |
299 | 300 |
300 /* | 301 /* |
301 * Will be called from the library startup code, | 302 * Will be called from the library startup code, |
302 * which always happens on the application's main thread. | 303 * which always happens on the application's main thread. |
303 */ | 304 */ |
304 void __pthread_initialize(void) { | 305 void __pthread_initialize(void) { |
305 __pthread_initialize_minimal(TDB_SIZE); | 306 __pthread_initialize_minimal(TDB_SIZE); |
306 | 307 |
307 struct nc_combined_tdb *tdb = (struct nc_combined_tdb *) nc_get_tdb(); | 308 struct nc_combined_tdb *tdb = (struct nc_combined_tdb *) __nc_get_tdb(); |
308 nc_tdb_init(&tdb->tdb, &tdb->basic_data); | 309 nc_tdb_init(&tdb->tdb, &tdb->basic_data); |
309 __nc_initial_thread_id = &tdb->basic_data; | 310 __nc_initial_thread_id = &tdb->basic_data; |
310 | 311 |
311 __nc_initialize_globals(); | 312 __nc_initialize_globals(); |
312 } | 313 } |
313 | 314 |
314 #endif | 315 #endif |
315 | 316 |
316 | 317 |
317 /* pthread functions */ | 318 /* pthread functions */ |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 nc_thread_cleanup_handler *handler = __nc_cleanup_handlers; | 486 nc_thread_cleanup_handler *handler = __nc_cleanup_handlers; |
486 __nc_cleanup_handlers = handler->previous; | 487 __nc_cleanup_handlers = handler->previous; |
487 if (execute) | 488 if (execute) |
488 handler->handler_function(handler->handler_arg); | 489 handler->handler_function(handler->handler_arg); |
489 free(handler); | 490 free(handler); |
490 } | 491 } |
491 } | 492 } |
492 | 493 |
493 void pthread_exit(void *retval) { | 494 void pthread_exit(void *retval) { |
494 /* Get all we need from the tdb before releasing it. */ | 495 /* Get all we need from the tdb before releasing it. */ |
495 nc_thread_descriptor_t *tdb = nc_get_tdb(); | 496 nc_thread_descriptor_t *tdb = __nc_get_tdb(); |
496 nc_thread_memory_block_t *stack_node = tdb->stack_node; | 497 nc_thread_memory_block_t *stack_node = tdb->stack_node; |
497 int32_t *is_used = &stack_node->is_used; | 498 int32_t *is_used = &stack_node->is_used; |
498 nc_basic_thread_data_t *basic_data = tdb->basic_data; | 499 nc_basic_thread_data_t *basic_data = tdb->basic_data; |
499 int joinable = tdb->joinable; | 500 int joinable = tdb->joinable; |
500 | 501 |
501 /* Call cleanup handlers. */ | 502 /* Call cleanup handlers. */ |
502 while (NULL != __nc_cleanup_handlers) { | 503 while (NULL != __nc_cleanup_handlers) { |
503 pthread_cleanup_pop(1); | 504 pthread_cleanup_pop(1); |
504 } | 505 } |
505 | 506 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 } | 624 } |
624 | 625 |
625 int pthread_kill(pthread_t thread_id, | 626 int pthread_kill(pthread_t thread_id, |
626 int sig) { | 627 int sig) { |
627 /* This function is currently unimplemented. */ | 628 /* This function is currently unimplemented. */ |
628 return ENOSYS; | 629 return ENOSYS; |
629 } | 630 } |
630 | 631 |
631 pthread_t pthread_self(void) { | 632 pthread_t pthread_self(void) { |
632 /* Get the tdb pointer from gs and use it to return the thread handle. */ | 633 /* Get the tdb pointer from gs and use it to return the thread handle. */ |
633 nc_thread_descriptor_t *tdb = nc_get_tdb(); | 634 nc_thread_descriptor_t *tdb = __nc_get_tdb(); |
634 return tdb->basic_data; | 635 return tdb->basic_data; |
635 } | 636 } |
636 | 637 |
637 int pthread_equal(pthread_t thread1, pthread_t thread2) { | 638 int pthread_equal(pthread_t thread1, pthread_t thread2) { |
638 return (thread1 == thread2); | 639 return (thread1 == thread2); |
639 } | 640 } |
640 | 641 |
641 int pthread_setschedprio(pthread_t thread_id, int prio) { | 642 int pthread_setschedprio(pthread_t thread_id, int prio) { |
642 if (thread_id != pthread_self()) { | 643 if (thread_id != pthread_self()) { |
643 /* | 644 /* |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 | 822 |
822 /* | 823 /* |
823 * We include this directly in this file rather than compiling it | 824 * We include this directly in this file rather than compiling it |
824 * separately because there is some code (e.g. libstdc++) that uses weak | 825 * separately because there is some code (e.g. libstdc++) that uses weak |
825 * references to all pthread functions, but conditionalizes its calls only | 826 * references to all pthread functions, but conditionalizes its calls only |
826 * on one symbol. So if these functions are in another file in a library | 827 * on one symbol. So if these functions are in another file in a library |
827 * archive, they might not be linked in by static linking. | 828 * archive, they might not be linked in by static linking. |
828 */ | 829 */ |
829 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ | 830 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ |
830 #include "native_client/src/untrusted/pthread/nc_tsd.c" | 831 #include "native_client/src/untrusted/pthread/nc_tsd.c" |
OLD | NEW |