Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: src/untrusted/pthread/nc_thread.c

Issue 951583004: Implement pthread_rwlock functions for NaCl newlib (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/untrusted/pthread/nc_rwlock.c ('k') | src/untrusted/pthread/pthread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 #endif 56 #endif
57 57
58 typedef struct nc_thread_cleanup_handler { 58 typedef struct nc_thread_cleanup_handler {
59 struct nc_thread_cleanup_handler *previous; 59 struct nc_thread_cleanup_handler *previous;
60 void (*handler_function)(void *arg); 60 void (*handler_function)(void *arg);
61 void *handler_arg; 61 void *handler_arg;
62 } nc_thread_cleanup_handler; 62 } nc_thread_cleanup_handler;
63 63
64 static __thread nc_thread_cleanup_handler *__nc_cleanup_handlers = NULL; 64 static __thread nc_thread_cleanup_handler *__nc_cleanup_handlers = NULL;
65 65
66 #define TDB_SIZE (sizeof(struct nc_combined_tdb))
67
68 static inline char *align(uint32_t offset, uint32_t alignment) { 66 static inline char *align(uint32_t offset, uint32_t alignment) {
69 return (char *) ((offset + alignment - 1) & ~(alignment - 1)); 67 return (char *) ((offset + alignment - 1) & ~(alignment - 1));
70 } 68 }
71 69
72 /* Thread management global variables. */ 70 /* Thread management global variables. */
73 const int __nc_kMaxCachedMemoryBlocks = 50; 71 const int __nc_kMaxCachedMemoryBlocks = 50;
74 72
75 int __nc_thread_initialized; 73 int __nc_thread_initialized;
76 74
77 /* Mutex used to synchronize thread management code. */ 75 /* Mutex used to synchronize thread management code. */
78 pthread_mutex_t __nc_thread_management_lock; 76 pthread_mutex_t __nc_thread_management_lock;
79 77
80 /* 78 /*
81 * Condition variable that gets signaled when all the threads 79 * Condition variable that gets signaled when all the threads
82 * except the main thread have terminated. 80 * except the main thread have terminated.
83 */ 81 */
84 static pthread_cond_t __nc_last_thread_cond; 82 static pthread_cond_t __nc_last_thread_cond;
85 pthread_t __nc_initial_thread_id; 83 pthread_t __nc_initial_thread_id;
86 84
87 /* Number of threads currently running in this NaCl module. */ 85 /* Number of threads currently running in this NaCl module. */
88 int __nc_running_threads_counter = 1; 86 int __nc_running_threads_counter = 1;
89 87
90 /* We have two queues of memory blocks - one for each type. */ 88 /* We have two queues of memory blocks - one for each type. */
91 STAILQ_HEAD(tailhead, entry) __nc_thread_memory_blocks[2]; 89 STAILQ_HEAD(tailhead, entry) __nc_thread_memory_blocks[2];
92 /* We need a counter for each queue to keep track of number of blocks. */ 90 /* We need a counter for each queue to keep track of number of blocks. */
93 int __nc_memory_block_counter[2]; 91 int __nc_memory_block_counter[2];
94 92
95 /* Internal functions */ 93 /* Internal functions */
96 94
97 static inline nc_thread_descriptor_t *nc_get_tdb(void) {
98 /*
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
101 * that here so that the IRT build can override the definition.
102 */
103 return (void *) ((char *) __nacl_read_tp_inline()
104 + __nacl_tp_tdb_offset(TDB_SIZE));
105 }
106
107 static void nc_thread_starter(void) { 95 static void nc_thread_starter(void) {
108 nc_thread_descriptor_t *tdb = nc_get_tdb(); 96 nc_thread_descriptor_t *tdb = __nc_get_tdb();
109 __newlib_thread_init(); 97 __newlib_thread_init();
110 #if defined(NACL_IN_IRT) 98 #if defined(NACL_IN_IRT)
111 g_is_irt_internal_thread = 1; 99 g_is_irt_internal_thread = 1;
112 #endif 100 #endif
113 void *retval = tdb->start_func(tdb->state); 101 void *retval = tdb->start_func(tdb->state);
114 102
115 /* 103 /*
116 * Free handler list to prevent memory leak in case function returns 104 * Free handler list to prevent memory leak in case function returns
117 * without calling pthread_cleanup_pop(), although doing that is unspecified 105 * without calling pthread_cleanup_pop(), although doing that is unspecified
118 * behaviour. 106 * behaviour.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 nc_free_memory_block_mu(TLS_AND_TDB_MEMORY, block); 224 nc_free_memory_block_mu(TLS_AND_TDB_MEMORY, block);
237 } 225 }
238 } 226 }
239 227
240 /* Initialize a newly allocated TDB to some default values. */ 228 /* Initialize a newly allocated TDB to some default values. */
241 static void nc_tdb_init(nc_thread_descriptor_t *tdb, 229 static void nc_tdb_init(nc_thread_descriptor_t *tdb,
242 nc_basic_thread_data_t *basic_data) { 230 nc_basic_thread_data_t *basic_data) {
243 tdb->tls_base = tdb; 231 tdb->tls_base = tdb;
244 tdb->joinable = PTHREAD_CREATE_JOINABLE; 232 tdb->joinable = PTHREAD_CREATE_JOINABLE;
245 tdb->join_waiting = 0; 233 tdb->join_waiting = 0;
234 tdb->rdlock_count = 0;
246 tdb->stack_node = NULL; 235 tdb->stack_node = NULL;
247 tdb->tls_node = NULL; 236 tdb->tls_node = NULL;
248 tdb->start_func = NULL; 237 tdb->start_func = NULL;
249 tdb->state = NULL; 238 tdb->state = NULL;
250 tdb->irt_thread_data = NULL; 239 tdb->irt_thread_data = NULL;
251 tdb->basic_data = basic_data; 240 tdb->basic_data = basic_data;
252 241
253 basic_data->retval = NULL; 242 basic_data->retval = NULL;
254 basic_data->status = THREAD_RUNNING; 243 basic_data->status = THREAD_RUNNING;
255 if (pthread_cond_init(&basic_data->join_condvar, NULL) != 0) 244 if (pthread_cond_init(&basic_data->join_condvar, NULL) != 0)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 286
298 #else 287 #else
299 288
300 /* 289 /*
301 * Will be called from the library startup code, 290 * Will be called from the library startup code,
302 * which always happens on the application's main thread. 291 * which always happens on the application's main thread.
303 */ 292 */
304 void __pthread_initialize(void) { 293 void __pthread_initialize(void) {
305 __pthread_initialize_minimal(TDB_SIZE); 294 __pthread_initialize_minimal(TDB_SIZE);
306 295
307 struct nc_combined_tdb *tdb = (struct nc_combined_tdb *) nc_get_tdb(); 296 struct nc_combined_tdb *tdb = (struct nc_combined_tdb *) __nc_get_tdb();
308 nc_tdb_init(&tdb->tdb, &tdb->basic_data); 297 nc_tdb_init(&tdb->tdb, &tdb->basic_data);
309 __nc_initial_thread_id = &tdb->basic_data; 298 __nc_initial_thread_id = &tdb->basic_data;
310 299
311 __nc_initialize_globals(); 300 __nc_initialize_globals();
312 } 301 }
313 302
314 #endif 303 #endif
315 304
316 305
317 /* pthread functions */ 306 /* pthread functions */
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 nc_thread_cleanup_handler *handler = __nc_cleanup_handlers; 474 nc_thread_cleanup_handler *handler = __nc_cleanup_handlers;
486 __nc_cleanup_handlers = handler->previous; 475 __nc_cleanup_handlers = handler->previous;
487 if (execute) 476 if (execute)
488 handler->handler_function(handler->handler_arg); 477 handler->handler_function(handler->handler_arg);
489 free(handler); 478 free(handler);
490 } 479 }
491 } 480 }
492 481
493 void pthread_exit(void *retval) { 482 void pthread_exit(void *retval) {
494 /* Get all we need from the tdb before releasing it. */ 483 /* Get all we need from the tdb before releasing it. */
495 nc_thread_descriptor_t *tdb = nc_get_tdb(); 484 nc_thread_descriptor_t *tdb = __nc_get_tdb();
496 nc_thread_memory_block_t *stack_node = tdb->stack_node; 485 nc_thread_memory_block_t *stack_node = tdb->stack_node;
497 int32_t *is_used = &stack_node->is_used; 486 int32_t *is_used = &stack_node->is_used;
498 nc_basic_thread_data_t *basic_data = tdb->basic_data; 487 nc_basic_thread_data_t *basic_data = tdb->basic_data;
499 int joinable = tdb->joinable; 488 int joinable = tdb->joinable;
500 489
501 /* Call cleanup handlers. */ 490 /* Call cleanup handlers. */
502 while (NULL != __nc_cleanup_handlers) { 491 while (NULL != __nc_cleanup_handlers) {
503 pthread_cleanup_pop(1); 492 pthread_cleanup_pop(1);
504 } 493 }
505 494
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 } 612 }
624 613
625 int pthread_kill(pthread_t thread_id, 614 int pthread_kill(pthread_t thread_id,
626 int sig) { 615 int sig) {
627 /* This function is currently unimplemented. */ 616 /* This function is currently unimplemented. */
628 return ENOSYS; 617 return ENOSYS;
629 } 618 }
630 619
631 pthread_t pthread_self(void) { 620 pthread_t pthread_self(void) {
632 /* Get the tdb pointer from gs and use it to return the thread handle. */ 621 /* Get the tdb pointer from gs and use it to return the thread handle. */
633 nc_thread_descriptor_t *tdb = nc_get_tdb(); 622 nc_thread_descriptor_t *tdb = __nc_get_tdb();
634 return tdb->basic_data; 623 return tdb->basic_data;
635 } 624 }
636 625
637 int pthread_equal(pthread_t thread1, pthread_t thread2) { 626 int pthread_equal(pthread_t thread1, pthread_t thread2) {
638 return (thread1 == thread2); 627 return (thread1 == thread2);
639 } 628 }
640 629
641 int pthread_setschedprio(pthread_t thread_id, int prio) { 630 int pthread_setschedprio(pthread_t thread_id, int prio) {
642 if (thread_id != pthread_self()) { 631 if (thread_id != pthread_self()) {
643 /* 632 /*
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 810
822 /* 811 /*
823 * We include this directly in this file rather than compiling it 812 * We include this directly in this file rather than compiling it
824 * separately because there is some code (e.g. libstdc++) that uses weak 813 * separately because there is some code (e.g. libstdc++) that uses weak
825 * references to all pthread functions, but conditionalizes its calls only 814 * 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 815 * 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. 816 * archive, they might not be linked in by static linking.
828 */ 817 */
829 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ 818 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */
830 #include "native_client/src/untrusted/pthread/nc_tsd.c" 819 #include "native_client/src/untrusted/pthread/nc_tsd.c"
OLDNEW
« no previous file with comments | « src/untrusted/pthread/nc_rwlock.c ('k') | src/untrusted/pthread/pthread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698