Deleted Added
full compact
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 ---