exception.cc (227983) | exception.cc (228004) |
---|---|
1#include <stdlib.h> 2#include <dlfcn.h> 3#include <stdio.h> 4#include <string.h> 5#include <stdint.h> 6#include <pthread.h> 7#include "typeinfo.h" 8#include "dwarf_eh.h" 9#include "cxxabi.h" 10 | 1#include <stdlib.h> 2#include <dlfcn.h> 3#include <stdio.h> 4#include <string.h> 5#include <stdint.h> 6#include <pthread.h> 7#include "typeinfo.h" 8#include "dwarf_eh.h" 9#include "cxxabi.h" 10 |
11#pragma weak pthread_key_create 12#pragma weak pthread_setspecific 13#pragma weak pthread_getspecific 14#pragma weak pthread_once 15#pragma weak pthread_once 16#pragma weak pthread_cond_signal 17#pragma weak pthread_cond_wait 18#pragma weak pthread_mutex_lock 19#pragma weak pthread_mutex_unlock 20 21 |
|
11using namespace ABI_NAMESPACE; 12 13/** 14 * Saves the result of the landing pad that we have found. For ARM, this is 15 * stored in the generic unwind structure, while on other platforms it is 16 * stored in the C++ exception. 17 */ 18static void saveLandingPad(struct _Unwind_Context *context, --- 265 unchanged lines hidden (view full) --- 284 285 286/** 287 * Once control used to protect the key creation. 288 */ 289static pthread_once_t once_control = PTHREAD_ONCE_INIT; 290 291/** | 22using namespace ABI_NAMESPACE; 23 24/** 25 * Saves the result of the landing pad that we have found. For ARM, this is 26 * stored in the generic unwind structure, while on other platforms it is 27 * stored in the C++ exception. 28 */ 29static void saveLandingPad(struct _Unwind_Context *context, --- 265 unchanged lines hidden (view full) --- 295 296 297/** 298 * Once control used to protect the key creation. 299 */ 300static pthread_once_t once_control = PTHREAD_ONCE_INIT; 301 302/** |
303 * We may not be linked against a full pthread implementation. If we're not, 304 * then we need to fake the thread-local storage by storing 'thread-local' 305 * things in a global. 306 */ 307static bool fakeTLS; 308/** 309 * Thread-local storage for a single-threaded program. 310 */ 311static __cxa_thread_info singleThreadInfo; 312/** |
|
292 * Initialise eh_key. 293 */ 294static void init_key(void) 295{ | 313 * Initialise eh_key. 314 */ 315static void init_key(void) 316{ |
317 if ((0 == pthread_key_create) || 318 (0 == pthread_setspecific) || 319 (0 == pthread_getspecific)) 320 { 321 fakeTLS = true; 322 return; 323 } |
|
296 pthread_key_create(&eh_key, thread_cleanup); | 324 pthread_key_create(&eh_key, thread_cleanup); |
325 pthread_setspecific(eh_key, (void*)0x42); 326 fakeTLS = (pthread_getspecific(eh_key) != (void*)0x42); 327 pthread_setspecific(eh_key, 0); |
|
297} 298 299/** 300 * Returns the thread info structure, creating it if it is not already created. 301 */ 302static __cxa_thread_info *thread_info() 303{ | 328} 329 330/** 331 * Returns the thread info structure, creating it if it is not already created. 332 */ 333static __cxa_thread_info *thread_info() 334{ |
304 pthread_once(&once_control, init_key); | 335 if ((0 == pthread_once) || pthread_once(&once_control, init_key)) 336 { 337 fakeTLS = true; 338 } 339 if (fakeTLS) { return &singleThreadInfo; } |
305 __cxa_thread_info *info = (__cxa_thread_info*)pthread_getspecific(eh_key); 306 if (0 == info) 307 { 308 info = (__cxa_thread_info*)calloc(1, sizeof(__cxa_thread_info)); 309 pthread_setspecific(eh_key, info); 310 } 311 return info; 312} 313/** 314 * Fast version of thread_info(). May fail if thread_info() is not called on 315 * this thread at least once already. 316 */ 317static __cxa_thread_info *thread_info_fast() 318{ | 340 __cxa_thread_info *info = (__cxa_thread_info*)pthread_getspecific(eh_key); 341 if (0 == info) 342 { 343 info = (__cxa_thread_info*)calloc(1, sizeof(__cxa_thread_info)); 344 pthread_setspecific(eh_key, info); 345 } 346 return info; 347} 348/** 349 * Fast version of thread_info(). May fail if thread_info() is not called on 350 * this thread at least once already. 351 */ 352static __cxa_thread_info *thread_info_fast() 353{ |
354 if (fakeTLS) { return &singleThreadInfo; } |
|
319 return (__cxa_thread_info*)pthread_getspecific(eh_key); 320} 321/** 322 * ABI function returning the __cxa_eh_globals structure. 323 */ 324extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals(void) 325{ 326 return &(thread_info()->globals); --- 35 unchanged lines hidden (view full) --- 362static char *emergency_malloc(size_t size) 363{ 364 if (size > 1024) { return 0; } 365 366 __cxa_thread_info *info = thread_info(); 367 // Only 4 emergency buffers allowed per thread! 368 if (info->emergencyBuffersHeld > 3) { return 0; } 369 | 355 return (__cxa_thread_info*)pthread_getspecific(eh_key); 356} 357/** 358 * ABI function returning the __cxa_eh_globals structure. 359 */ 360extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals(void) 361{ 362 return &(thread_info()->globals); --- 35 unchanged lines hidden (view full) --- 398static char *emergency_malloc(size_t size) 399{ 400 if (size > 1024) { return 0; } 401 402 __cxa_thread_info *info = thread_info(); 403 // Only 4 emergency buffers allowed per thread! 404 if (info->emergencyBuffersHeld > 3) { return 0; } 405 |
370 pthread_mutex_lock(&emergency_malloc_lock); | 406 if (pthread_mutex_lock) 407 { 408 pthread_mutex_lock(&emergency_malloc_lock); 409 } |
371 int buffer = -1; 372 while (buffer < 0) 373 { 374 // While we were sleeping on the lock, another thread might have free'd 375 // enough memory for us to use, so try the allocation again - no point 376 // using the emergency buffer if there is some real memory that we can 377 // use... 378 void *m = calloc(1, size); 379 if (0 != m) 380 { | 410 int buffer = -1; 411 while (buffer < 0) 412 { 413 // While we were sleeping on the lock, another thread might have free'd 414 // enough memory for us to use, so try the allocation again - no point 415 // using the emergency buffer if there is some real memory that we can 416 // use... 417 void *m = calloc(1, size); 418 if (0 != m) 419 { |
381 pthread_mutex_unlock(&emergency_malloc_lock); | 420 if (pthread_mutex_unlock) 421 { 422 pthread_mutex_unlock(&emergency_malloc_lock); 423 } |
382 return (char*)m; 383 } 384 for (int i=0 ; i<16 ; i++) 385 { 386 if (!buffer_allocated[i]) 387 { 388 buffer = i; 389 buffer_allocated[i] = true; 390 break; 391 } 392 } 393 // If there still isn't a buffer available, then sleep on the condition 394 // variable. This will be signalled when another thread releases one 395 // of the emergency buffers. 396 if (buffer < 0) 397 { | 424 return (char*)m; 425 } 426 for (int i=0 ; i<16 ; i++) 427 { 428 if (!buffer_allocated[i]) 429 { 430 buffer = i; 431 buffer_allocated[i] = true; 432 break; 433 } 434 } 435 // If there still isn't a buffer available, then sleep on the condition 436 // variable. This will be signalled when another thread releases one 437 // of the emergency buffers. 438 if (buffer < 0) 439 { |
440 // If we don't have pthread_cond_wait, then there is only one 441 // thread and it's already used all of the emergency buffers, so we 442 // have no alternative but to die. Calling abort() instead of 443 // terminate, because terminate can throw exceptions, which can 444 // bring us back here and infinite loop. 445 if (!pthread_cond_wait) 446 { 447 fputs("Terminating while out of memory trying to throw an exception", 448 stderr); 449 abort(); 450 } |
|
398 pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock); 399 } 400 } | 451 pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock); 452 } 453 } |
401 pthread_mutex_unlock(&emergency_malloc_lock); | 454 if (pthread_mutex_unlock) 455 { 456 pthread_mutex_unlock(&emergency_malloc_lock); 457 } |
402 info->emergencyBuffersHeld++; 403 return emergency_buffer + (1024 * buffer); 404} 405 406/** 407 * Frees a buffer returned by emergency_malloc(). 408 * 409 * Note: Neither this nor emergency_malloc() is particularly efficient. This --- 16 unchanged lines hidden (view full) --- 426 assert(buffer > 0 && 427 "Trying to free something that is not an emergency buffer!"); 428 // emergency_malloc() is expected to return 0-initialized data. We don't 429 // zero the buffer when allocating it, because the static buffers will 430 // begin life containing 0 values. 431 memset((void*)ptr, 0, 1024); 432 // Signal the condition variable to wake up any threads that are blocking 433 // waiting for some space in the emergency buffer | 458 info->emergencyBuffersHeld++; 459 return emergency_buffer + (1024 * buffer); 460} 461 462/** 463 * Frees a buffer returned by emergency_malloc(). 464 * 465 * Note: Neither this nor emergency_malloc() is particularly efficient. This --- 16 unchanged lines hidden (view full) --- 482 assert(buffer > 0 && 483 "Trying to free something that is not an emergency buffer!"); 484 // emergency_malloc() is expected to return 0-initialized data. We don't 485 // zero the buffer when allocating it, because the static buffers will 486 // begin life containing 0 values. 487 memset((void*)ptr, 0, 1024); 488 // Signal the condition variable to wake up any threads that are blocking 489 // waiting for some space in the emergency buffer |
434 pthread_mutex_lock(&emergency_malloc_lock); | 490 if (pthread_mutex_lock) 491 { 492 pthread_mutex_lock(&emergency_malloc_lock); 493 } |
435 // In theory, we don't need to do this with the lock held. In practice, 436 // our array of bools will probably be updated using 32-bit or 64-bit 437 // memory operations, so this update may clobber adjacent values. 438 buffer_allocated[buffer] = false; | 494 // In theory, we don't need to do this with the lock held. In practice, 495 // our array of bools will probably be updated using 32-bit or 64-bit 496 // memory operations, so this update may clobber adjacent values. 497 buffer_allocated[buffer] = false; |
439 pthread_cond_signal(&emergency_malloc_wait); 440 pthread_mutex_unlock(&emergency_malloc_lock); | 498 if (pthread_cond_signal && pthread_mutex_unlock) 499 { 500 pthread_cond_signal(&emergency_malloc_wait); 501 pthread_mutex_unlock(&emergency_malloc_lock); 502 } |
441} 442 443static char *alloc_or_die(size_t size) 444{ 445 char *buffer = (char*)calloc(1, size); 446 447 // If calloc() doesn't want to give us any memory, try using an emergency 448 // buffer. --- 973 unchanged lines hidden --- | 503} 504 505static char *alloc_or_die(size_t size) 506{ 507 char *buffer = (char*)calloc(1, size); 508 509 // If calloc() doesn't want to give us any memory, try using an emergency 510 // buffer. --- 973 unchanged lines hidden --- |