// File: /workspace/github_cpp_makefile_star2_O1/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, 0x30(%rsp)
movslq (%rdi), %rax
movq %rax, 0x10(%rsp)
cmpb $0x1, 0x553b0(%rip)     # 0x6e298
jne 0x18ef1
lock
incl 0x5530b(%rip)           # 0x6e1fc
movq 0x55468(%rip), %r14     # 0x6e360
movq 0x55469(%rip), %r12     # 0x6e368
movq 0x5546a(%rip), %r15     # 0x6e370
movq 0x5546b(%rip), %rax     # 0x6e378
movq %rax, 0x48(%rsp)
movq 0x55467(%rip), %rbx     # 0x6e380
movl 0x55395(%rip), %ebp     # 0x6e2b4
movl $0x20, %edi
callq 0x94b0
movq %rax, %rdi
movl 0x553be(%rip), %eax     # 0x6e2f0
movl 0x55314(%rip), %ecx     # 0x6e24c
leaq 0x50b41(%rip), %rdx     # 0x69a80
movq %rdx, (%rdi)
movq %r14, 0x8(%rdi)
movl %ebp, 0x10(%rdi)
movl %eax, 0x14(%rdi)
movl %ecx, 0x18(%rdi)
movq %rdi, 0x40(%rsp)
callq 0x24c0c
movq %rax, %r13
movq %r12, %rdi
movq 0x10(%rsp), %rsi
callq 0x18adf
movq %rax, %r14
movq (%rax), %rax
movq %r14, %rdi
callq *0x10(%rax)
movq %rax, %r12
leaq 0x18(%rsp), %rax
movq %r12, (%rax)
movq %rbx, 0x8(%rax)
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl %ecx, 0x10(%rax)
movb $0x1, %sil
movb %sil, 0x14(%rax)
movb 0x552b7(%rip), %dil     # 0x6e251
movb 0x5529d(%rip), %dl      # 0x6e23d
xorps %xmm0, %xmm0
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x60(%rsp)
movq %r15, 0x10(%rsp)
movq %r15, 0x70(%rsp)
movq %rax, 0x78(%rsp)
movaps %xmm0, 0x80(%rsp)
movb %sil, 0x90(%rsp)
movl %ecx, 0x94(%rsp)
movups %xmm0, 0x98(%rsp)
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movq %rax, 0xa8(%rsp)
xorl %r8d, %r8d
movq %r8, 0xb0(%rsp)
movl $0x80, %ecx
movq %rcx, 0xb8(%rsp)
movq %r8, 0xc0(%rsp)
movq %rax, 0xc8(%rsp)
movq %r8, 0xd0(%rsp)
movq %rcx, 0xd8(%rsp)
movaps %xmm0, 0xe0(%rsp)
movl $0x0, 0xf0(%rsp)
movb %sil, 0xf4(%rsp)
movb %dil, 0xf5(%rsp)
movups %xmm0, 0xf8(%rsp)
movq %rbx, 0x108(%rsp)
testq %rbx, %rbx
movq %r14, 0x38(%rsp)
je 0x1906d
cmpq $0x0, 0x18(%rbx)
setne %dil
jmp 0x1906f
xorl %edi, %edi
leaq 0x50(%rsp), %r10
movb %dil, 0xc0(%r10)
xorl %r9d, %r9d
movw %r9w, 0xc1(%r10)
movq %r9, 0xc4(%r10)
leaq 0x5096c(%rip), %rdi     # 0x69a00
movq %rdi, 0xd0(%r10)
movups %xmm0, 0xd8(%r10)
movaps %xmm0, 0xf0(%r10)
movq %r9, 0x100(%r10)
movl $0xffffffff, 0x108(%r10) # imm = 0xFFFFFFFF
movb %r9b, 0x10c(%r10)
movq %r9, 0x110(%r10)
movw %r9w, 0x118(%r10)
movb %sil, 0x11a(%r10)
movw $0xffff, %di            # imm = 0xFFFF
movw %di, 0x11c(%r10)
movb $-0x1, %r8b
movb %r8b, 0x11e(%r10)
movq %r9, 0x120(%r10)
movw %r9w, 0x128(%r10)
movb %sil, 0x12a(%r10)
movw %di, 0x12c(%r10)
movb %r8b, 0x12e(%r10)
movabsq $0x3c6ef35f0019660d, %rsi # imm = 0x3C6EF35F0019660D
movq %rsi, 0x134(%r10)
movb %r9b, 0x144(%r10)
movb %dl, 0x148(%r10)
movq %r9, 0x150(%r10)
movq %rax, 0x158(%r10)
movq %r9, 0x160(%r10)
movq %rcx, 0x168(%r10)
movq %r9, 0x170(%r10)
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movq %rdx, 0x178(%r10)
movw %r9w, 0x180(%r10)
movq %r9, 0x184(%r10)
movw $0x101, 0x18c(%r10)     # imm = 0x101
movq %rax, 0x190(%r10)
movq %r9, 0x198(%r10)
movq %rcx, 0x1a0(%r10)
movq %r9, 0x1a8(%r10)
movq %rax, 0x1b0(%r10)
movq %r9, 0x1b8(%r10)
movq %rcx, 0x1c0(%r10)
movups %xmm0, 0x1c8(%r10)
xorl %ebx, %ebx
xorl %r14d, %r14d
testb $0x1, %bl
je 0x191d8
movq (%r12), %rax
movq %r12, %rdi
movq %r13, %rsi
movl $0x1, %edx
movl $0x1, %ecx
callq *0x10(%rax)
xorl %ebx, %ebx
testb $0x1, %r14b
jne 0x194f9
movq %r13, %rdi
callq 0x4c244
movzwl %ax, %ebx
movl %ebx, %r14d
shrl $0x8, %r14d
movq 0x50(%r13), %rcx
movq 0x58(%r13), %rax
addq %rcx, %rax
movl 0x5504f(%rip), %edx     # 0x6e254
cmpq %rdx, %rax
movl $0x0, %edx
cmovael %edx, %ebx
movl $0x1, %edx
cmovael %edx, %r14d
testb $0x1, %bl
je 0x194ef
movq 0x18(%r13), %rdx
imulq $0x268, %rcx, %rcx      # imm = 0x268
movl %eax, 0x28(%rsp)
movl 0x20(%rdx,%rcx), %r15d
movq 0x10(%rsp), %rax
movq %rax, 0x70(%rsp)
movb $0x1, 0xf4(%rsp)
cmpl $0x1, %r15d
jbe 0x19571
cmpb $0x0, 0x5509b(%rip)     # 0x6e2f4
jne 0x192b6
movb $0x1, 0x2c(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e8ec
movq $0x0, 0x114(%rsp)
movl %r15d, 0x80(%rsp)
movl %r15d, 0x84(%rsp)
movl %r15d, 0x88(%rsp)
movl %r15d, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
callq 0x3eb8e
testb %al, %al
jne 0x191ba
cmpb $0x0, 0x55038(%rip)     # 0x6e2f5
jne 0x1931a
movb $0x0, 0x2c(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e8ec
movq $0x0, 0x114(%rsp)
movl %r15d, 0x80(%rsp)
movl %r15d, 0x84(%rsp)
movl %r15d, 0x88(%rsp)
movl %r15d, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
callq 0x3eb8e
testb %al, %al
jne 0x191ba
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x40(%rax)
movl $0x1, 0x10(%r12)
testb %al, %al
jne 0x191ba
movl %r15d, %eax
shrl %eax
movl %r15d, %ebp
movl %eax, 0xc(%rsp)
subl %eax, %ebp
movb $0x0, 0xf4(%rsp)
cmpb $0x0, 0x54fa1(%rip)     # 0x6e2f5
jne 0x193ab
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e8ec
movq $0x0, 0x114(%rsp)
movl %ebp, 0x80(%rsp)
movl %r15d, 0x84(%rsp)
movl %r15d, 0x88(%rsp)
movl %r15d, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
callq 0x3eb8e
testb %al, %al
jne 0x191ba
cmpb $0x0, 0x54f42(%rip)     # 0x6e2f4
jne 0x1940e
movb $0x1, 0x2c(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e8ec
movq $0x0, 0x114(%rsp)
movl %ebp, 0x80(%rsp)
movl %r15d, 0x84(%rsp)
movl %r15d, 0x88(%rsp)
movl %r15d, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
callq 0x3eb8e
testb %al, %al
jne 0x191ba
movq 0x48(%rsp), %rax
movq %rax, 0x70(%rsp)
movb $0x0, 0xf4(%rsp)
cmpb $0x0, 0x54ece(%rip)     # 0x6e2f5
jne 0x19487
movb $0x0, 0x2c(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e8ec
movq $0x0, 0x114(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x80(%rsp)
movl %r15d, 0x84(%rsp)
movl %r15d, 0x88(%rsp)
movl %r15d, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
callq 0x3eb8e
testb %al, %al
jne 0x191ba
cmpb $0x0, 0x54e66(%rip)     # 0x6e2f4
jne 0x191ba
movb $0x1, 0x2c(%rsp)
imulq $0x268, 0x50(%r13), %rsi # imm = 0x268
addq 0x18(%r13), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e8ec
movq $0x0, 0x114(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x80(%rsp)
movl %r15d, 0x84(%rsp)
movl %r15d, 0x88(%rsp)
movl %r15d, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
callq 0x3eb8e
jmp 0x191ba
testb $0x1, %r14b
je 0x191ba
testb $0x1, %bl
movq 0x40(%rsp), %rbx
movq 0x38(%rsp), %r14
je 0x1951f
movq (%r12), %rax
movq %r12, %rdi
movq %r13, %rsi
movl $0x1, %edx
movl $0x1, %ecx
callq *0x10(%rax)
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rax
lock
incl (%rax)
movq (%rbx), %rax
movq %rbx, %rdi
movq %r13, %rsi
callq *0x10(%rax)
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x28(%rax)
movq (%r14), %rax
movq %r14, %rdi
movq %r12, %rsi
callq *0x20(%rax)
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
leaq 0x50(%rsp), %rdi
callq 0x3efd4
addq $0x238, %rsp            # imm = 0x238
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x51a78(%rip), %rdi     # 0x6aff0
leaq 0x3db7d(%rip), %rsi     # 0x570fc
movl $0x42, %edx
callq 0x9560
movq 0x51a60(%rip), %rdi     # 0x6aff0
callq 0x91f0
movl $0x4, %edi
callq 0x9200
movl $0x1, (%rax)
movq 0x5198c(%rip), %rsi     # 0x6af38
movq %rax, %rdi
xorl %edx, %edx
callq 0x98f0
jmp 0x195be
jmp 0x195be
jmp 0x195be
jmp 0x195be
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x3efd4
movq %rbx, %rdi
callq 0x9930