// File: /workspace/github_c_makefile_star2_O0/icebert[P]pblat/lib/errabort.c
// Function: getThreadVars
static struct perThreadAbortVars *getThreadVars()
/* Return a pointer to the perThreadAbortVars for the current pthread. */
{
pthread_t pid = pthread_self(); //  pthread_t can be a pointer or a number, implementation-dependent.

// Test for out-of-memory condition causing re-entrancy into this function that would block
// on its own main mutex ptavMutex.  Do this by looking for its own pid.
// Some care must be exercised in testing and comparing the threads pid against one in-use.
// We need yet another mutex and a boolean to tell us when the pidInUse value may be safely compared to pid.

// Use a boolean since there is no known unused value for pthread_t variable. NULL and -1 are not portable.
static boolean pidInUseValid = FALSE;  // tells when pidInUse contains a valid pid that can be compared.
static pthread_t pidInUse; // there is no "unused" value to which we can initialize this.
static pthread_mutex_t pidInUseMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock( &pidInUseMutex );
// If this pid equals pidInUse, then this function has been re-entered due to severe out-of-memory error.
// But we only compare them when pidInUseValid is TRUE.
if (pidInUseValid && pthread_equal(pid, pidInUse)) 
    {
    // Avoid deadlock on self by exiting immediately.
    // Use pthread_equal because directly comparing two pthread_t vars is not allowed.
    // This re-entrancy only happens when it has aborted already due to out of memory
    // which should be a rare occurrence.
    char *errMsg = "errAbort re-entered due to out-of-memory condition. Exiting.\n";
    write(STDERR_FILENO, errMsg, strlen(errMsg)); 
    exit(1);   // out of memory is a serious problem, exit immediately, but allow atexit cleanup.
    }
pthread_mutex_unlock( &pidInUseMutex );

// This is the main mutex we really care about.
// It controls access to the hash where thread-specific data is stored.
static pthread_mutex_t ptavMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock( &ptavMutex );

// safely tell threads that pidInUse
// is valid and correctly set and may be compared to pid
pthread_mutex_lock( &pidInUseMutex );
pidInUse = pthread_self();  // setting it directly to pid is not allowed.
pidInUseValid = TRUE;
pthread_mutex_unlock( &pidInUseMutex );

// This means that if we crash due to out-of-memory below,
// it will be able to detect the re-entrancy and handle it above.

static struct hash *perThreadVars = NULL;
if (perThreadVars == NULL)
    perThreadVars = hashNew(0);
// convert the pid into a string for the hash key
char pidStr[64];
safef(pidStr, sizeof(pidStr), "%lld",  ptrToLL(pid));
struct hashEl *hel = hashLookup(perThreadVars, pidStr);
if (hel == NULL)
    {
    // if it is the first time, initialization the perThreadAbortVars
    struct perThreadAbortVars *ptav;
    AllocVar(ptav);
    ptav->debugPushPopErr = FALSE;
    ptav->errAbortInProgress = FALSE;
    ptav->warnIx = 0;
    ptav->warnArray[0] = defaultVaWarn;
    ptav->abortIx = 0;
    ptav->abortArray[0] = defaultAbort;
    hel = hashAdd(perThreadVars, pidStr, ptav);
    }

// safely tell other threads that pidInUse
// is no longer valid and may not be compared to pid
pthread_mutex_lock( &pidInUseMutex );
pidInUseValid = FALSE;
pthread_mutex_unlock( &pidInUseMutex );

// unlock our mutex controlling the hash of thread-specific data
pthread_mutex_unlock( &ptavMutex );
return (struct perThreadAbortVars *)(hel->val);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
callq 0x6600
movq %rax, -0x8(%rbp)
leaq 0xd3738(%rip), %rdi     # 0x109a00
callq 0x6ae0
cmpl $0x0, 0xd3720(%rip)     # 0x1099f4
je 0x36322
movq -0x8(%rbp), %rdi
movq 0xd3717(%rip), %rsi     # 0x1099f8
callq 0x6d40
cmpl $0x0, %eax
je 0x36322
leaq 0xa4587(%rip), %rax     # 0xda879
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rdi
callq 0x62c0
movq -0x68(%rbp), %rsi
movq %rax, %rdx
movl $0x2, %edi
callq 0x6250
movl $0x1, %edi
callq 0x68b0
leaq 0xd36d7(%rip), %rdi     # 0x109a00
callq 0x64e0
leaq 0xd36f3(%rip), %rdi     # 0x109a28
callq 0x6ae0
leaq 0xd36bf(%rip), %rdi     # 0x109a00
callq 0x6ae0
callq 0x6600
movq %rax, 0xd36a6(%rip)     # 0x1099f8
movl $0x1, 0xd3698(%rip)     # 0x1099f4
leaq 0xd369d(%rip), %rdi     # 0x109a00
callq 0x64e0
cmpq $0x0, 0xd36e0(%rip)     # 0x109a50
jne 0x36385
xorl %edi, %edi
movl $0x1, %esi
callq 0x398a0
movq %rax, 0xd36cb(%rip)     # 0x109a50
leaq -0x50(%rbp), %rdi
movq -0x8(%rbp), %rcx
movl $0x40, %esi
leaq 0xa3f63(%rip), %rdx     # 0xda2fc
movb $0x0, %al
callq 0x31090
movq 0xd36a9(%rip), %rdi     # 0x109a50
leaq -0x50(%rbp), %rsi
callq 0x38e20
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
jne 0x36433
movl $0x118, %edi            # imm = 0x118
callq 0x40c50
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movl $0x0, (%rax)
movq -0x60(%rbp), %rax
movl $0x0, 0x4(%rax)
movq -0x60(%rbp), %rax
movl $0x0, 0xa8(%rax)
movq -0x60(%rbp), %rax
leaq -0x217(%rip), %rcx      # 0x361e0
movq %rcx, 0x8(%rax)
movq -0x60(%rbp), %rax
movl $0x0, 0x110(%rax)
movq -0x60(%rbp), %rax
leaq 0x5c(%rip), %rcx        # 0x36470
movq %rcx, 0xb0(%rax)
movq 0xd362e(%rip), %rdi     # 0x109a50
leaq -0x50(%rbp), %rsi
movq -0x60(%rbp), %rdx
callq 0x39230
movq %rax, -0x58(%rbp)
leaq 0xd35c6(%rip), %rdi     # 0x109a00
callq 0x6ae0
movl $0x0, 0xd35ab(%rip)     # 0x1099f4
leaq 0xd35b0(%rip), %rdi     # 0x109a00
callq 0x64e0
leaq 0xd35cc(%rip), %rdi     # 0x109a28
callq 0x64e0
movq -0x58(%rbp), %rax
movq 0x10(%rax), %rax
addq $0x70, %rsp
popq %rbp
retq
nop