// File: /workspace/github_cpp_makefile_star2_O3/BenLangmead[P]bowtie/ebwt_search.cpp
// Function: mismatchSearchWorkerFull(void*)
static void mismatchSearchWorkerFull(void *vp){
	thread_tracking_pair *p = (thread_tracking_pair*) vp;
	int tid = p->tid;
#else
static void mismatchSearchWorkerFull(void *vp){
	int tid = *((int*)vp);
#endif
	if(thread_stealing) {
		increment_thread_counter();
	}
	PatternComposer&	_patsrc = *mismatchSearch_patsrc;
	HitSink&		_sink   = *mismatchSearch_sink;
	Ebwt&			ebwtFw  = *mismatchSearch_ebwtFw;
	Ebwt&			ebwtBw  = *mismatchSearch_ebwtBw;
	EList<BTRefString >& os      = *mismatchSearch_os;

	// Per-thread initialization
	PatternSourcePerThreadFactory* patsrcFact = createPatsrcFactory(_patsrc, tid, readsPerBatch);
	PatternSourcePerThread* patsrc = patsrcFact->create();
	HitSinkPerThreadFactory* sinkFact = createSinkFactory(_sink, tid);
	HitSinkPerThread* sink = sinkFact->create();
	EbwtSearchParams params(
	        *sink,      // HitSinkPerThread
	        os,         // reference sequences
	        true,       // read is forward
	        false);     // index is mirror index
	GreedyDFSRangeSource bt(
	        &ebwtFw, params,
	        0xffffffff,     // qualThresh
	        0xffffffff,     // max backtracks (no max)
	        0,              // reportPartials (don't)
	        true,           // reportExacts
	        rangeMode,      // reportRanges
	        NULL,           // seedlings
	        NULL,           // mutations
	        verbose,        // verbose
	        &os,
	        false);         // considerQuals
	bool skipped = false;
	pair<bool, bool> get_read_ret = make_pair(false, false);
#ifdef PER_THREAD_TIMING
	uint64_t ncpu_changeovers = 0;
	uint64_t nnuma_changeovers = 0;

	int current_cpu = 0, current_node = 0;
	get_cpu_and_node(current_cpu, current_node);

	std::stringstream ss;
	std::string msg;
	ss << "thread: " << tid << " time: ";
	msg = ss.str();
	{
		Timer timer(std::cout, msg.c_str());
#endif
		while(true) {
#ifdef PER_THREAD_TIMING
			int cpu = 0, node = 0;
			get_cpu_and_node(cpu, node);
			if(cpu != current_cpu) {
				ncpu_changeovers++;
				current_cpu = cpu;
			}
			if(node != current_node) {
				nnuma_changeovers++;
				current_node = node;
			}
#endif
			FINISH_READ(patsrc);
			GET_READ(patsrc);
			uint32_t plen = (uint32_t)patFw.length();
			uint32_t s = plen;
			uint32_t s3 = s >> 1; // length of 3' half of seed
			uint32_t s5 = (s >> 1) + (s & 1); // length of 5' half of seed
			#define DONEMASK_SET(p)
			#include "search_1mm_phase1.c"
			#include "search_1mm_phase2.c"
			#undef DONEMASK_SET
		} // End read loop
		FINISH_READ(patsrc);
#ifdef PER_THREAD_TIMING
		ss.str("");
		ss.clear();
		ss << "thread: " << tid << " cpu_changeovers: " << ncpu_changeovers << std::endl
		   << "thread: " << tid << " node_changeovers: " << nnuma_changeovers << std::endl;
		std::cout << ss.str();
	}
#endif
#if (__cplusplus >= 201103L)
	p->done->fetch_add(1);
#endif
    	WORKER_EXIT();
}

/**
 * Search through a single (forward) Ebwt index for exact end-to-end
 * hits.  Assumes that index is already loaded into memory.
 */
static void mismatchSearchFull(PatternComposer& _patsrc,
                               HitSink& _sink,
                               Ebwt& ebwtFw,
                               Ebwt& ebwtBw,
                               EList<BTRefString >& os)
{
	mismatchSearch_patsrc       = &_patsrc;
	mismatchSearch_sink         = &_sink;
	mismatchSearch_ebwtFw       = &ebwtFw;
	mismatchSearch_ebwtBw       = &ebwtBw;
	mismatchSearch_doneMask     = NULL;
	mismatchSearch_hitMask      = NULL;
	mismatchSearch_os           = &os;

	assert(!ebwtFw.isInMemory());
	assert(!ebwtBw.isInMemory());
	{
		// Load the other half of the index into memory
		Timer _t(cerr, "Time loading forward index: ", timing);
		ebwtFw.loadIntoMemory(-1, !noRefNames, startVerbose);
	}
	{
		// Load the other half of the index into memory
		Timer _t(cerr, "Time loading mirror index: ", timing);
		ebwtBw.loadIntoMemory(-1, !noRefNames, startVerbose);
	}
	// Create range caches, which are shared among all aligners
	BitPairReference *refs = NULL;
	bool pair = mates1.size() > 0 || mates12.size() > 0;
	if(pair && mixedThresh < 0xffffffff) {
		Timer _t(cerr, "Time loading reference: ", timing);
		refs = new BitPairReference(adjustedEbwtFileBase, sanityCheck, NULL, &os, false, true, useMm, useShmem, mmSweep, verbose, startVerbose);
		if(!refs->loaded()) throw 1;
	}
	mismatchSearch_refs = refs;

	int tids[max(nthreads, thread_ceiling)];
#if (__cplusplus >= 201103L)
	EList<std::thread*> threads;
	EList<thread_tracking_pair> tps;
	tps.resizeExact(max(nthreads, thread_ceiling));
#else
	EList<tthread::thread*> threads;
#endif

#if (__cplusplus >= 201103L)
	std::atomic<int> all_threads_done;
	all_threads_done = 0;
#endif

	CHUD_START();
	{
		Timer _t(cerr, "Time for 1-mismatch full-index search: ", timing);

#ifndef _WIN32
		int pid = 0;
		if(thread_stealing) {
			pid = getpid();
			write_pid(thread_stealing_dir.c_str(), pid);
			thread_counter = 0;
		}
#endif

		for(int i = 0; i < nthreads; i++) {
			tids[i] = i;
#if (__cplusplus >= 201103L)
			tps[i].tid = tids[i];
			tps[i].done = &all_threads_done;
			if (i == nthreads - 1) {
				if(stateful) {
					mismatchSearchWorkerFullStateful((void*)&tps[i]);
				} else {
					mismatchSearchWorkerFull((void*)&tps[i]);
				}
			}
			else {
				if(stateful) {
					threads.push_back(new std::thread(mismatchSearchWorkerFullStateful, (void*)&tps[i]));
				} else {
					threads.push_back(new std::thread(mismatchSearchWorkerFull, (void*)&tps[i]));
				}
				threads[i]->detach();
				SLEEP(10);
			}
#else
			if (i == nthreads - 1) {
				if(stateful) {
					mismatchSearchWorkerFullStateful((void*)(tids + i));
				} else {
					mismatchSearchWorkerFull((void*)(tids + i));
				}
			}
			else {
				if(stateful) {
					threads.push_back(new tthread::thread(mismatchSearchWorkerFullStateful, (void *)(tids + i)));
				} else {
					threads.push_back(new tthread::thread(mismatchSearchWorkerFull, (void *)(tids + i)));
				}
			}
#endif
		}

#ifndef _WIN32
		if(thread_stealing) {
			int orig_threads = nthreads, steal_ctr = 1;
			for(int j = 0; j < 10; j++) {
				sleep(1);
			}
			while(thread_counter > 0) {
				if(steal_thread(pid, orig_threads)) {
					nthreads++;
					tids[nthreads-1] = nthreads;
#if (__cplusplus >= 201103L)
					tps[nthreads-1].tid = nthreads - 1;
					tps[nthreads-1].done = &all_threads_done;
					if(stateful) {
						threads.push_back(new std::thread(mismatchSearchWorkerFullStateful, (void*)&tps[nthreads-1]));
					} else {
						threads.push_back(new std::thread(mismatchSearchWorkerFull, (void*)&tps[nthreads-1]));
					}
					threads[nthreads - 1]->detach();
					SLEEP(10);
#else
					if(stateful) {
						threads.push_back(new tthread::thread(mismatchSearchWorkerFullStateful, (void *)(tids + nthreads - 1)));
					} else {
						threads.push_back(new tthread::thread(mismatchSearchWorkerFull, (void *)(tids + nthreads - 1)));
					}
#endif
					cerr << "pid " << pid << " started new worker # " << nthreads << endl;
				}
				steal_ctr++;
				for(int j = 0; j < 10; j++) {
					sleep(1);
				}
			}
		}
#endif

#if (__cplusplus >= 201103L)
		while(all_threads_done < nthreads) {
			SLEEP(10);
		}
#else
		for (int i = 0; i < nthreads - 1; i++) {
			threads[i]->join();
		}
#endif

#ifndef _WIN32
		if(thread_stealing) {
			del_pid(thread_stealing_dir.c_str(), pid);
		}
#endif
	}
	if(refs != NULL) delete refs;

	for (int i = 0; i < nthreads - 1; i++) {
		if (threads[i] != NULL) {
			delete threads[i];
		}
	}
}

#define SWITCH_TO_FW_INDEX() { \
	/* Evict the mirror index from memory if necessary */ \
	if(ebwtBw.isInMemory()) ebwtBw.evictFromMemory(); \
	assert(!ebwtBw.isInMemory()); \
	/* Load the forward index into memory if necessary */ \
	if(!ebwtFw.isInMemory()) { \
		Timer _t(cerr, "Time loading forward index: ", timing); \
		ebwtFw.loadIntoMemory(-1, !noRefNames, startVerbose); \
	} \
	assert(ebwtFw.isInMemory()); \
	_patsrc.reset(); /* rewind pattern source to first pattern */ \
}

