// File: /workspace/github_c_makefile_star2_O2/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 %r14
pushq %rbx
subq $0x48, %rsp
callq 0x6600
movq %rax, %rbx
leaq 0x94e76(%rip), %rdi     # 0xb75e0
callq 0x6ae0
cmpb $0x1, 0x94e5e(%rip)     # 0xb75d4
jne 0x2278f
movq 0x94e59(%rip), %rsi     # 0xb75d8
movq %rbx, %rdi
callq 0x6d40
testl %eax, %eax
jne 0x22894
leaq 0x94e4a(%rip), %r14     # 0xb75e0
movq %r14, %rdi
callq 0x64f0
leaq 0x94e63(%rip), %rdi     # 0xb7608
callq 0x6ae0
movq %r14, %rdi
callq 0x6ae0
movq %rbx, 0x94e1f(%rip)     # 0xb75d8
movb $0x1, 0x94e14(%rip)     # 0xb75d4
movq %r14, %rdi
callq 0x64f0
cmpq $0x0, 0x94e60(%rip)     # 0xb7630
jne 0x227e3
pushq $0x1
popq %rsi
xorl %edi, %edi
callq 0x245c9
movq %rax, 0x94e4d(%rip)     # 0xb7630
leaq 0x5cc8a(%rip), %rdx     # 0x7f474
movq %rsp, %r14
pushq $0x40
popq %rsi
movq %r14, %rdi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x1fab2
movq 0x94e2c(%rip), %rdi     # 0xb7630
movq %r14, %rsi
callq 0x24088
movq %rax, %rbx
testq %rax, %rax
jne 0x2285e
movl $0x118, %edi            # imm = 0x118
callq 0x28bb0
andq $0x0, (%rax)
andl $0x0, 0xa8(%rax)
leaq -0x172(%rip), %rcx      # 0x226be
movq %rcx, 0x8(%rax)
andl $0x0, 0x110(%rax)
leaq 0x6c(%rip), %rcx        # 0x228ae
movq %rcx, 0xb0(%rax)
movq 0x94de0(%rip), %rdi     # 0xb7630
movq %rsp, %rsi
movq %rax, %rdx
callq 0x242d0
movq %rax, %rbx
leaq 0x94d7b(%rip), %r14     # 0xb75e0
movq %r14, %rdi
callq 0x6ae0
movb $0x0, 0x94d60(%rip)     # 0xb75d4
movq %r14, %rdi
callq 0x64f0
leaq 0x94d85(%rip), %rdi     # 0xb7608
callq 0x64f0
movq 0x10(%rbx), %rax
addq $0x48, %rsp
popq %rbx
popq %r14
retq
leaq 0x5d124(%rip), %rsi     # 0x7f9bf
pushq $0x2
popq %rdi
pushq $0x3d
popq %rdx
callq 0x6260
pushq $0x1
popq %rdi
callq 0x68d0