// File: /workspace/github_c_makefile_star2_O1/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
pushq %r14
pushq %rbx
subq $0x40, %rsp
callq 0x6600
movq %rax, %rbx
leaq 0x9c720(%rip), %rdi     # 0xc35c0
callq 0x6ae0
cmpb $0x1, 0x9c708(%rip)     # 0xc35b4
jne 0x26ec5
movq 0x9c703(%rip), %rsi     # 0xc35b8
movq %rbx, %rdi
callq 0x6d40
testl %eax, %eax
jne 0x26fd2
leaq 0x9c6f4(%rip), %r14     # 0xc35c0
movq %r14, %rdi
callq 0x64f0
leaq 0x9c70d(%rip), %rdi     # 0xc35e8
callq 0x6ae0
movq %r14, %rdi
callq 0x6ae0
movq %rbx, 0x9c6c9(%rip)     # 0xc35b8
movb $0x1, 0x9c6be(%rip)     # 0xc35b4
movq %r14, %rdi
callq 0x64f0
cmpq $0x0, 0x9c70a(%rip)     # 0xc3610
jne 0x26f1b
xorl %edi, %edi
movl $0x1, %esi
callq 0x29160
movq %rax, 0x9c6f5(%rip)     # 0xc3610
leaq 0x69562(%rip), %rdx     # 0x90484
xorl %ebp, %ebp
movq %rsp, %r14
movq %r14, %rdi
movl $0x40, %esi
movq %rbx, %rcx
xorl %eax, %eax
callq 0x23c18
movq 0x9c6d0(%rip), %rdi     # 0xc3610
movq %r14, %rsi
callq 0x28b2c
movq %rax, %rbx
testq %rax, %rax
jne 0x26f9b
movl $0x118, %edi            # imm = 0x118
callq 0x2dc95
movq $0x0, (%rax)
movl %ebp, 0xa8(%rax)
leaq -0xf6(%rip), %rcx       # 0x26e78
movq %rcx, 0x8(%rax)
movl %ebp, 0x110(%rax)
leaq 0x73(%rip), %rcx        # 0x26ff2
movq %rcx, 0xb0(%rax)
movq 0x9c683(%rip), %rdi     # 0xc3610
movq %rsp, %rsi
movq %rax, %rdx
callq 0x28dbe
movq %rax, %rbx
leaq 0x9c61e(%rip), %r14     # 0xc35c0
movq %r14, %rdi
callq 0x6ae0
movb $0x0, 0x9c603(%rip)     # 0xc35b4
movq %r14, %rdi
callq 0x64f0
leaq 0x9c628(%rip), %rdi     # 0xc35e8
callq 0x64f0
movq 0x10(%rbx), %rax
addq $0x40, %rsp
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x699f6(%rip), %rsi     # 0x909cf
movl $0x3d, %edx
movl $0x2, %edi
callq 0x6260
movl $0x1, %edi
callq 0x68d0