#define SWITCH_TO_BW_INDEX() { \
	/* Evict the forward index from memory if necessary */ \
	if(ebwtFw.isInMemory()) ebwtFw.evictFromMemory(); \
	assert(!ebwtFw.isInMemory()); \
	/* Load the forward index into memory if necessary */ \
	if(!ebwtBw.isInMemory()) { \
		Timer _t(cerr, "Time loading mirror index: ", timing); \
		ebwtBw.loadIntoMemory(-1, !noRefNames, startVerbose);   \
	} \
	assert(ebwtBw.isInMemory()); \
	_patsrc.reset(); /* rewind pattern source to first pattern */ \
}

#define ASSERT_NO_HITS_FW(ebwtfw) \
	if(sanityCheck && os.size() > 0) { \
		EList<Hit> hits; \
		uint32_t threeRevOff = (seedMms <= 3) ? s : 0; \
		uint32_t twoRevOff   = (seedMms <= 2) ? s : 0; \
		uint32_t oneRevOff   = (seedMms <= 1) ? s : 0; \
		uint32_t unrevOff    = (seedMms == 0) ? s : 0; \
		if(hits.size() > 0) { \
			/* Print offending hit obtained by oracle */ \
			::printHit( \
				os, \
				hits[0], \
				patFw, \
				plen, \
				unrevOff, \
				oneRevOff, \
				twoRevOff, \
				threeRevOff, \
				ebwtfw);  /* ebwtFw */ \
		} \
		assert_eq(0, hits.size()); \
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x238, %rsp            # imm = 0x238
movq %rdi, 0x40(%rsp)
movslq (%rdi), %rax
movq %rax, (%rsp)
cmpb $0x1, 0x545dd(%rip)     # 0x6d298
jne 0x18cc4
lock
incl 0x54538(%rip)           # 0x6d1fc
movq 0x54695(%rip), %r12     # 0x6d360
movq 0x54696(%rip), %r15     # 0x6d368
movq 0x54697(%rip), %rbx     # 0x6d370
movq 0x54698(%rip), %rax     # 0x6d378
movq %rax, 0x38(%rsp)
movq 0x54694(%rip), %r14     # 0x6d380
movl 0x545c2(%rip), %ebp     # 0x6d2b4
movl $0x20, %edi
callq 0x94b0
movq %rax, %rdi
movl 0x545eb(%rip), %eax     # 0x6d2f0
movl 0x54541(%rip), %ecx     # 0x6d24c
leaq 0x4fdee(%rip), %rdx     # 0x68b00
movq %rdx, (%rdi)
movq %r12, 0x8(%rdi)
movl %ebp, 0x10(%rdi)
movl %eax, 0x14(%rdi)
movl %ecx, 0x18(%rdi)
movq %rdi, 0x18(%rsp)
callq 0x24942
movq %rax, %r13
movq %r15, %rdi
movq (%rsp), %rsi
callq 0x188b3
movq %rax, %rdi
movq (%rax), %rax
movq %rdi, 0x10(%rsp)
callq *0x10(%rax)
leaq 0x20(%rsp), %rdi
movq %rax, (%rsp)
movq %rax, (%rdi)
movq %r14, 0x8(%rdi)
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl %ecx, 0x10(%rdi)
movb $0x1, %sil
movb %sil, 0x14(%rdi)
movb 0x544e2(%rip), %r8b     # 0x6d251
movb 0x544c8(%rip), %dl      # 0x6d23d
pxor %xmm0, %xmm0
movdqa %xmm0, 0x50(%rsp)
movdqa %xmm0, 0x60(%rsp)
movq %rbx, 0x48(%rsp)
movq %rbx, 0x70(%rsp)
movq %rdi, 0x78(%rsp)
movdqa %xmm0, 0x80(%rsp)
movb %sil, 0x90(%rsp)
movl %ecx, 0x94(%rsp)
movdqu %xmm0, 0x98(%rsp)
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movq %rax, 0xa8(%rsp)
xorl %edi, %edi
movq %rdi, 0xb0(%rsp)
movl $0x80, %ecx
movq %rcx, 0xb8(%rsp)
movq %rdi, 0xc0(%rsp)
movq %rax, 0xc8(%rsp)
movq %rdi, 0xd0(%rsp)
movq %rcx, 0xd8(%rsp)
movdqa %xmm0, 0xe0(%rsp)
movl $0x0, 0xf0(%rsp)
movb %sil, 0xf4(%rsp)
movb %r8b, 0xf5(%rsp)
movdqu %xmm0, 0xf8(%rsp)
movq %r14, 0x108(%rsp)
testq %r14, %r14
je 0x18e41
cmpq $0x0, 0x18(%r14)
setne %dil
leaq 0x50(%rsp), %rbp
movb %dil, 0xc0(%rbp)
xorl %ebx, %ebx
movw %bx, 0xc1(%rbp)
movq %rbx, 0xc4(%rbp)
leaq 0x4fc1c(%rip), %rdi     # 0x68a80
movq %rdi, 0xd0(%rbp)
movdqu %xmm0, 0xd8(%rbp)
movdqa %xmm0, 0xf0(%rbp)
movq %rbx, 0x100(%rbp)
movl $0xffffffff, 0x108(%rbp) # imm = 0xFFFFFFFF
movb %bl, 0x10c(%rbp)
movq %rbx, 0x110(%rbp)
movw %bx, 0x118(%rbp)
movb %sil, 0x11a(%rbp)
movw $0xffff, %di            # imm = 0xFFFF
movw %di, 0x11c(%rbp)
movb $-0x1, %r8b
movb %r8b, 0x11e(%rbp)
movq %rbx, 0x120(%rbp)
movw %bx, 0x128(%rbp)
movb %sil, 0x12a(%rbp)
movw %di, 0x12c(%rbp)
movb %r8b, 0x12e(%rbp)
movabsq $0x3c6ef35f0019660d, %rsi # imm = 0x3C6EF35F0019660D
movq %rsi, 0x134(%rbp)
movb %bl, 0x144(%rbp)
movb %dl, 0x148(%rbp)
movq %rbx, 0x150(%rbp)
movq %rax, 0x158(%rbp)
movq %rbx, 0x160(%rbp)
movq %rcx, 0x168(%rbp)
movq %rbx, 0x170(%rbp)
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movq %rdx, 0x178(%rbp)
movw %bx, 0x180(%rbp)
movq %rbx, 0x184(%rbp)
movw $0x101, 0x18c(%rbp)     # imm = 0x101
movq %rax, 0x190(%rbp)
movq %rbx, 0x198(%rbp)
movq %rcx, 0x1a0(%rbp)
movq %rax, 0x1b0(%rbp)
movq %rbx, 0x1b8(%rbp)
movq %rcx, 0x1c0(%rbp)
movq %rbx, 0x1a8(%rbp)
movdqu %xmm0, 0x1c8(%rbp)
xorl %r15d, %r15d
testb $0x1, %bl
je 0x18f9c
movq (%rsp), %rdi
movq (%rdi), %rax
movq %r13, %rsi
movl $0x1, %edx
movl $0x1, %ecx
callq *0x10(%rax)
xorl %ebx, %ebx
testb $0x1, %r15b
jne 0x19288
movq %r13, %rdi
callq 0x4aeaa
movl %eax, %ebx
movq 0x50(%r13), %rcx
movq 0x58(%r13), %rax
addq %rcx, %rax
movl 0x54293(%rip), %edx     # 0x6d254
cmpq %rdx, %rax
jae 0x192a4
movl %ebx, %r15d
shrl $0x8, %r15d
andl $0x1, %r15d
testb $0x1, %bl
je 0x1927e
movq 0x18(%r13), %rdx
imulq $0x268, %rcx, %rcx      # imm = 0x268
movl %eax, 0x30(%rsp)
movl 0x20(%rdx,%rcx), %r14d
movq 0x48(%rsp), %rax
movq %rax, 0x70(%rsp)
movb $0x1, 0xf4(%rsp)
cmpl $0x1, %r14d
jbe 0x192ff
cmpb $0x0, 0x542df(%rip)     # 0x6d2f4
jne 0x19061
movb $0x1, 0x34(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
movq %rbp, %rdi
callq 0x3dc68
movq $0x0, 0x114(%rsp)
movd %r14d, %xmm0
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movdqa %xmm0, 0x80(%rsp)
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3df16
testb %al, %al
jne 0x18f7e
cmpb $0x0, 0x5428d(%rip)     # 0x6d2f5
jne 0x190b4
movb $0x0, 0x34(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
movq %rbp, %rdi
callq 0x3dc68
movq $0x0, 0x114(%rsp)
movd %r14d, %xmm0
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movdqa %xmm0, 0x80(%rsp)
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3df16
testb %al, %al
jne 0x18f7e
movq (%rsp), %rdi
movq (%rdi), %rax
xorl %esi, %esi
callq *0x40(%rax)
movq (%rsp), %rcx
movl $0x1, 0x10(%rcx)
testb %al, %al
jne 0x18f7e
movl %r14d, %eax
shrl %eax
movl %r14d, %r12d
movl %eax, 0xc(%rsp)
subl %eax, %r12d
movb $0x0, 0xf4(%rsp)
cmpb $0x0, 0x54204(%rip)     # 0x6d2f5
jne 0x19145
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
movq %rbp, %rdi
callq 0x3dc68
movq $0x0, 0x114(%rsp)
movl %r12d, 0x80(%rsp)
movl %r14d, 0x84(%rsp)
movl %r14d, 0x88(%rsp)
movl %r14d, 0x8c(%rsp)
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3df16
testb %al, %al
jne 0x18f7e
cmpb $0x0, 0x541a8(%rip)     # 0x6d2f4
jne 0x191a5
movb $0x1, 0x34(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
movq %rbp, %rdi
callq 0x3dc68
movq $0x0, 0x114(%rsp)
movl %r12d, 0x80(%rsp)
movl %r14d, 0x84(%rsp)
movl %r14d, 0x88(%rsp)
movl %r14d, 0x8c(%rsp)
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3df16
testb %al, %al
jne 0x18f7e
movq 0x38(%rsp), %rax
movq %rax, 0x70(%rsp)
movb $0x0, 0xf4(%rsp)
cmpb $0x0, 0x54137(%rip)     # 0x6d2f5
jne 0x1921a
movb $0x0, 0x34(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
movq %rbp, %rdi
callq 0x3dc68
movq $0x0, 0x114(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x80(%rsp)
movl %r14d, 0x84(%rsp)
movl %r14d, 0x88(%rsp)
movl %r14d, 0x8c(%rsp)
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3df16
testb %al, %al
jne 0x18f7e
cmpb $0x0, 0x540d3(%rip)     # 0x6d2f4
jne 0x18f7e
movb $0x1, 0x34(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
movq %rbp, %rdi
callq 0x3dc68
movq $0x0, 0x114(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x80(%rsp)
movl %r14d, 0x84(%rsp)
movl %r14d, 0x88(%rsp)
movl %r14d, 0x8c(%rsp)
movq %rbp, %rdi
xorl %esi, %esi
callq 0x3df16
jmp 0x18f7e
btl $0x8, %ebx
jae 0x18f7e
testb $0x1, %bl
je 0x192a4
movq (%rsp), %rdi
movq (%rdi), %rax
movq %r13, %rsi
movl $0x1, %edx
movl $0x1, %ecx
callq *0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x8(%rax), %rax
lock
incl (%rax)
movq 0x18(%rsp), %rdi
movq (%rdi), %rax
movq %r13, %rsi
callq *0x10(%rax)
movq 0x18(%rsp), %rdi
movq (%rdi), %rax
callq *0x28(%rax)
movq 0x10(%rsp), %rdi
movq (%rdi), %rax
movq (%rsp), %rsi
callq *0x20(%rax)
movq 0x10(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
leaq 0x50(%rsp), %rdi
callq 0x3e34e
addq $0x238, %rsp            # imm = 0x238
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x50cea(%rip), %rdi     # 0x69ff0
leaq 0x3cecf(%rip), %rsi     # 0x561dc
movl $0x42, %edx
callq 0x9560
movq 0x50cd2(%rip), %rdi     # 0x69ff0
callq 0x91f0
movl $0x4, %edi
callq 0x9200
movl $0x1, (%rax)
movq 0x50bfe(%rip), %rsi     # 0x69f38
movq %rax, %rdi
xorl %edx, %edx
callq 0x98f0
jmp 0x1934c
jmp 0x1934c
jmp 0x1934c
jmp 0x1934c
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x3e34e
movq %rbx, %rdi
callq 0x9930