// File: ATOMIC-LICHESS[P]ATOMKRAFT/thread.cpp
// Function: ThreadsManager::init()
void ThreadsManager::init() {

  int threadID[MAX_THREADS];

  // This flag is needed to properly end the threads when program exits
  allThreadsShouldExit = false;

  // Threads will sent to sleep as soon as created, only main thread is kept alive
  activeThreads = 1;
  threads[0].state = Thread::SEARCHING;

  // Allocate pawn and material hash tables for main thread
  init_hash_tables();

  lock_init(&mpLock);

  // Initialize thread and split point locks
  for (int i = 0; i < MAX_THREADS; i++)
  {
      lock_init(&threads[i].sleepLock);
      cond_init(&threads[i].sleepCond);

      for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
          lock_init(&(threads[i].splitPoints[j].lock));
  }

  // Create and startup all the threads but the main that is already running
  for (int i = 1; i < MAX_THREADS; i++)
  {
      threads[i].state = Thread::INITIALIZING;
      threadID[i] = i;

#if defined(_MSC_VER)
      bool ok = (CreateThread(NULL, 0, start_routine, (LPVOID)&threadID[i], 0, NULL) != NULL);
#else
      pthread_t pthreadID;
      bool ok = (pthread_create(&pthreadID, NULL, start_routine, (void*)&threadID[i]) == 0);
      pthread_detach(pthreadID);
#endif
      if (!ok)
      {
          std::cout << "Failed to create thread number " << i << std::endl;
          ::exit(EXIT_FAILURE);
      }

      // Wait until the thread has finished launching and is gone to sleep
      while (threads[i].state == Thread::INITIALIZING) {}
  }
}

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xb0(%rsp)
movq 0xb0(%rsp), %rdi
movq %rdi, 0x8(%rsp)
movb $0x0, 0x38(%rdi)
movl $0x1, 0x34(%rdi)
movl $0x1, 0xc8(%rdi)
callq 0x4fb30
movq 0x8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x67a0
movl $0x0, 0x2c(%rsp)
cmpl $0x20, 0x2c(%rsp)
jge 0x4fa2a
movq 0x8(%rsp), %rdi
addq $0x40, %rdi
movslq 0x2c(%rsp), %rax
imulq $0x560, %rax, %rax      # imm = 0x560
addq %rax, %rdi
addq $0x30, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x67a0
movq 0x8(%rsp), %rdi
addq $0x40, %rdi
movslq 0x2c(%rsp), %rax
imulq $0x560, %rax, %rax      # imm = 0x560
addq %rax, %rdi
addq $0x58, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x6620
movl $0x0, 0x28(%rsp)
cmpl $0x8, 0x28(%rsp)
jge 0x4fa18
movq 0x8(%rsp), %rdi
addq $0x40, %rdi
movslq 0x2c(%rsp), %rax
imulq $0x560, %rax, %rax      # imm = 0x560
addq %rax, %rdi
addq $0xa0, %rdi
movslq 0x28(%rsp), %rax
imulq $0x98, %rax, %rax
addq %rax, %rdi
addq $0x38, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x67a0
movl 0x28(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0x4f9c9
jmp 0x4fa1a
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x4f96c
movl $0x1, 0x24(%rsp)
cmpl $0x20, 0x24(%rsp)
jge 0x4fb20
movq 0x8(%rsp), %rax
addq $0x40, %rax
movslq 0x24(%rsp), %rcx
imulq $0x560, %rcx, %rcx      # imm = 0x560
addq %rcx, %rax
movl $0x0, 0x88(%rax)
movl 0x24(%rsp), %ecx
movslq 0x24(%rsp), %rax
movl %ecx, 0x30(%rsp,%rax,4)
movslq 0x24(%rsp), %rax
leaq 0x30(%rsp), %rcx
shlq $0x2, %rax
addq %rax, %rcx
leaq 0x18(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
leaq -0x5ed(%rip), %rdx      # 0x4f4a0
callq 0x69d0
cmpl $0x0, %eax
sete %al
andb $0x1, %al
movb %al, 0x17(%rsp)
movq 0x18(%rsp), %rdi
callq 0x6360
testb $0x1, 0x17(%rsp)
jne 0x4fae7
movq 0x1c502(%rip), %rdi     # 0x6bfb8
leaq 0xba08(%rip), %rsi      # 0x5b4c5
callq 0x64b0
movq %rax, %rdi
movl 0x24(%rsp), %esi
callq 0x6940
movq %rax, %rdi
movq 0x1c4b8(%rip), %rsi     # 0x6bf90
callq 0x6520
movl $0x1, %edi
callq 0x6630
jmp 0x4fae9
movq 0x8(%rsp), %rax
addq $0x40, %rax
movslq 0x24(%rsp), %rcx
imulq $0x560, %rcx, %rcx      # imm = 0x560
addq %rcx, %rax
movl 0x88(%rax), %eax
cmpl $0x0, %eax
jne 0x4fb0e
jmp 0x4fae9
jmp 0x4fb10
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x4fa32
addq $0xb8, %rsp
retq
nopl (%rax,%rax)