decompiled_code:
// attributes: thunk
int __fastcall uthread_yield_handler()
{
return uthread_yield();
}

canonical_decompiled_code:
int __fastcall func6()
{
return func5();
}

original_code:
void uthread_yield_handler( int signum )
{
  uthread_yield();
}

canonical_original_code:
void uthread_yield_handler(int signum)
{
  uthread_yield();
}

variable_types: signum int


original_code:
void uthread_mutex_init(uthread_mutex_t *lockVar)
{
  lockVar->locking_thread = ((void *)0);
  lockVar->wait_queue_length = 0;
  lockVar->wait_queue_head = ((void *)0);
  lockVar->wait_queue_tail = ((void *)0);
}

canonical_original_code:
void uthread_mutex_init(struct uthread_mutex *lockVar)
{
  lockVar->locking_thread = ((void *)0);
  lockVar->wait_queue_length = 0;
  lockVar->wait_queue_head = ((void *)0);
  lockVar->wait_queue_tail = ((void *)0);
}

variable_types: struct uthread_mutex { struct uthread { struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; } uc_stack; struct mcontext_t { long long gregs[23]; struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; } _st[8]; struct _libc_xmmreg { unsigned int element[4]; } _xmm[16]; unsigned int __glibc_reserved1[24]; } *fpregs; unsigned long long __reserved1[8]; } uc_mcontext; struct __sigset_t { unsigned long __val[-1]; } uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; } context; void *stack; int pri; struct uthread *next; } *locking_thread; int wait_queue_length; struct uthread_wait_record { struct uthread *thread; struct uthread_wait_record *next; } *wait_queue_head; struct uthread_wait_record *wait_queue_tail; } *

return_type: void

user_defined_types: struct uthread_mutex { struct uthread *locking_thread; int wait_queue_length; struct uthread_wait_record *wait_queue_head; struct uthread_wait_record *wait_queue_tail; }

user_defined_types: struct uthread { struct ucontext_t context; void *stack; int pri; struct uthread *next; }

user_defined_types: struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t uc_stack; struct mcontext_t uc_mcontext; struct __sigset_t uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; }

user_defined_types: struct mcontext_t { long long gregs[23]; struct _libc_fpstate *fpregs; unsigned long long __reserved1[8]; }

user_defined_types: struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg _st[8]; struct _libc_xmmreg _xmm[16]; unsigned int __glibc_reserved1[24]; }


decompiled_code:
int __fastcall uthread_mutex_unlock(__int64 a1)
{
_QWORD *v2; // rcx
__int64 v3; // r8
_QWORD *v4; // rax
_QWORD *v5; // rdi
__int64 v6; // rdx
int result; // eax
sigset_t v8; // [rsp+0h] [rbp-108h] BYREF
sigset_t oset; // [rsp+80h] [rbp-88h] BYREF

sigfillset(&v8);
if ( sigprocmask(0, &v8, &oset) < 0 )
{
perror("block signals");
exit(-1);
}
v2 = *(_QWORD **)(a1 + 16);
if ( *(_DWORD *)(a1 + 8) == 1 )
{
*(_QWORD *)(a1 + 16) = 0LL;
v5 = v2;
*(_QWORD *)(a1 + 24) = 0LL;
}
else
{
v3 = *v2;
v4 = (_QWORD *)v2[1];
if ( *v2 == *(_QWORD *)a1 )
{
v3 = *v4;
v5 = *(_QWORD **)(a1 + 16);
*(_QWORD *)(a1 + 16) = v4;
}
else
{
while ( 1 )
{
v6 = *v4;
v5 = v4;
v4 = (_QWORD *)v4[1];
if ( *(_QWORD *)a1 == v6 )
break;
v2 = v5;
if ( !v4 )
{
perror("wait record not found");
exit(-1);
}
}
v2[1] = v4;
}
*(_QWORD *)a1 = v3;
}
free(v5);
--*(_DWORD *)(a1 + 8);
result = sigprocmask(2, &oset, 0LL);
if ( result < 0 )
{
perror("unblocking signals");
exit(-1);
}
return result;
}

canonical_decompiled_code:
int __fastcall func9(__int64 a1)
{
_QWORD *v2; // rcx
__int64 v3; // r8
_QWORD *v4; // rax
_QWORD *v5; // rdi
__int64 v6; // rdx
int result; // eax
sigset_t v8; // [rsp+0h] [rbp-108h] BYREF
sigset_t oset; // [rsp+80h] [rbp-88h] BYREF

sigfillset(&v8);
if ( sigprocmask(0, &v8, &oset) < 0 )
{
perror("block signals");
exit(-1);
}
v2 = *(_QWORD **)(a1 + 16);
if ( *(_DWORD *)(a1 + 8) == 1 )
{
*(_QWORD *)(a1 + 16) = 0LL;
v5 = v2;
*(_QWORD *)(a1 + 24) = 0LL;
}
else
{
v3 = *v2;
v4 = (_QWORD *)v2[1];
if ( *v2 == *(_QWORD *)a1 )
{
v3 = *v4;
v5 = *(_QWORD **)(a1 + 16);
*(_QWORD *)(a1 + 16) = v4;
}
else
{
while ( 1 )
{
v6 = *v4;
v5 = v4;
v4 = (_QWORD *)v4[1];
if ( *(_QWORD *)a1 == v6 )
break;
v2 = v5;
if ( !v4 )
{
perror("wait record not found");
exit(-1);
}
}
v2[1] = v4;
}
*(_QWORD *)a1 = v3;
}
free(v5);
--*(_DWORD *)(a1 + 8);
result = sigprocmask(2, &oset, 0LL);
if ( result < 0 )
{
perror("unblocking signals");
exit(-1);
}
return result;
}

original_code:
void uthread_mutex_unlock(uthread_mutex_t *lockVar)
{
  sigset_t mask, orig_mask;
  sigfillset(&mask);
  if( sigprocmask(0, &mask, &orig_mask) < 0 )
    {
      perror("block signals");
      exit(-1);
    }
  uthread_wait_record_t *old_record;
  if( lockVar->wait_queue_length == 1 )
    {
      old_record = lockVar->wait_queue_head;
      lockVar->wait_queue_head = ((void *)0);
      lockVar->wait_queue_tail = ((void *)0);
    }
  else
    {
      if( lockVar->wait_queue_head->thread == lockVar->locking_thread )
        {
          old_record = lockVar->wait_queue_head;
          lockVar->wait_queue_head = old_record->next;
        }
      else
        {
          uthread_wait_record_t *search_prev_p = lockVar->wait_queue_head;
          uthread_wait_record_t *search_p = lockVar->wait_queue_head->next;
          while( search_p->thread != lockVar->locking_thread )
            {
              search_prev_p = search_p;
              search_p = search_p->next;
              if( search_p == ((void *)0))
                {
                  perror("wait record not found");
                  exit(-1);
                }
            }
          search_prev_p->next = search_p->next;
          old_record = search_p;
        }
      lockVar->locking_thread = lockVar->wait_queue_head->thread;
    }
  free(old_record);
  lockVar->wait_queue_length--;
  if( sigprocmask(2, &orig_mask, ((void *)0)) < 0 )
    {
      perror("unblocking signals");
      exit(-1);
    }
}

canonical_original_code:
void uthread_mutex_unlock(struct uthread_mutex *lockVar)
{
  struct __sigset_t mask; struct __sigset_t orig_mask;
  sigfillset(&mask);
  if( sigprocmask(0, &mask, &orig_mask) < 0 )
    {
      perror("block signals");
      exit(-1);
    }
  struct uthread_wait_record *old_record;
  if( lockVar->wait_queue_length == 1 )
    {
      old_record = lockVar->wait_queue_head;
      lockVar->wait_queue_head = ((void *)0);
      lockVar->wait_queue_tail = ((void *)0);
    }
  else
    {
      if( lockVar->wait_queue_head->thread == lockVar->locking_thread )
        {
          old_record = lockVar->wait_queue_head;
          lockVar->wait_queue_head = old_record->next;
        }
      else
        {
          struct uthread_wait_record *search_prev_p = lockVar->wait_queue_head;
          struct uthread_wait_record *search_p = lockVar->wait_queue_head->next;
          while( search_p->thread != lockVar->locking_thread )
            {
              search_prev_p = search_p;
              search_p = search_p->next;
              if( search_p == ((void *)0))
                {
                  perror("wait record not found");
                  exit(-1);
                }
            }
          search_prev_p->next = search_p->next;
          old_record = search_p;
        }
      lockVar->locking_thread = lockVar->wait_queue_head->thread;
    }
  free(old_record);
  lockVar->wait_queue_length--;
  if( sigprocmask(2, &orig_mask, ((void *)0)) < 0 )
    {
      perror("unblocking signals");
      exit(-1);
    }
}

variable_types: struct uthread_wait_record { struct uthread { struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; } uc_stack; struct mcontext_t { long long gregs[23]; struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; } _st[8]; struct _libc_xmmreg { unsigned int element[4]; } _xmm[16]; unsigned int __glibc_reserved1[24]; } *fpregs; unsigned long long __reserved1[8]; } uc_mcontext; struct __sigset_t { unsigned long __val[-1]; } uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; } context; void *stack; int pri; struct uthread *next; } *thread; struct uthread_wait_record *next; } *

user_defined_types: struct uthread_wait_record { struct uthread *thread; struct uthread_wait_record *next; }


decompiled_code:
void __fastcall uthread_mutex_destroy(__int64 a1)
{
_QWORD *i; // rdi

for ( i = *(_QWORD **)(a1 + 16); i; i = *(_QWORD **)(a1 + 16) )
{
*(_QWORD *)(a1 + 16) = i[1];
free(i);
}
}

original_code:
void uthread_mutex_destroy(uthread_mutex_t *lockVar)
{
  uthread_wait_record_t *free_p = lockVar->wait_queue_head;
  while( lockVar->wait_queue_head != ((void *)0) )
    {
      lockVar->wait_queue_head = lockVar->wait_queue_head->next;
      free(free_p);
      free_p = lockVar->wait_queue_head;
    }
}

canonical_original_code:
void uthread_mutex_destroy(struct uthread_mutex *lockVar)
{
  struct uthread_wait_record *free_p = lockVar->wait_queue_head;
  while( lockVar->wait_queue_head != ((void *)0) )
    {
      lockVar->wait_queue_head = lockVar->wait_queue_head->next;
      free(free_p);
      free_p = lockVar->wait_queue_head;
    }
}

user_defined_types: struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; }

user_defined_types: struct __sigset_t { unsigned long __val[-1]; }

user_defined_types: struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; }

user_defined_types: struct _libc_xmmreg { unsigned int element[4]; }


decompiled_code:
void uthread_init()
{
ucontext_t *v0; // [rsp+0h] [rbp-10h]

if ( !current_thread )
{
v0 = (ucontext_t *)malloc(0x3E0uLL);
if ( getcontext(v0) < 0
|| (++live_uthreads,
v0[1].uc_stack.ss_size = 0LL,
v0[1].uc_mcontext.gregs[1] = (greg_t)v0,
LODWORD(v0[1].uc_mcontext.gregs[0]) = 9,
current_thread = v0,
tail_thread = (__int64)v0,
getcontext(&cleanup_context) < 0) )
{
perror("getcontext");
}
else
{
cleanup_context.uc_stack.ss_sp = &cleanup_stack;
cleanup_context.uc_stack.ss_size = (size_t)&unk_100000;
cleanup_context.uc_link = 0LL;
makecontext(&cleanup_context, free_stack, 0);
yield_timer.it_interval.tv_sec = 0LL;
yield_timer.it_interval.tv_usec = 10LL;
yield_timer.it_value.tv_sec = 0LL;
yield_timer.it_value.tv_usec = 10LL;
if ( setitimer(ITIMER_VIRTUAL, &yield_timer, 0LL) < 0 )
{
perror("timer");
}
else
{
yield_action.sa_handler = (__sighandler_t)uthread_yield_handler;
sigemptyset(&set);
dword_100CA8 = 0;
if ( sigaction(26, &yield_action, 0LL) >= 0 )
return;
perror("sigaction");
}
}
exit(-1);
}
}

canonical_decompiled_code:
void func3()
{
ucontext_t *v0; // [rsp+0h] [rbp-10h]

if ( !current_thread )
{
v0 = (ucontext_t *)malloc(0x3E0uLL);
if ( getcontext(v0) < 0
|| (++live_uthreads,
v0[1].uc_stack.ss_size = 0LL,
v0[1].uc_mcontext.gregs[1] = (greg_t)v0,
LODWORD(v0[1].uc_mcontext.gregs[0]) = 9,
current_thread = v0,
tail_thread = (__int64)v0,
getcontext(&cleanup_context) < 0) )
{
perror("getcontext");
}
else
{
cleanup_context.uc_stack.ss_sp = &cleanup_stack;
cleanup_context.uc_stack.ss_size = (size_t)&unk_100000;
cleanup_context.uc_link = 0LL;
makecontext(&cleanup_context, free_stack, 0);
yield_timer.it_interval.tv_sec = 0LL;
yield_timer.it_interval.tv_usec = 10LL;
yield_timer.it_value.tv_sec = 0LL;
yield_timer.it_value.tv_usec = 10LL;
if ( setitimer(ITIMER_VIRTUAL, &yield_timer, 0LL) < 0 )
{
perror("timer");
}
else
{
yield_action.sa_handler = (__sighandler_t)uthread_yield_handler;
sigemptyset(&set);
dword_100CA8 = 0;
if ( sigaction(26, &yield_action, 0LL) >= 0 )
return;
perror("sigaction");
}
}
exit(-1);
}
}

original_code:
void
uthread_init (void)
{
  if (current_thread)
    {
      return;
    }
  uthread_t *main_thread = (uthread_t *) malloc (sizeof (uthread_t));
  if (getcontext (&main_thread->context) < 0)
    {
      perror ("getcontext");
      exit (-1);
    }
  main_thread->stack = ((void *)0);
  main_thread->next = main_thread;
  tail_thread = current_thread = main_thread;
  main_thread->pri = 9;
  live_uthreads++;
  if (getcontext (&cleanup_context) < 0)
    {
      perror ("getcontext");
      exit (-1);
    }
  cleanup_context.uc_stack.ss_sp = cleanup_stack;
  cleanup_context.uc_stack.ss_size = (1 << 20);
  cleanup_context.uc_link = ((void *)0);
  makecontext (&cleanup_context, free_stack, 0);
  yield_timer.it_interval.tv_sec = 0;
  yield_timer.it_interval.tv_usec = TIME_SLICE_USEC;
  yield_timer.it_value.tv_sec = 0;
  yield_timer.it_value.tv_usec = TIME_SLICE_USEC;
  if( setitimer(ITIMER_VIRTUAL, &yield_timer, ((void *)0)) < 0 )
    {
      perror("timer");
      exit(-1);
    }
  yield_action.__sigaction_handler.sa_handler = &uthread_yield_handler;
  sigemptyset( &yield_action.sa_mask );
  yield_action.sa_flags = 0;
  if( sigaction(26, &yield_action, ((void *)0)) < 0 )
    {
      perror("sigaction");
      exit(-1);
    }
}

canonical_original_code:
void uthread_init()
{
  if (current_thread)
    {
      return;
    }
  struct uthread *main_thread = (uthread_t *) malloc (sizeof (uthread_t));
  if (getcontext (&main_thread->context) < 0)
    {
      perror ("getcontext");
      exit (-1);
    }
  main_thread->stack = ((void *)0);
  main_thread->next = main_thread;
  tail_thread = current_thread = main_thread;
  main_thread->pri = 9;
  live_uthreads++;
  if (getcontext (&cleanup_context) < 0)
    {
      perror ("getcontext");
      exit (-1);
    }
  cleanup_context.uc_stack.ss_sp = cleanup_stack;
  cleanup_context.uc_stack.ss_size = (1 << 20);
  cleanup_context.uc_link = ((void *)0);
  makecontext (&cleanup_context, free_stack, 0);
  yield_timer.it_interval.tv_sec = 0;
  yield_timer.it_interval.tv_usec = TIME_SLICE_USEC;
  yield_timer.it_value.tv_sec = 0;
  yield_timer.it_value.tv_usec = TIME_SLICE_USEC;
  if( setitimer(ITIMER_VIRTUAL, &yield_timer, ((void *)0)) < 0 )
    {
      perror("timer");
      exit(-1);
    }
  yield_action.__sigaction_handler.sa_handler = &uthread_yield_handler;
  sigemptyset( &yield_action.sa_mask );
  yield_action.sa_flags = 0;
  if( sigaction(26, &yield_action, ((void *)0)) < 0 )
    {
      perror("sigaction");
      exit(-1);
    }
}

variable_types: struct uthread { struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; } uc_stack; struct mcontext_t { long long gregs[23]; struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; } _st[8]; struct _libc_xmmreg { unsigned int element[4]; } _xmm[16]; unsigned int __glibc_reserved1[24]; } *fpregs; unsigned long long __reserved1[8]; } uc_mcontext; struct __sigset_t { unsigned long __val[-1]; } uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; } context; void *stack; int pri; struct uthread *next; } *


decompiled_code:
__int64 __fastcall uthread_create(void (*a1)(void), unsigned int a2, int a3)
{
void *v3; // rax
size_t v4; // r12
ucontext_t **v5; // rax
ucontext_t *v6; // rsi
ucontext_t **v7; // rbp
ucontext_t *v8; // rax
__int64 v9; // rdx
__int64 v10; // rcx
__int64 v11; // rcx
ucontext_t **v12; // rax
__int64 v13; // rcx
ucontext_t *v14; // rdi
int v15; // er8
ucontext_t **v16; // rax
ucontext_t *i; // rcx
ucontext_t *v18; // rdx
__int64 *v19; // rax
__int64 v20; // rdx
ucontext_t *ucp; // [rsp+8h] [rbp-30h]

ucp = (ucontext_t *)malloc(0x3E0uLL);
if ( getcontext(ucp) < 0 )
{
perror("getcontext");
exit(-1);
}
ucp->uc_stack.ss_size = (size_t)&unk_100000;
v3 = malloc((size_t)&unk_100000);
ucp->uc_link = 0LL;
ucp[1].uc_stack.ss_size = (size_t)v3;
ucp->uc_stack.ss_sp = v3;
LODWORD(ucp[1].uc_mcontext.gregs[0]) = a3;
makecontext(ucp, a1, 1, a2);
v4 = ++live_uthreads;
v5 = (ucontext_t **)malloc(8LL * live_uthreads);
v6 = current_thread;
v7 = v5;
v8 = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
if ( current_thread == v8 )
{
v12 = v7;
v13 = 8LL;
}
else
{
v9 = 1LL;
do
{
v7[v9 - 1] = v8;
v8 = (ucontext_t *)v8[1].uc_mcontext.gregs[1];
v10 = (int)v9++;
}
while ( v6 != v8 );
v11 = v10;
v12 = &v7[v11];
v13 = v11 * 8 + 8;
}
*v12 = v6;
*(ucontext_t **)((char *)v7 + v13) = ucp;
qsort(v7, v4, 8uLL, (__compar_fn_t)uthread_priority_sort);
v14 = *v7;
v15 = live_uthreads;
head_thread = *v7;
if ( live_uthreads <= 1 )
{
v20 = (__int64)v14;
v19 = (__int64 *)v7;
}
else
{
v16 = v7 + 1;
for ( i = v14; ; i = v18 )
{
v18 = *v16;
i[1].uc_mcontext.gregs[1] = (greg_t)*v16;
if ( &v7[v15 - 1] == v16 )
break;
++v16;
}
v19 = (__int64 *)&v7[v15 - 1];
v20 = *v19;
}
*(_QWORD *)(v20 + 984) = v14;
tail_thread = *v19;
if ( v14 != *(ucontext_t **)(tail_thread + 984) )
_assert_fail("tail_thread->next == head_thread", "uthread.c", 0xD5u, "uthread_create");
free(v7);
return (unsigned int)++uthread_id;
}

canonical_decompiled_code:
__int64 __fastcall func4(void (*a1)(void), unsigned int a2, int a3)
{
void *v3; // rax
size_t v4; // r12
ucontext_t **v5; // rax
ucontext_t *v6; // rsi
ucontext_t **v7; // rbp
ucontext_t *v8; // rax
__int64 v9; // rdx
__int64 v10; // rcx
__int64 v11; // rcx
ucontext_t **v12; // rax
__int64 v13; // rcx
ucontext_t *v14; // rdi
int v15; // er8
ucontext_t **v16; // rax
ucontext_t *i; // rcx
ucontext_t *v18; // rdx
__int64 *v19; // rax
__int64 v20; // rdx
ucontext_t *ucp; // [rsp+8h] [rbp-30h]

ucp = (ucontext_t *)malloc(0x3E0uLL);
if ( getcontext(ucp) < 0 )
{
perror("getcontext");
exit(-1);
}
ucp->uc_stack.ss_size = (size_t)&unk_100000;
v3 = malloc((size_t)&unk_100000);
ucp->uc_link = 0LL;
ucp[1].uc_stack.ss_size = (size_t)v3;
ucp->uc_stack.ss_sp = v3;
LODWORD(ucp[1].uc_mcontext.gregs[0]) = a3;
makecontext(ucp, a1, 1, a2);
v4 = ++live_uthreads;
v5 = (ucontext_t **)malloc(8LL * live_uthreads);
v6 = current_thread;
v7 = v5;
v8 = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
if ( current_thread == v8 )
{
v12 = v7;
v13 = 8LL;
}
else
{
v9 = 1LL;
do
{
v7[v9 - 1] = v8;
v8 = (ucontext_t *)v8[1].uc_mcontext.gregs[1];
v10 = (int)v9++;
}
while ( v6 != v8 );
v11 = v10;
v12 = &v7[v11];
v13 = v11 * 8 + 8;
}
*v12 = v6;
*(ucontext_t **)((char *)v7 + v13) = ucp;
qsort(v7, v4, 8uLL, (__compar_fn_t)uthread_priority_sort);
v14 = *v7;
v15 = live_uthreads;
head_thread = *v7;
if ( live_uthreads <= 1 )
{
v20 = (__int64)v14;
v19 = (__int64 *)v7;
}
else
{
v16 = v7 + 1;
for ( i = v14; ; i = v18 )
{
v18 = *v16;
i[1].uc_mcontext.gregs[1] = (greg_t)*v16;
if ( &v7[v15 - 1] == v16 )
break;
++v16;
}
v19 = (__int64 *)&v7[v15 - 1];
v20 = *v19;
}
*(_QWORD *)(v20 + 984) = v14;
tail_thread = *v19;
if ( v14 != *(ucontext_t **)(tail_thread + 984) )
_assert_fail("tail_thread->next == head_thread", "uthread.c", 0xD5u, "uthread_create");
free(v7);
return (unsigned int)++uthread_id;
}

original_code:
int
uthread_create (uthread_func_t func, int val, int pri)
{
  uthread_t *new_thread = (uthread_t *) malloc (sizeof (uthread_t));
  if (getcontext (&new_thread->context) < 0)
    {
      perror ("getcontext");
      exit (-1);
    }
  new_thread->context.uc_stack.ss_size = (1 << 20);
  new_thread->context.uc_stack.ss_sp = new_thread->stack =
    malloc ((1 << 20));
  new_thread->context.uc_link = ((void *)0);
  new_thread->pri = pri;
  makecontext (&new_thread->context, (void (*)(void)) func, 1, val);
  live_uthreads++;
  uthread_t **thread_buf = malloc( live_uthreads * sizeof(uthread_t*) );
  uthread_t *thread_copy_p = current_thread->next;
  int thread_buf_pos = 0;
  while( thread_copy_p != current_thread )
    {
      thread_buf[thread_buf_pos] = thread_copy_p;
      thread_copy_p = thread_copy_p->next;
      thread_buf_pos++;
    }
  thread_buf[thread_buf_pos] = current_thread;
  thread_buf[thread_buf_pos + 1] = new_thread;
  qsort(thread_buf, live_uthreads, sizeof(uthread_t*), uthread_priority_sort);
  head_thread = thread_buf[0];
  for( thread_buf_pos = 1; thread_buf_pos < live_uthreads; thread_buf_pos++ )
    {
      thread_buf[thread_buf_pos - 1]->next = thread_buf[thread_buf_pos];
    }
  thread_buf[thread_buf_pos - 1]->next = head_thread;
  tail_thread = thread_buf[thread_buf_pos - 1];
  ((void) sizeof ((tail_thread->next == head_thread) ? 1 : 0), __extension__ ({ if (tail_thread->next == head_thread) ; else __assert_fail ("tail_thread->next == head_thread", "uthread.c", 213, __extension__ __PRETTY_FUNCTION__); }));
  free(thread_buf);
  return ++uthread_id;
}

canonical_original_code:
int uthread_create(void (*func)(int val), int val, int pri)
{
  struct uthread *new_thread = (uthread_t *) malloc (sizeof (uthread_t));
  if (getcontext (&new_thread->context) < 0)
    {
      perror ("getcontext");
      exit (-1);
    }
  new_thread->context.uc_stack.ss_size = (1 << 20);
  new_thread->context.uc_stack.ss_sp = new_thread->stack =
    malloc ((1 << 20));
  new_thread->context.uc_link = ((void *)0);
  new_thread->pri = pri;
  makecontext (&new_thread->context, (void (*)()) func, 1, val);
  live_uthreads++;
  struct uthread **thread_buf = malloc( live_uthreads * sizeof(uthread_t*) );
  struct uthread *thread_copy_p = current_thread->next;
  int thread_buf_pos = 0;
  while( thread_copy_p != current_thread )
    {
      thread_buf[thread_buf_pos] = thread_copy_p;
      thread_copy_p = thread_copy_p->next;
      thread_buf_pos++;
    }
  thread_buf[thread_buf_pos] = current_thread;
  thread_buf[thread_buf_pos + 1] = new_thread;
  qsort(thread_buf, live_uthreads, sizeof(struct uthread *), uthread_priority_sort);
  head_thread = thread_buf[0];
  for( thread_buf_pos = 1; thread_buf_pos < live_uthreads; thread_buf_pos++ )
    {
      thread_buf[thread_buf_pos - 1]->next = thread_buf[thread_buf_pos];
    }
  thread_buf[thread_buf_pos - 1]->next = head_thread;
  tail_thread = thread_buf[thread_buf_pos - 1];
  ((void) sizeof ((tail_thread->next == head_thread) ? 1 : 0), __extension__ ({ if (tail_thread->next == head_thread) ; else __assert_fail ("tail_thread->next == head_thread", "uthread.c", 213, __extension__ __PRETTY_FUNCTION__); }));
  free(thread_buf);
  return ++uthread_id;
}

variable_types:
func
void (*)(int val)

variable_types: val int

variable_types: pri int

variable_types: struct uthread { struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; } uc_stack; struct mcontext_t { long long gregs[23]; struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; } _st[8]; struct _libc_xmmreg { unsigned int element[4]; } _xmm[16]; unsigned int __glibc_reserved1[24]; } *fpregs; unsigned long long __reserved1[8]; } uc_mcontext; struct __sigset_t { unsigned long __val[-1]; } uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; } context; void *stack; int pri; struct uthread *next; } **

return_type: int


decompiled_code:
int uthread_yield()
{
ucontext_t *v0; // rdi
ucontext_t *v1; // rsi
int result; // eax

v0 = current_thread;
v1 = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
if ( current_thread != v1 )
{
result = v1[1].uc_mcontext.gregs[0];
if ( SLODWORD(current_thread[1].uc_mcontext.gregs[0]) >= result || (v1 = head_thread, current_thread != head_thread) )
{
current_thread = v1;
result = swapcontext(v0, v1);
}
}
return result;
}

canonical_decompiled_code:
int func5()
{
ucontext_t *v0; // rdi
ucontext_t *v1; // rsi
int result; // eax

v0 = current_thread;
v1 = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
if ( current_thread != v1 )
{
result = v1[1].uc_mcontext.gregs[0];
if ( SLODWORD(current_thread[1].uc_mcontext.gregs[0]) >= result || (v1 = head_thread, current_thread != head_thread) )
{
current_thread = v1;
result = swapcontext(v0, v1);
}
}
return result;
}

original_code:
void
uthread_yield (void)
{
  if (current_thread == current_thread->next)
      return;
  uthread_t *old_thread = current_thread;
  if( old_thread->pri < old_thread->next->pri )
    {
      if( current_thread == head_thread )
          return;
      else
          current_thread = head_thread;
    }
  else
      current_thread = old_thread->next;
  swapcontext (&old_thread->context, &current_thread->context);
}

canonical_original_code:
void uthread_yield()
{
  if (current_thread == current_thread->next)
      return;
  struct uthread *old_thread = current_thread;
  if( old_thread->pri < old_thread->next->pri )
    {
      if( current_thread == head_thread )
          return;
      else
          current_thread = head_thread;
    }
  else
      current_thread = old_thread->next;
  swapcontext (&old_thread->context, &current_thread->context);
}


decompiled_code:
int uthread_exit()
{
ucontext_t *v0; // rdx
ucontext_t *v1; // rsi
greg_t v2; // rdi
ucontext_t *v3; // rax
__int64 v4; // rcx

v0 = current_thread;
v1 = head_thread;
v2 = current_thread[1].uc_mcontext.gregs[1];
v3 = head_thread;
if ( head_thread == current_thread )
{
current_thread = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
head_thread = (ucontext_t *)v2;
*(_QWORD *)(tail_thread + 984) = v2;
}
else
{
do
{
v4 = (__int64)v3;
v3 = (ucontext_t *)v3[1].uc_mcontext.gregs[1];
}
while ( v3 != current_thread );
if ( SLODWORD(current_thread[1].uc_mcontext.gregs[0]) < *(_DWORD *)(v2 + 976) )
{
*(_QWORD *)(v4 + 984) = v2;
current_thread = v1;
}
else if ( (ucontext_t *)tail_thread == current_thread )
{
tail_thread = v4;
*(_QWORD *)(v4 + 984) = head_thread;
current_thread = v1;
}
else
{
current_thread = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
*(_QWORD *)(v4 + 984) = v2;
}
}
retired_thread = v0;
return setcontext(&cleanup_context);
}

canonical_decompiled_code:
int func7()
{
ucontext_t *v0; // rdx
ucontext_t *v1; // rsi
greg_t v2; // rdi
ucontext_t *v3; // rax
__int64 v4; // rcx

v0 = current_thread;
v1 = head_thread;
v2 = current_thread[1].uc_mcontext.gregs[1];
v3 = head_thread;
if ( head_thread == current_thread )
{
current_thread = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
head_thread = (ucontext_t *)v2;
*(_QWORD *)(tail_thread + 984) = v2;
}
else
{
do
{
v4 = (__int64)v3;
v3 = (ucontext_t *)v3[1].uc_mcontext.gregs[1];
}
while ( v3 != current_thread );
if ( SLODWORD(current_thread[1].uc_mcontext.gregs[0]) < *(_DWORD *)(v2 + 976) )
{
*(_QWORD *)(v4 + 984) = v2;
current_thread = v1;
}
else if ( (ucontext_t *)tail_thread == current_thread )
{
tail_thread = v4;
*(_QWORD *)(v4 + 984) = head_thread;
current_thread = v1;
}
else
{
current_thread = (ucontext_t *)current_thread[1].uc_mcontext.gregs[1];
*(_QWORD *)(v4 + 984) = v2;
}
}
retired_thread = v0;
return setcontext(&cleanup_context);
}

original_code:
void
uthread_exit (void)
{
  uthread_t *old_thread = current_thread;
  if( old_thread == head_thread )
    {
      current_thread = current_thread->next;
      tail_thread->next = current_thread;
      head_thread = current_thread;
    }
  else
    {
      uthread_t *prev_thread = head_thread;
      while( prev_thread->next != old_thread )
        prev_thread = prev_thread->next;
      if( old_thread->pri < old_thread->next->pri )
        {
          prev_thread->next = old_thread->next;
          current_thread = head_thread;
        }
      else
        {
          if( old_thread == tail_thread )
            {
              tail_thread = prev_thread;
              prev_thread->next = head_thread;
              current_thread = head_thread;
            }
          else
            {
              current_thread = current_thread->next;
              prev_thread->next = current_thread;
            }
        }
    }
  retired_thread = old_thread;
  setcontext (&cleanup_context);
}

canonical_original_code:
void uthread_exit()
{
  struct uthread *old_thread = current_thread;
  if( old_thread == head_thread )
    {
      current_thread = current_thread->next;
      tail_thread->next = current_thread;
      head_thread = current_thread;
    }
  else
    {
      struct uthread *prev_thread = head_thread;
      while( prev_thread->next != old_thread )
        prev_thread = prev_thread->next;
      if( old_thread->pri < old_thread->next->pri )
        {
          prev_thread->next = old_thread->next;
          current_thread = head_thread;
        }
      else
        {
          if( old_thread == tail_thread )
            {
              tail_thread = prev_thread;
              prev_thread->next = head_thread;
              current_thread = head_thread;
            }
          else
            {
              current_thread = current_thread->next;
              prev_thread->next = current_thread;
            }
        }
    }
  retired_thread = old_thread;
  setcontext (&cleanup_context);
}


decompiled_code:
__int64 __fastcall thread_start(unsigned int a1)
{
printf("In thread_start %d , control transfered\n", a1);
return uthread_yield();
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned int a1)
{
printf("In thread_start %d , control transfered\n", a1);
return func19();
}

original_code:
void thread_start(int val) {
  printf("In thread_start %d , control transfered\n", val);
  uthread_yield();
}


original_code:
void list_init(list_t *l,
        int (*compare)(const void *key, const void *with),
        void (*data_delete)(void *data)){
  l->head = ((void *)0);
  l->tail = ((void *)0);
  l->length = 0;
  l->compare = compare;
  l->data_delete = data_delete;
}

canonical_original_code:
void list_init(struct list *l, int (*compare)(void *key, void *with), void (*data_delete)(void *data)){
  l->head = ((void *)0);
  l->tail = ((void *)0);
  l->length = 0;
  l->compare = compare;
  l->data_delete = data_delete;
}

variable_types: struct list { struct list_item { struct list_item *prev; void *data; } *head; unsigned int length; int (*compare)(void *key, void *with); void (*data_delete)(void *data); } *

variable_types:
compare
int (*)(void *key, void *with)

user_defined_types: struct list { struct list_item *head; unsigned int length; int (*compare)(void *key, void *with); void (*data_delete)(void *data); }


decompiled_code:
__int64 __fastcall list_visit_items(__int64 *a1, __int64 (__fastcall *a2)(__int64))
{
__int64 i; // rbx
__int64 result; // rax

for ( i = *a1; i; i = *(_QWORD *)(i + 8) )
result = a2(i);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func10(__int64 *a1, __int64 (__fastcall *a2)(__int64))
{
__int64 i; // rbx
__int64 result; // rax

for ( i = *a1; i; i = *(_QWORD *)(i + 8) )
result = a2(i);
return result;
}

original_code:
void list_visit_items(list_t *l, void (*visitor)(void *v)){
  list_item_t *current_item = l->head;
  while(current_item != ((void *)0))
    {
      visitor(current_item);
      current_item = current_item->next;
    }
}

canonical_original_code:
void list_visit_items(struct list *l, void (*visitor)(void *v)){
  struct list_item *current_item = l->head;
  while(current_item != ((void *)0))
    {
      visitor(current_item);
      current_item = current_item->next;
    }
}

variable_types:
visitor
void (*)(void *v)

variable_types: struct list_item { struct list_item *prev; void *data; } *


decompiled_code:
__int64 __fastcall list_insert_tail(__int64 a1, __int64 a2)
{
_QWORD *v2; // rax
_QWORD *v3; // rbx
int v4; // eax
__int64 v5; // rdx
__int64 result; // rax

v2 = malloc(0x18uLL);
if ( !v2 )
{
perror("malloc failed to create new object.");
exit(-1);
}
v3 = v2;
list_item_init(v2, a2);
v4 = *(_DWORD *)(a1 + 16);
if ( v4 )
{
v5 = *(_QWORD *)(a1 + 8);
result = (unsigned int)(v4 + 1);
*(_QWORD *)(v5 + 8) = v3;
*v3 = v5;
*(_QWORD *)(a1 + 8) = v3;
*(_DWORD *)(a1 + 16) = result;
}
else
{
result = 1LL;
*(_QWORD *)a1 = v3;
*(_QWORD *)(a1 + 8) = v3;
*(_DWORD *)(a1 + 16) = 1;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func11(__int64 a1, __int64 a2)
{
_QWORD *v2; // rax
_QWORD *v3; // rbx
int v4; // eax
__int64 v5; // rdx
__int64 result; // rax

v2 = malloc(0x18uLL);
if ( !v2 )
{
perror("malloc failed to create new object.");
exit(-1);
}
v3 = v2;
func8(v2, a2);
v4 = *(_DWORD *)(a1 + 16);
if ( v4 )
{
v5 = *(_QWORD *)(a1 + 8);
result = (unsigned int)(v4 + 1);
*(_QWORD *)(v5 + 8) = v3;
*v3 = v5;
*(_QWORD *)(a1 + 8) = v3;
*(_DWORD *)(a1 + 16) = result;
}
else
{
result = 1LL;
*(_QWORD *)a1 = v3;
*(_QWORD *)(a1 + 8) = v3;
*(_DWORD *)(a1 + 16) = 1;
}
return result;
}

original_code:
void list_insert_tail(list_t *l, void *v){
  list_item_t *new = malloc(sizeof(list_item_t));
  if(new == ((void *)0))
    {
      perror("malloc failed to create new object.");
      exit(-1);
    }
  list_item_init(new, v);
  if( l->length == 0 )
    {
      l->head = new;
      l->tail = new;
    }
  else
    {
      l->tail->next = new;
      new->prev = l->tail;
      l->tail = new;
    }
  l->length++;
}

canonical_original_code:
void list_insert_tail(struct list *l, void *v){
  struct list_item *new = malloc(sizeof(list_item_t));
  if(new == ((void *)0))
    {
      perror("malloc failed to create new object.");
      exit(-1);
    }
  list_item_init(new, v);
  if( l->length == 0 )
    {
      l->head = new;
      l->tail = new;
    }
  else
    {
      l->tail->next = new;
      new->prev = l->tail;
      l->tail = new;
    }
  l->length++;
}

variable_types:
v
void *

user_defined_types: struct list_item { struct list_item *prev; void *data; }


original_code:
void thread_init(thread_t *t,
                 int pri, int id){
  t->pri = pri;
  t->id = id;
}

canonical_original_code:
void thread_init(struct thread *t, int pri, int id){
  t->pri = pri;
  t->id = id;
}

variable_types: struct thread { struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; } uc_stack; struct mcontext_t { long long gregs[23]; struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; } _st[8]; struct _libc_xmmreg { unsigned int element[4]; } _xmm[16]; unsigned int __glibc_reserved1[24]; } *fpregs; unsigned long long __reserved1[8]; } uc_mcontext; struct __sigset_t { unsigned long __val[-1]; } uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; } ucp; char ucp_stack[1048576]; int pri; int id; _Bool free_stack; } *

variable_types: id int

user_defined_types: struct thread { struct ucontext_t ucp; char ucp_stack[1048576]; int pri; int id; _Bool free_stack; }


decompiled_code:
void __fastcall thread_data_delete(__int64 a1)
{
free(*(void **)(a1 + 16));
}

canonical_decompiled_code:
void __fastcall func14(__int64 a1)
{
free(*(void **)(a1 + 16));
}

original_code:
void thread_data_delete(void *item){
  thread_t *t = (thread_t*)(((list_item_t*)item)->data);
  free(t);
}

canonical_original_code:
void thread_data_delete(void *item){
  struct thread *t = (thread_t*)(((list_item_t*)item)->data);
  free(t);
}

variable_types:
item
void *


decompiled_code:
__int64 __fastcall thread_compare_pri(__int64 a1, __int64 a2)
{
return (unsigned int)(*(_DWORD *)(*(_QWORD *)(*(_QWORD *)a1 + 16LL) + 1049544LL)
- *(_DWORD *)(*(_QWORD *)(*(_QWORD *)a2 + 16LL) + 1049544LL));
}

original_code:
int thread_compare_pri(const void *key, const void *with){
  list_item_t **arg1 = (list_item_t**)key;
  list_item_t **arg2 = (list_item_t**)with;
  thread_t *t1 = (thread_t*)((*arg1)->data);
  thread_t *t2 = (thread_t*)((*arg2)->data);
  int pri1 = t1->pri;
  int pri2 = t2->pri;
  return pri1 - pri2;
}

canonical_original_code:
int thread_compare_pri(void *key, void *with){
  struct list_item **arg1 = (list_item_t**)key;
  struct list_item **arg2 = (list_item_t**)with;
  struct thread *t1 = (thread_t*)((*arg1)->data);
  struct thread *t2 = (thread_t*)((*arg2)->data);
  int pri1 = t1->pri;
  int pri2 = t2->pri;
  return pri1 - pri2;
}

variable_types:
key
void *

variable_types:
with
void *

variable_types: struct list_item { struct list_item *prev; void *data; } **


decompiled_code:
void uthread_handler(void)
{
while ( 1 )
{
list_remove_head((__int64)&thread_queue);
if ( !dword_504490 )
break;
setcontext(*(const ucontext_t **)(thread_queue + 16));
}
}

canonical_decompiled_code:
void func16(void)
{
while ( 1 )
{
func12((__int64)&thread_queue);
if ( !dword_504490 )
break;
setcontext(*(const ucontext_t **)(thread_queue + 16));
}
}

original_code:
void uthread_handler(){
  while( 1 ){
    list_remove_head(&thread_queue);
    if( thread_queue.length >= 1 )
      {
        list_item_t *new_head = thread_queue.head;
        thread_t *head_thread = (thread_t*)new_head->data;
        setcontext(&(head_thread->ucp));
      }
    else break;
  }
}

canonical_original_code:
void uthread_handler(){
  while( 1 ){
    list_remove_head(&thread_queue);
    if( thread_queue.length >= 1 )
      {
        struct list_item *new_head = thread_queue.head;
        struct thread *head_thread = (thread_t*)new_head->data;
        setcontext(&(head_thread->ucp));
      }
    else break;
  }
}


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
puts("Testing uthread_create");
uthread_init("Testing uthread_create", argv);
uthread_create(thread_start, 1LL, 0LL);
uthread_yield();
puts("back in main");
uthread_exit();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
puts("Testing uthread_create");
func17("Testing uthread_create", argv);
func18(thread_start, 1LL, 0LL);
func19();
puts("back in main");
func20();
return 0;
}

original_code:
int main(int argc, char **argv) {
  printf("Testing uthread_create\n");
  uthread_init();
  uthread_create(thread_start, 1, 0);
  uthread_yield();
  printf("back in main\n");
  uthread_exit();
  return 0;
}

variable_types: argc int

variable_types:
argv
char **


decompiled_code:
int uthread_init()
{
ucontext_t *v0; // rax
ucontext_t *v1; // rbp

list_init((__int64)&thread_queue, (__int64)thread_compare_pri, (__int64)thread_data_delete);
getcontext(&handler);
handler.uc_stack.ss_sp = &handler_stack;
handler.uc_stack.ss_size = 0x100000LL;
handler.uc_link = 0LL;
makecontext(&handler, uthread_handler, 0);
v0 = (ucontext_t *)malloc(0x1003D8uLL);
thread_id = 0;
v1 = v0;
thread_init((__int64)v0, 0, 0);
++thread_id;
list_insert_tail((__int64)&thread_queue, (__int64)v1);
return getcontext(v1);
}

canonical_decompiled_code:
int func17()
{
ucontext_t *v0; // rax
ucontext_t *v1; // rbp

func9((__int64)&thread_queue, (__int64)thread_compare_pri, (__int64)thread_data_delete);
getcontext(&handler);
handler.uc_stack.ss_sp = &handler_stack;
handler.uc_stack.ss_size = 0x100000LL;
handler.uc_link = 0LL;
makecontext(&handler, uthread_handler, 0);
v0 = (ucontext_t *)malloc(0x1003D8uLL);
thread_id = 0;
v1 = v0;
func13((__int64)v0, 0, 0);
++thread_id;
func11((__int64)&thread_queue, (__int64)v1);
return getcontext(v1);
}

original_code:
void uthread_init(){
  list_init(&thread_queue, thread_compare_pri, thread_data_delete);
  getcontext(&handler);
  handler.uc_stack.ss_sp = &handler_stack;
  handler.uc_stack.ss_size = sizeof(handler_stack);
  handler.uc_link = ((void *)0);
  makecontext(&handler, uthread_handler, 0);
  thread_t *new_thread = malloc( sizeof(thread_t) );
  thread_id = 0;
  thread_init(new_thread, 0, thread_id);
  thread_id++;
  list_insert_tail(&thread_queue, new_thread);
  ucontext_t *new_context = &new_thread->ucp;
  getcontext(new_context);
}

canonical_original_code:
void uthread_init(){
  list_init(&thread_queue, thread_compare_pri, thread_data_delete);
  getcontext(&handler);
  handler.uc_stack.ss_sp = &handler_stack;
  handler.uc_stack.ss_size = sizeof(handler_stack);
  handler.uc_link = ((void *)0);
  makecontext(&handler, uthread_handler, 0);
  struct thread *new_thread = malloc( sizeof(thread_t) );
  thread_id = 0;
  thread_init(new_thread, 0, thread_id);
  thread_id++;
  list_insert_tail(&thread_queue, new_thread);
  struct ucontext_t *new_context = &new_thread->ucp;
  getcontext(new_context);
}

variable_types: struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct stack_t { void *ss_sp; int ss_flags; unsigned long ss_size; } uc_stack; struct mcontext_t { long long gregs[23]; struct _libc_fpstate { unsigned short cwd; unsigned short swd; unsigned short ftw; unsigned short fop; unsigned long rip; unsigned long rdp; unsigned int mxcsr; unsigned int mxcr_mask; struct _libc_fpxreg { unsigned short significand[4]; unsigned short exponent; unsigned short __glibc_reserved1[3]; } _st[8]; struct _libc_xmmreg { unsigned int element[4]; } _xmm[16]; unsigned int __glibc_reserved1[24]; } *fpregs; unsigned long long __reserved1[8]; } uc_mcontext; struct __sigset_t { unsigned long __val[-1]; } uc_sigmask; struct _libc_fpstate __fpregs_mem; unsigned long long __ssp[4]; } *


decompiled_code:
__int64 __fastcall uthread_create(void (*a1)(void), unsigned int a2, int a3)
{
ucontext_t *v4; // rbp

v4 = (ucontext_t *)malloc(0x1003D8uLL);
thread_init((__int64)v4, a3, thread_id);
v4->uc_stack.ss_sp = &v4[1].uc_stack.ss_size;
v4->uc_stack.ss_size = 0x100000LL;
v4->uc_link = 0LL;
++thread_id;
getcontext(v4);
makecontext(v4, a1, 1, a2);
list_insert_tail((__int64)&thread_queue, (__int64)v4);
return (unsigned int)(thread_id - 1);
}

canonical_decompiled_code:
__int64 __fastcall func18(void (*a1)(void), unsigned int a2, int a3)
{
ucontext_t *v4; // rbp

v4 = (ucontext_t *)malloc(0x1003D8uLL);
func13((__int64)v4, a3, thread_id);
v4->uc_stack.ss_sp = &v4[1].uc_stack.ss_size;
v4->uc_stack.ss_size = 0x100000LL;
v4->uc_link = 0LL;
++thread_id;
getcontext(v4);
makecontext(v4, a1, 1, a2);
func11((__int64)&thread_queue, (__int64)v4);
return (unsigned int)(thread_id - 1);
}

original_code:
int uthread_create(void (*func)(int), int val, int pri){
  thread_t *new_thread = malloc( sizeof(thread_t) );
  thread_init(new_thread, pri, thread_id);
  thread_id++;
  new_thread->ucp.uc_stack.ss_sp = new_thread->ucp_stack;
  new_thread->ucp.uc_stack.ss_size = sizeof(new_thread->ucp_stack);
  new_thread->ucp.uc_link = ((void *)0);
  ucontext_t *new_context = &(new_thread->ucp);
  getcontext(new_context);
  makecontext(new_context, func, 1, val);
  list_insert_tail(&thread_queue, new_thread);
  return thread_id - 1;
}

canonical_original_code:
int uthread_create(void (*func)(int), int val, int pri){
  struct thread *new_thread = malloc( sizeof(thread_t) );
  thread_init(new_thread, pri, thread_id);
  thread_id++;
  new_thread->ucp.uc_stack.ss_sp = new_thread->ucp_stack;
  new_thread->ucp.uc_stack.ss_size = sizeof(new_thread->ucp_stack);
  new_thread->ucp.uc_link = ((void *)0);
  struct ucontext_t *new_context = &(new_thread->ucp);
  getcontext(new_context);
  makecontext(new_context, func, 1, val);
  list_insert_tail(&thread_queue, new_thread);
  return thread_id - 1;
}

variable_types:
func
void (*)(int)

variable_types: val int


decompiled_code:
int uthread_yield()
{
ucontext_t *v0; // rbp
int result; // eax

if ( (unsigned int)dword_504490 > 1 )
{
v0 = *(ucontext_t **)(thread_queue + 16);
list_rotate_one((__int64)&thread_queue);
result = swapcontext(v0, *(const ucontext_t **)(thread_queue + 16));
}
return result;
}

canonical_decompiled_code:
int func19()
{
ucontext_t *v0; // rbp
int result; // eax

if ( (unsigned int)dword_504490 > 1 )
{
v0 = *(ucontext_t **)(thread_queue + 16);
list_rotate_one((__int64)&thread_queue);
result = swapcontext(v0, *(const ucontext_t **)(thread_queue + 16));
}
return result;
}

original_code:
void uthread_yield(){
  if( thread_queue.length > 1)
    {
      list_item_t *cur_head = thread_queue.head;
      thread_t *cur_thread = (thread_t*)cur_head->data;
      list_rotate_one(&thread_queue);
      list_item_t *new_head = thread_queue.head;
      thread_t *new_thread = (thread_t*)new_head->data;
      ucontext_t *old_context = &cur_thread->ucp;
      ucontext_t *new_context = &new_thread->ucp;
      swapcontext(old_context, new_context);
    }
}

canonical_original_code:
void uthread_yield(){
  if( thread_queue.length > 1)
    {
      struct list_item *cur_head = thread_queue.head;
      struct thread *cur_thread = (thread_t*)cur_head->data;
      list_rotate_one(&thread_queue);
      struct list_item *new_head = thread_queue.head;
      struct thread *new_thread = (thread_t*)new_head->data;
      struct ucontext_t *old_context = &cur_thread->ucp;
      struct ucontext_t *new_context = &new_thread->ucp;
      swapcontext(old_context, new_context);
    }
}


decompiled_code:
int uthread_exit()
{
return setcontext(&handler);
}

canonical_decompiled_code:
int func20()
{
return setcontext(&handler);
}

original_code:
void uthread_exit(){
  setcontext(&handler);
}


whaleInit

decompiled_code:
_QWORD *whaleInit()
{
_QWORD *v0; // rbx
_QWORD *result; // rax

v0 = malloc(0x18uLL);
maleQ = (__int64)v0;
result = malloc(0x18uLL);
v0[1] = 0LL;
v0[2] = v0;
*(_DWORD *)v0 = 0;
result[1] = 0LL;
result[2] = result;
*(_DWORD *)result = 0;
femaleQ = (__int64)result;
return result;
}

canonical_decompiled_code:
_QWORD *func7()
{
_QWORD *v0; // rbx
_QWORD *result; // rax

v0 = malloc(0x18uLL);
maleQ = (__int64)v0;
result = malloc(0x18uLL);
v0[1] = 0LL;
v0[2] = v0;
*(_DWORD *)v0 = 0;
result[1] = 0LL;
result[2] = result;
*(_DWORD *)result = 0;
femaleQ = (__int64)result;
return result;
}

original_code:
void whaleInit(){
 maleQ=(whale_t*) malloc(sizeof(whale_t));
 femaleQ=(whale_t*) malloc(sizeof(whale_t));
 maleQ->next=((void *)0);
 maleQ->tail=maleQ;
 maleQ->id=0;
 femaleQ->next=((void *)0);
 femaleQ->tail=femaleQ;
 femaleQ->id=0;
}

canonical_original_code:
void whaleInit(){
 maleQ=(struct whale *) malloc(sizeof(whale_t));
 femaleQ=(struct whale *) malloc(sizeof(whale_t));
 maleQ->next=((void *)0);
 maleQ->tail=maleQ;
 maleQ->id=0;
 femaleQ->next=((void *)0);
 femaleQ->tail=femaleQ;
 femaleQ->id=0;
}

user_defined_types: struct whale { int id; struct whale *next; struct whale *tail; }


decompiled_code:
int __fastcall create_male(unsigned int a1)
{
double v1; // xmm0_8
int v2; // ebx
_QWORD *v3; // rax
__int64 v4; // rdx
__int64 v5; // rax
double v6; // xmm0_8
double v7; // xmm0_8
__int64 v8; // rsi
__int64 v9; // rcx
__int64 v10; // rdx
double v11; // xmm0_8
unsigned int v12; // er12
double v13; // xmm0_8
_QWORD *v14; // rax
__int64 v15; // rdx

pthread_mutex_lock(&stdout_lock);
v1 = elapsed_time();
printf("(t=%f) %d: %s\n", v1, a1, "Male Created");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v2 = male;
if ( male <= 0 )
{
if ( female > 0 )
{
pthread_mutex_lock(&stdout_lock);
v11 = elapsed_time();
printf("(t=%f) %d: %s\n", v11, a1, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v12 = *(_DWORD *)femaleQ;
v13 = elapsed_time();
printf("(t=%f) %d: %s\n", v13, v12, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
++male;
v14 = malloc(0x18uLL);
v15 = maleQ;
*(_DWORD *)v14 = a1;
*(_QWORD *)(*(_QWORD *)(v15 + 16) + 8LL) = v14;
*(_QWORD *)(v15 + 16) = v14;
v14[1] = 0LL;
sem_post(&male_avail);
LODWORD(v5) = sem_wait(&maker_avail);
return v5;
}
goto LABEL_3;
}
if ( female <= 0 )
{
LABEL_3:
v3 = malloc(0x18uLL);
v4 = maleQ;
male = v2 + 1;
*(_DWORD *)v3 = a1;
*(_QWORD *)(*(_QWORD *)(v4 + 16) + 8LL) = v3;
*(_QWORD *)(v4 + 16) = v3;
v3[1] = 0LL;
sem_post(&male_avail);
sem_wait(&fem_avail);
LODWORD(v5) = sem_wait(&maker_avail);
return v5;
}
sem_post(&maker_avail);
pthread_mutex_lock(&stdout_lock);
v6 = elapsed_time();
printf("(t=%f) %d: %s\n", v6, a1, "Became MatchMaker");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v7 = elapsed_time();
printf("(t=%f) %d: %s\n", v7, a1, "Mated");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v5 = *(_QWORD *)(maleQ + 8);
if ( v5 && (v8 = femaleQ, (v9 = *(_QWORD *)(femaleQ + 8)) != 0) )
{
v10 = *(_QWORD *)(maleQ + 16);
maleQ = *(_QWORD *)(maleQ + 8);
femaleQ = v9;
*(_QWORD *)(v5 + 16) = v10;
v5 = *(_QWORD *)(v8 + 16);
*(_QWORD *)(v9 + 16) = v5;
}
else
{
maleQ = 0LL;
femaleQ = 0LL;
}
--male;
--female;
return v5;
}

canonical_decompiled_code:
int __fastcall func9(unsigned int a1)
{
double v1; // xmm0_8
int v2; // ebx
_QWORD *v3; // rax
__int64 v4; // rdx
__int64 v5; // rax
double v6; // xmm0_8
double v7; // xmm0_8
__int64 v8; // rsi
__int64 v9; // rcx
__int64 v10; // rdx
double v11; // xmm0_8
unsigned int v12; // er12
double v13; // xmm0_8
_QWORD *v14; // rax
__int64 v15; // rdx

pthread_mutex_lock(&stdout_lock);
v1 = func8();
printf("(t=%f) %d: %s\n", v1, a1, "Male Created");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v2 = male;
if ( male <= 0 )
{
if ( female > 0 )
{
pthread_mutex_lock(&stdout_lock);
v11 = func8();
printf("(t=%f) %d: %s\n", v11, a1, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v12 = *(_DWORD *)femaleQ;
v13 = func8();
printf("(t=%f) %d: %s\n", v13, v12, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
++male;
v14 = malloc(0x18uLL);
v15 = maleQ;
*(_DWORD *)v14 = a1;
*(_QWORD *)(*(_QWORD *)(v15 + 16) + 8LL) = v14;
*(_QWORD *)(v15 + 16) = v14;
v14[1] = 0LL;
sem_post(&male_avail);
LODWORD(v5) = sem_wait(&maker_avail);
return v5;
}
goto LABEL_3;
}
if ( female <= 0 )
{
LABEL_3:
v3 = malloc(0x18uLL);
v4 = maleQ;
male = v2 + 1;
*(_DWORD *)v3 = a1;
*(_QWORD *)(*(_QWORD *)(v4 + 16) + 8LL) = v3;
*(_QWORD *)(v4 + 16) = v3;
v3[1] = 0LL;
sem_post(&male_avail);
sem_wait(&fem_avail);
LODWORD(v5) = sem_wait(&maker_avail);
return v5;
}
sem_post(&maker_avail);
pthread_mutex_lock(&stdout_lock);
v6 = func8();
printf("(t=%f) %d: %s\n", v6, a1, "Became MatchMaker");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v7 = func8();
printf("(t=%f) %d: %s\n", v7, a1, "Mated");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v5 = *(_QWORD *)(maleQ + 8);
if ( v5 && (v8 = femaleQ, (v9 = *(_QWORD *)(femaleQ + 8)) != 0) )
{
v10 = *(_QWORD *)(maleQ + 16);
maleQ = *(_QWORD *)(maleQ + 8);
femaleQ = v9;
*(_QWORD *)(v5 + 16) = v10;
v5 = *(_QWORD *)(v8 + 16);
*(_QWORD *)(v9 + 16) = v5;
}
else
{
maleQ = 0LL;
femaleQ = 0LL;
}
--male;
--female;
return v5;
}

original_code:
void create_male(int id) {
 pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Male Created"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
 if((male > 0) && (female > 0))
 {
  sem_post(&maker_avail);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Became MatchMaker"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Mated"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  if(maleQ->next!=((void *)0) && femaleQ->next!=((void *)0))
  {
   maleQ->next->tail=maleQ->tail;
   maleQ=maleQ->next;
   femaleQ->next->tail=femaleQ->tail;
   femaleQ=femaleQ->next;
  }
  else{
   maleQ=((void *)0);
   femaleQ=((void *)0);
   }
  male--;
  female--;
 }
 else if (female > 0)
 {
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), femaleQ->id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  male++;
  whale_t *temp=(whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
maleQ->tail->next=temp;
maleQ->tail=temp;
maleQ->tail->next=((void *)0);
  sem_post(&male_avail);
  sem_wait(&maker_avail);
 }
 else
 {
 whale_t *temp=(whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
maleQ->tail->next=temp;
maleQ->tail=temp;
maleQ->tail->next=((void *)0);
  male++;
  sem_post(&male_avail);
  sem_wait(&fem_avail);
  sem_wait(&maker_avail);
 }
}

canonical_original_code:
void create_male(int id) {
 pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Male Created"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
 if((male > 0) && (female > 0))
 {
  sem_post(&maker_avail);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Became MatchMaker"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Mated"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  if(maleQ->next!=((void *)0) && femaleQ->next!=((void *)0))
  {
   maleQ->next->tail=maleQ->tail;
   maleQ=maleQ->next;
   femaleQ->next->tail=femaleQ->tail;
   femaleQ=femaleQ->next;
  }
  else{
   maleQ=((void *)0);
   femaleQ=((void *)0);
   }
  male--;
  female--;
 }
 else if (female > 0)
 {
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), femaleQ->id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  male++;
  struct whale *temp = (whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
maleQ->tail->next=temp;
maleQ->tail=temp;
maleQ->tail->next=((void *)0);
  sem_post(&male_avail);
  sem_wait(&maker_avail);
 }
 else
 {
 struct whale *temp = (whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
maleQ->tail->next=temp;
maleQ->tail=temp;
maleQ->tail->next=((void *)0);
  male++;
  sem_post(&male_avail);
  sem_wait(&fem_avail);
  sem_wait(&maker_avail);
 }
}

variable_types: struct whale { int id; struct whale *next; struct whale *tail; } *


decompiled_code:
int __fastcall create_female(unsigned int a1)
{
double v1; // xmm0_8
unsigned int v2; // er12
double v3; // xmm0_8
double v4; // xmm0_8
_QWORD *v5; // rax
__int64 v6; // rdx
__int64 v7; // rax
double v8; // xmm0_8
double v9; // xmm0_8
__int64 v10; // rsi
__int64 v11; // rcx
__int64 v12; // rdx
_QWORD *v13; // rax
__int64 v14; // rdx

pthread_mutex_lock(&stdout_lock);
v1 = elapsed_time();
printf("(t=%f) %d: %s\n", v1, a1, "Female Created");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
if ( male <= 0 )
{
v13 = malloc(0x18uLL);
v14 = femaleQ;
++female;
*(_DWORD *)v13 = a1;
*(_QWORD *)(*(_QWORD *)(v14 + 16) + 8LL) = v13;
*(_QWORD *)(v14 + 16) = v13;
v13[1] = 0LL;
sem_post(&fem_avail);
sem_wait(&male_avail);
goto LABEL_4;
}
if ( female <= 0 )
{
pthread_mutex_lock(&stdout_lock);
v2 = *(_DWORD *)maleQ;
v3 = elapsed_time();
printf("(t=%f) %d: %s\n", v3, v2, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v4 = elapsed_time();
printf("(t=%f) %d: %s\n", v4, a1, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v5 = malloc(0x18uLL);
v6 = femaleQ;
++female;
*(_DWORD *)v5 = a1;
*(_QWORD *)(*(_QWORD *)(v6 + 16) + 8LL) = v5;
*(_QWORD *)(v6 + 16) = v5;
v5[1] = 0LL;
sem_post(&fem_avail);
LABEL_4:
LODWORD(v7) = sem_wait(&maker_avail);
return v7;
}
sem_post(&maker_avail);
pthread_mutex_lock(&stdout_lock);
v8 = elapsed_time();
printf("(t=%f) %d: %s\n", v8, a1, "Became MatchMaker");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v9 = elapsed_time();
printf("(t=%f) %d: %s\n", v9, a1, "Mated");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v7 = *(_QWORD *)(maleQ + 8);
if ( v7 && (v10 = femaleQ, (v11 = *(_QWORD *)(femaleQ + 8)) != 0) )
{
v12 = *(_QWORD *)(maleQ + 16);
maleQ = *(_QWORD *)(maleQ + 8);
femaleQ = v11;
*(_QWORD *)(v7 + 16) = v12;
v7 = *(_QWORD *)(v10 + 16);
*(_QWORD *)(v11 + 16) = v7;
}
else
{
maleQ = 0LL;
femaleQ = 0LL;
}
--male;
--female;
return v7;
}

canonical_decompiled_code:
int __fastcall func10(unsigned int a1)
{
double v1; // xmm0_8
unsigned int v2; // er12
double v3; // xmm0_8
double v4; // xmm0_8
_QWORD *v5; // rax
__int64 v6; // rdx
__int64 v7; // rax
double v8; // xmm0_8
double v9; // xmm0_8
__int64 v10; // rsi
__int64 v11; // rcx
__int64 v12; // rdx
_QWORD *v13; // rax
__int64 v14; // rdx

pthread_mutex_lock(&stdout_lock);
v1 = func8();
printf("(t=%f) %d: %s\n", v1, a1, "Female Created");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
if ( male <= 0 )
{
v13 = malloc(0x18uLL);
v14 = femaleQ;
++female;
*(_DWORD *)v13 = a1;
*(_QWORD *)(*(_QWORD *)(v14 + 16) + 8LL) = v13;
*(_QWORD *)(v14 + 16) = v13;
v13[1] = 0LL;
sem_post(&fem_avail);
sem_wait(&male_avail);
goto LABEL_4;
}
if ( female <= 0 )
{
pthread_mutex_lock(&stdout_lock);
v2 = *(_DWORD *)maleQ;
v3 = func8();
printf("(t=%f) %d: %s\n", v3, v2, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v4 = func8();
printf("(t=%f) %d: %s\n", v4, a1, "Found Mate");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v5 = malloc(0x18uLL);
v6 = femaleQ;
++female;
*(_DWORD *)v5 = a1;
*(_QWORD *)(*(_QWORD *)(v6 + 16) + 8LL) = v5;
*(_QWORD *)(v6 + 16) = v5;
v5[1] = 0LL;
sem_post(&fem_avail);
LABEL_4:
LODWORD(v7) = sem_wait(&maker_avail);
return v7;
}
sem_post(&maker_avail);
pthread_mutex_lock(&stdout_lock);
v8 = func8();
printf("(t=%f) %d: %s\n", v8, a1, "Became MatchMaker");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
pthread_mutex_lock(&stdout_lock);
v9 = func8();
printf("(t=%f) %d: %s\n", v9, a1, "Mated");
fflush(stdout);
pthread_mutex_unlock(&stdout_lock);
v7 = *(_QWORD *)(maleQ + 8);
if ( v7 && (v10 = femaleQ, (v11 = *(_QWORD *)(femaleQ + 8)) != 0) )
{
v12 = *(_QWORD *)(maleQ + 16);
maleQ = *(_QWORD *)(maleQ + 8);
femaleQ = v11;
*(_QWORD *)(v7 + 16) = v12;
v7 = *(_QWORD *)(v10 + 16);
*(_QWORD *)(v11 + 16) = v7;
}
else
{
maleQ = 0LL;
femaleQ = 0LL;
}
--male;
--female;
return v7;
}

original_code:
void create_female(int id) {
 pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Female Created"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
 if((male > 0) && (female > 0))
 {
  sem_post(&maker_avail);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Became MatchMaker"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Mated"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  if(maleQ->next!=((void *)0) && femaleQ->next!=((void *)0))
  {
   maleQ->next->tail=maleQ->tail;
   maleQ=maleQ->next;
   femaleQ->next->tail=femaleQ->tail;
   femaleQ=femaleQ->next;
  }
  else{
   maleQ=((void *)0);
   femaleQ=((void *)0);
   }
  male--;
  female--;
 }
 else if (male > 0)
 {
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), maleQ->id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
   whale_t *temp=(whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
femaleQ->tail->next=temp;
femaleQ->tail=temp;
femaleQ->tail->next=((void *)0);
  female++;
  sem_post(&fem_avail);
  sem_wait(&maker_avail);
 }
 else
 {
whale_t *temp=(whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
femaleQ->tail->next=temp;
femaleQ->tail=temp;
femaleQ->tail->next=((void *)0);
  female++;
  sem_post(&fem_avail);
  sem_wait(&male_avail);
  sem_wait(&maker_avail);
 }
}

canonical_original_code:
void create_female(int id) {
 pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Female Created"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
 if((male > 0) && (female > 0))
 {
  sem_post(&maker_avail);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Became MatchMaker"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Mated"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  if(maleQ->next!=((void *)0) && femaleQ->next!=((void *)0))
  {
   maleQ->next->tail=maleQ->tail;
   maleQ=maleQ->next;
   femaleQ->next->tail=femaleQ->tail;
   femaleQ=femaleQ->next;
  }
  else{
   maleQ=((void *)0);
   femaleQ=((void *)0);
   }
  male--;
  female--;
 }
 else if (male > 0)
 {
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), maleQ->id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %s\n", elapsed_time(), id, "Found Mate"); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
   struct whale *temp = (whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
femaleQ->tail->next=temp;
femaleQ->tail=temp;
femaleQ->tail->next=((void *)0);
  female++;
  sem_post(&fem_avail);
  sem_wait(&maker_avail);
 }
 else
 {
struct whale *temp = (whale_t*) malloc(sizeof(whale_t));
  temp->id =id;
femaleQ->tail->next=temp;
femaleQ->tail=temp;
femaleQ->tail->next=((void *)0);
  female++;
  sem_post(&fem_avail);
  sem_wait(&male_avail);
  sem_wait(&maker_avail);
 }
}


decompiled_code:
void __fastcall __noreturn create_whale(void *a1)
{
unsigned int v1; // edi

v1 = *(_DWORD *)a1;
if ( (rand() & 1) != 0 )
create_male(v1);
else
create_female(v1);
pthread_exit(0LL);
}

canonical_decompiled_code:
void __fastcall __noreturn func11(void *a1)
{
unsigned int v1; // edi

v1 = *(_DWORD *)a1;
if ( (rand() & 1) != 0 )
func9(v1);
else
func10(v1);
pthread_exit(0LL);
}

original_code:
void *create_whale(void* arg) {
 int id = *((int *) arg);
 if (rand() & 1) {
  create_male(id);
 } else {
  create_female(id);
 }
 pthread_exit(((void *)0));
}

canonical_original_code:
void *create_whale(void *arg) {
 int id = *((int *) arg);
 if (rand() & 1) {
  create_male(id);
 } else {
  create_female(id);
 }
 pthread_exit(((void *)0));
}

variable_types:
arg
void *

return_type: void *


decompiled_code:
int __fastcall whale_sleep(int a1)
{
return usleep(1000 * a1);
}

canonical_decompiled_code:
int __fastcall func12(int a1)
{
return usleep(1000 * a1);
}

original_code:
void whale_sleep(int sem_wait_time_ms) {
 usleep(sem_wait_time_ms * 1000);
}


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
int v4; // ebp
int arg; // [rsp+4h] [rbp-74h] BYREF
pthread_t newthread; // [rsp+8h] [rbp-70h] BYREF
struct timeval tv; // [rsp+10h] [rbp-68h] BYREF
pthread_attr_t attr; // [rsp+20h] [rbp-58h] BYREF

if ( argc != 3 )
usage(*argv);
whaleInit(argc, argv, envp);
pthread_mutex_init(&stdout_lock, 0LL);
gettimeofday(&tv, 0LL);
srand(tv.tv_usec);
gettimeofday(&time0, 0LL);
v3 = atoi(argv[1]);
v4 = (int)(atof(argv[2]) * 1000.0);
sem_init(&male_avail, 0, 0);
sem_init(&fem_avail, 0, 0);
sem_init(&maker_avail, 0, 0);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, 1);
for ( arg = 0; arg < v3; ++arg )
{
whale_sleep((unsigned int)v4);
pthread_create(&newthread, &attr, create_whale, &arg);
}
whale_sleep((unsigned int)(int)((double)v4 * 10.0));
pthread_mutex_destroy(&stdout_lock);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
int v4; // ebp
int arg; // [rsp+4h] [rbp-74h] BYREF
pthread_t newthread; // [rsp+8h] [rbp-70h] BYREF
struct timeval tv; // [rsp+10h] [rbp-68h] BYREF
pthread_attr_t attr; // [rsp+20h] [rbp-58h] BYREF

if ( argc != 3 )
func13(*argv);
func7(argc, argv, envp);
pthread_mutex_init(&stdout_lock, 0LL);
gettimeofday(&tv, 0LL);
srand(tv.tv_usec);
gettimeofday(&time0, 0LL);
v3 = atoi(argv[1]);
v4 = (int)(atof(argv[2]) * 1000.0);
sem_init(&male_avail, 0, 0);
sem_init(&fem_avail, 0, 0);
sem_init(&maker_avail, 0, 0);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, 1);
for ( arg = 0; arg < v3; ++arg )
{
func12((unsigned int)v4);
pthread_create(&newthread, &attr, create_whale, &arg);
}
func12((unsigned int)(int)((double)v4 * 10.0));
pthread_mutex_destroy(&stdout_lock);
return 0;
}

original_code:
int main(int argc, char *argv[]) {
 if (argc != 3) {
  usage(argv[0]);
 }
 whaleInit();
 pthread_mutex_init(&stdout_lock, ((void *)0));
 struct timeval tv;
 gettimeofday(&tv, ((void *)0));
 srand(tv.tv_usec);
 gettimeofday(&time0, ((void *)0));
 int num_whales = atoi(argv[1]);
 int sem_wait_time_ms = atof(argv[2]) * 1000;
   sem_init(&male_avail, 0, 0);
  sem_init(&fem_avail, 0, 0);
   sem_init(&maker_avail, 0, 0);
 pthread_attr_t thread_attr;
 pthread_attr_init(&thread_attr);
 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
 for (int whale = 0; whale < num_whales; whale++) {
  whale_sleep(sem_wait_time_ms);
  pthread_t whale_thread_id;
  pthread_create(&whale_thread_id, &thread_attr, create_whale, (void *) &whale);
 }
 whale_sleep(sem_wait_time_ms * 10.0);
 pthread_mutex_destroy(&stdout_lock);
}

canonical_original_code:
int main(int argc, char *argv[]) {
 if (argc != 3) {
  usage(argv[0]);
 }
 whaleInit();
 pthread_mutex_init(&stdout_lock, ((void *)0));
 struct timeval tv;
 gettimeofday(&tv, ((void *)0));
 srand(tv.tv_usec);
 gettimeofday(&time0, ((void *)0));
 int num_whales = atoi(argv[1]);
 int sem_wait_time_ms = atof(argv[2]) * 1000;
   sem_init(&male_avail, 0, 0);
  sem_init(&fem_avail, 0, 0);
   sem_init(&maker_avail, 0, 0);
 union pthread_attr_t thread_attr;
 pthread_attr_init(&thread_attr);
 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
 for (int whale = 0; whale < num_whales; whale++) {
  whale_sleep(sem_wait_time_ms);
  unsigned long whale_thread_id;
  pthread_create(&whale_thread_id, &thread_attr, create_whale, (void *) &whale);
 }
 whale_sleep(sem_wait_time_ms * 10.0);
 pthread_mutex_destroy(&stdout_lock);
}

variable_types:
argv
char *[]

variable_types: struct timeval { long tv_sec; long tv_usec; }

variable_types: union pthread_attr_t { char __size[56]; long __align; }

variable_types: whale int


decompiled_code:
double elapsed_time()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)(LODWORD(v1.tv_usec) - LODWORD(time0.tv_usec)) / 1000000.0
+ (double)(LODWORD(v1.tv_sec) - LODWORD(time0.tv_sec));
}

canonical_decompiled_code:
double func8()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)(LODWORD(v1.tv_usec) - LODWORD(time0.tv_usec)) / 1000000.0
+ (double)(LODWORD(v1.tv_sec) - LODWORD(time0.tv_sec));
}

original_code:
double elapsed_time() {
 struct timeval tv;
 gettimeofday(&tv, ((void *)0));
 return (tv.tv_sec - time0.tv_sec + (tv.tv_usec - time0.tv_usec) / 1.e6 );
}

return_type: double

user_defined_types: struct timeval { long tv_sec; long tv_usec; }


usage

decompiled_code:
void __fastcall __noreturn usage(const char *a1)
{
fprintf(
stderr,
"Usage: %s num_whales sem_wait_time\n"
"\tnum_whales - the total number of whales to create\n"
"\tsem_wait_time - the amount of time to sem_wait before creating another whale (seconds)\n",
a1);
exit(-1);
}

canonical_decompiled_code:
void __fastcall __noreturn func13(const char *a1)
{
fprintf(
stderr,
"Usage: %s num_whales sem_wait_time\n"
"\tnum_whales - the total number of whales to create\n"
"\tsem_wait_time - the amount of time to sem_wait before creating another whale (seconds)\n",
a1);
exit(-1);
}

original_code:
void usage(char *arg0) {
 fprintf(stderr, "Usage: %s num_whales sem_wait_time\n"
     "\tnum_whales - the total number of whales to create\n"
      "\tsem_wait_time - the amount of time to sem_wait before creating another whale (seconds)\n",
     arg0);
 exit(-1);
}


decompiled_code:
void __fastcall string_data_delete(__int64 a1)
{
free(*(void **)(a1 + 16));
}

canonical_decompiled_code:
void __fastcall func1(__int64 a1)
{
free(*(void **)(a1 + 16));
}

original_code:
void string_data_delete(void *item){
  free(((list_item_t*)item)->data);
}

canonical_original_code:
void string_data_delete(void *item){
  free(((struct list_item *)item)->data);
}


decompiled_code:
int __fastcall print_data_string(__int64 a1)
{
return puts(*(const char **)(a1 + 16));
}

canonical_decompiled_code:
int __fastcall func2(__int64 a1)
{
return puts(*(const char **)(a1 + 16));
}

original_code:
void print_data_string(void *v){
  printf("%s\n", (char*)( ( (list_item_t*)v)->data));
}

canonical_original_code:
void print_data_string(void *v){
  printf("%s\n", (char *)( ( (struct list_item *)v)->data));
}

variable_types:
v
void *


decompiled_code:
int __fastcall list_item_compare_string(__int64 a1, __int64 a2)
{
return strcmp(*(const char **)(*(_QWORD *)a1 + 16LL), *(const char **)(*(_QWORD *)a2 + 16LL));
}

canonical_decompiled_code:
int __fastcall func3(__int64 a1, __int64 a2)
{
return strcmp(*(const char **)(*(_QWORD *)a1 + 16LL), *(const char **)(*(_QWORD *)a2 + 16LL));
}

original_code:
int list_item_compare_string(const void *key, const void *with){
  list_item_t **arg1 = (list_item_t**)key;
  list_item_t **arg2 = (list_item_t**)with;
  char *data1 = (char*)((*arg1)->data);
  char *data2 = (char*)((*arg2)->data);
  return strcmp(data1, data2);
}

canonical_original_code:
int list_item_compare_string(void *key, void *with){
  struct list_item **arg1 = (list_item_t**)key;
  struct list_item **arg2 = (list_item_t**)with;
  char *data1 = (char*)((*arg1)->data);
  char *data2 = (char*)((*arg2)->data);
  return strcmp(data1, data2);
}


decompiled_code:
__int64 __fastcall cleanup_list(_QWORD *a1)
{
__int64 result; // rax

for ( ; *a1; result = list_remove_head(a1) )
;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(_QWORD *a1)
{
__int64 result; // rax

for ( ; *a1; result = list_remove_head(a1) )
;
return result;
}

original_code:
void cleanup_list(list_t *l){
  while(l->head != ((void *)0))
    {
      list_remove_head(l);
    }
}

canonical_original_code:
void cleanup_list(struct list *l){
  while(l->head != ((void *)0))
    {
      list_remove_head(l);
    }
}

variable_types: struct list { struct list_item { struct list_item *prev; void *data; } *head; unsigned int length; int (*compare)(void *key, void *with); void (*data_delete)(void *data); } *


decompiled_code:
int __fastcall update_state(unsigned int *a1, unsigned int a2)
{
unsigned int v2; // er12
unsigned int v3; // ebp
double v4; // xmm0_8

a1[1] = a2;
pthread_mutex_lock(&stdout_lock);
v2 = a1[1];
v3 = *a1;
v4 = elapsed_time();
printf("(t=%f) %d: %c\n", v4, v3, v2);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

canonical_decompiled_code:
int __fastcall func8(unsigned int *a1, unsigned int a2)
{
unsigned int v2; // er12
unsigned int v3; // ebp
double v4; // xmm0_8

a1[1] = a2;
pthread_mutex_lock(&stdout_lock);
v2 = a1[1];
v3 = *a1;
v4 = func7();
printf("(t=%f) %d: %c\n", v4, v3, v2);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

original_code:
void
update_state (philosopher_t * philosopher, state_t state)
{
  philosopher->state = state;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %c\n", elapsed_time (), philosopher->id, philosopher->state); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

canonical_original_code:
void update_state(struct _philosopher *philosopher, enum _state state)
{
  philosopher->state = state;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: %c\n", elapsed_time (), philosopher->id, philosopher->state); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

variable_types: struct _philosopher { int id; enum _state { STATE_THINKING=expr, STATE_HUNGRY=expr, STATE_EATING=expr } state; struct _chopstick { _Bool down; } *left; struct _philosopher *left_phil; double avg_wait; _Bool do_random; } *

user_defined_types: struct _philosopher { int id; enum _state state; struct _chopstick *left; struct _philosopher *left_phil; double avg_wait; _Bool do_random; }


decompiled_code:
int __fastcall pickup_left(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 1) = 0;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = elapsed_time();
printf("(t=%f) %d: LEFT UP\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

canonical_decompiled_code:
int __fastcall func9(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 1) = 0;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = func7();
printf("(t=%f) %d: LEFT UP\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

original_code:
void
pickup_left (philosopher_t * philosopher)
{
  philosopher->left->down = 0;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: LEFT UP\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

canonical_original_code:
void pickup_left(struct _philosopher *philosopher)
{
  philosopher->left->down = 0;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: LEFT UP\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

user_defined_types: enum _state { STATE_THINKING=expr, STATE_HUNGRY=expr, STATE_EATING=expr }


decompiled_code:
int __fastcall pickup_right(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 2) = 0;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = elapsed_time();
printf("(t=%f) %d: RIGHT UP\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

canonical_decompiled_code:
int __fastcall func10(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 2) = 0;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = func7();
printf("(t=%f) %d: RIGHT UP\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

original_code:
void
pickup_right (philosopher_t * philosopher)
{
  philosopher->right->down = 0;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: RIGHT UP\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

canonical_original_code:
void pickup_right(struct _philosopher *philosopher)
{
  philosopher->right->down = 0;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: RIGHT UP\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}


decompiled_code:
int __fastcall putdown_left(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 1) = 1;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = elapsed_time();
printf("(t=%f) %d: LEFT DOWN\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

canonical_decompiled_code:
int __fastcall func11(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 1) = 1;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = func7();
printf("(t=%f) %d: LEFT DOWN\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

original_code:
void
putdown_left (philosopher_t * philosopher)
{
  philosopher->left->down = 1;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: LEFT DOWN\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

canonical_original_code:
void putdown_left(struct _philosopher *philosopher)
{
  philosopher->left->down = 1;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: LEFT DOWN\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}


decompiled_code:
int __fastcall putdown_right(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 2) = 1;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = elapsed_time();
printf("(t=%f) %d: RIGHT DOWN\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

canonical_decompiled_code:
int __fastcall func12(int *a1)
{
unsigned int v1; // ebp
double v2; // xmm0_8

**((_BYTE **)a1 + 2) = 1;
pthread_mutex_lock(&stdout_lock);
v1 = *a1;
v2 = func7();
printf("(t=%f) %d: RIGHT DOWN\n", v2, v1);
fflush(stdout);
return pthread_mutex_unlock(&stdout_lock);
}

original_code:
void
putdown_right (philosopher_t * philosopher)
{
  philosopher->right->down = 1;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: RIGHT DOWN\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}

canonical_original_code:
void putdown_right(struct _philosopher *philosopher)
{
  philosopher->right->down = 1;
  pthread_mutex_lock(&stdout_lock); printf("(t=%f) %d: RIGHT DOWN\n", elapsed_time (), philosopher->id); fflush(stdout); pthread_mutex_unlock(&stdout_lock);
}


original_code:
void
phil_sleep (philosopher_t * philosopher)
{
  int wait_time_us = philosopher->avg_wait * 1e6;
  if (philosopher->do_random)
    {
      wait_time_us = rand () / (2147483647 + 1.0) * 2.0 * wait_time_us;
    }
  usleep (wait_time_us);
}

canonical_original_code:
void phil_sleep(struct _philosopher *philosopher)
{
  int wait_time_us = philosopher->avg_wait * 1e6;
  if (philosopher->do_random)
    {
      wait_time_us = rand () / (2147483647 + 1.0) * 2.0 * wait_time_us;
    }
  usleep (wait_time_us);
}


decompiled_code:
void __fastcall __noreturn philosopher_thread(void *a1)
{
while ( 1 )
{
phil_sleep((__int64)a1);
update_state((unsigned int *)a1, 0x48u);
if ( pthread_mutex_trylock(&chopstick_manipulation_lock) )
{
pthread_mutex_lock(&canEat_mutex);
pthread_cond_wait(&canEat_cv, &canEat_mutex);
pthread_mutex_unlock(&canEat_mutex);
pthread_mutex_lock(&chopstick_manipulation_lock);
}
pickup_right((int *)a1);
pickup_left((int *)a1);
update_state((unsigned int *)a1, 0x45u);
phil_sleep((__int64)a1);
putdown_right((int *)a1);
putdown_left((int *)a1);
pthread_mutex_lock(&canEat_mutex);
pthread_cond_signal(&canEat_cv);
pthread_mutex_unlock(&canEat_mutex);
update_state((unsigned int *)a1, 0x54u);
pthread_mutex_unlock(&chopstick_manipulation_lock);
phil_sleep((__int64)a1);
}
}

canonical_decompiled_code:
void __fastcall __noreturn func14(void *a1)
{
while ( 1 )
{
func13((__int64)a1);
func8((unsigned int *)a1, 0x48u);
if ( pthread_mutex_trylock(&chopstick_manipulation_lock) )
{
pthread_mutex_lock(&canEat_mutex);
pthread_cond_wait(&canEat_cv, &canEat_mutex);
pthread_mutex_unlock(&canEat_mutex);
pthread_mutex_lock(&chopstick_manipulation_lock);
}
func10((int *)a1);
func9((int *)a1);
func8((unsigned int *)a1, 0x45u);
func13((__int64)a1);
func12((int *)a1);
func11((int *)a1);
pthread_mutex_lock(&canEat_mutex);
pthread_cond_signal(&canEat_cv);
pthread_mutex_unlock(&canEat_mutex);
func8((unsigned int *)a1, 0x54u);
pthread_mutex_unlock(&chopstick_manipulation_lock);
func13((__int64)a1);
}
}

original_code:
void *
philosopher_thread (void *arg)
{
  philosopher_t *philosopher = (philosopher_t *) arg;
  while (1)
    {
      phil_sleep (philosopher);
      update_state (philosopher, STATE_HUNGRY);
      int manipulate = pthread_mutex_trylock(&chopstick_manipulation_lock);
      if ( manipulate != 0 )
        {
          pthread_mutex_lock(&canEat_mutex);
          pthread_cond_wait(&canEat_cv, &canEat_mutex);
          pthread_mutex_unlock(&canEat_mutex);
          pthread_mutex_lock(&chopstick_manipulation_lock);
        }
      pickup_right(philosopher);
      pickup_left(philosopher);
      update_state(philosopher, STATE_EATING);
      phil_sleep(philosopher);
      putdown_right(philosopher);
      putdown_left(philosopher);
      pthread_mutex_lock(&canEat_mutex);
      pthread_cond_signal(&canEat_cv);
      pthread_mutex_unlock(&canEat_mutex);
      update_state(philosopher, STATE_THINKING);
      pthread_mutex_unlock(&chopstick_manipulation_lock);
      phil_sleep (philosopher);
    }
  pthread_exit (((void *)0));
}

canonical_original_code:
void *philosopher_thread(void *arg)
{
  struct _philosopher *philosopher = (philosopher_t *) arg;
  while (1)
    {
      phil_sleep (philosopher);
      update_state (philosopher, STATE_HUNGRY);
      int manipulate = pthread_mutex_trylock(&chopstick_manipulation_lock);
      if ( manipulate != 0 )
        {
          pthread_mutex_lock(&canEat_mutex);
          pthread_cond_wait(&canEat_cv, &canEat_mutex);
          pthread_mutex_unlock(&canEat_mutex);
          pthread_mutex_lock(&chopstick_manipulation_lock);
        }
      pickup_right(philosopher);
      pickup_left(philosopher);
      update_state(philosopher, STATE_EATING);
      phil_sleep(philosopher);
      putdown_right(philosopher);
      putdown_left(philosopher);
      pthread_mutex_lock(&canEat_mutex);
      pthread_cond_signal(&canEat_cv);
      pthread_mutex_unlock(&canEat_mutex);
      update_state(philosopher, STATE_THINKING);
      pthread_mutex_unlock(&chopstick_manipulation_lock);
      phil_sleep (philosopher);
    }
  pthread_exit (((void *)0));
}

variable_types: manipulate int


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t v3; // r12
size_t v4; // r13
int v5; // er14
bool v6; // bl
char *v7; // rbp
char *v8; // r12
char *v9; // r15
char *v10; // r9
_DWORD *v11; // rcx
int v12; // esi
__int64 v13; // rdi
pthread_t *v14; // r14
pthread_t *v15; // r13
pthread_t *v16; // rbx
pthread_t v17; // rdi
double ptr; // [rsp+0h] [rbp-48h]
pthread_t *ptra; // [rsp+0h] [rbp-48h]
void *ptrb; // [rsp+0h] [rbp-48h]
__int64 v22; // [rsp+8h] [rbp-40h]

gettimeofday(&time0, 0LL);
if ( argc <= 3 )
usage(*argv);
v3 = atoi(argv[1]);
v4 = 8 * v3;
v5 = v3;
ptr = atof(argv[2]);
v6 = atoi(argv[3]) != 0;
pthread_mutex_init(&stdout_lock, 0LL);
pthread_mutex_init(&chopstick_manipulation_lock, 0LL);
pthread_mutex_init(&canEat_mutex, 0LL);
pthread_cond_init(&canEat_cv, 0LL);
v7 = (char *)malloc(56 * v3);
v8 = (char *)malloc(v3);
if ( v5 <= 0 )
{
ptrb = malloc(v4);
free(ptrb);
}
else
{
v9 = v7;
v22 = (unsigned int)v5;
memset(v8, 1, (unsigned int)v5);
v10 = v8;
v11 = v7;
v12 = 0;
do
{
*v11 = v12++;
v11 += 14;
*((_QWORD *)v11 - 6) = v10++;
*((double *)v11 - 2) = ptr;
*((_BYTE *)v11 - 8) = v6;
*(v11 - 13) = 84;
v13 = v12 % v5;
*((_QWORD *)v11 - 5) = &v8[v13];
*((_QWORD *)v11 - 4) = &v7[56 * ((v5 - 2 + v12) % v5)];
*((_QWORD *)v11 - 3) = &v7[56 * v13];
}
while ( v12 != v5 );
v14 = (pthread_t *)malloc(v4);
ptra = v14;
v15 = v14;
v16 = &v14[v22];
do
{
pthread_create(v14++, 0LL, philosopher_thread, v9);
v9 += 56;
}
while ( v16 != v14 );
do
{
v17 = *v15++;
pthread_join(v17, 0LL);
}
while ( v16 != v15 );
free(ptra);
}
free(v7);
free(v8);
pthread_mutex_destroy(&stdout_lock);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t v3; // r12
size_t v4; // r13
int v5; // er14
bool v6; // bl
char *v7; // rbp
char *v8; // r12
char *v9; // r15
char *v10; // r9
_DWORD *v11; // rcx
int v12; // esi
__int64 v13; // rdi
pthread_t *v14; // r14
pthread_t *v15; // r13
pthread_t *v16; // rbx
pthread_t v17; // rdi
double ptr; // [rsp+0h] [rbp-48h]
pthread_t *ptra; // [rsp+0h] [rbp-48h]
void *ptrb; // [rsp+0h] [rbp-48h]
__int64 v22; // [rsp+8h] [rbp-40h]

gettimeofday(&time0, 0LL);
if ( argc <= 3 )
func15(*argv);
v3 = atoi(argv[1]);
v4 = 8 * v3;
v5 = v3;
ptr = atof(argv[2]);
v6 = atoi(argv[3]) != 0;
pthread_mutex_init(&stdout_lock, 0LL);
pthread_mutex_init(&chopstick_manipulation_lock, 0LL);
pthread_mutex_init(&canEat_mutex, 0LL);
pthread_cond_init(&canEat_cv, 0LL);
v7 = (char *)malloc(56 * v3);
v8 = (char *)malloc(v3);
if ( v5 <= 0 )
{
ptrb = malloc(v4);
free(ptrb);
}
else
{
v9 = v7;
v22 = (unsigned int)v5;
memset(v8, 1, (unsigned int)v5);
v10 = v8;
v11 = v7;
v12 = 0;
do
{
*v11 = v12++;
v11 += 14;
*((_QWORD *)v11 - 6) = v10++;
*((double *)v11 - 2) = ptr;
*((_BYTE *)v11 - 8) = v6;
*(v11 - 13) = 84;
v13 = v12 % v5;
*((_QWORD *)v11 - 5) = &v8[v13];
*((_QWORD *)v11 - 4) = &v7[56 * ((v5 - 2 + v12) % v5)];
*((_QWORD *)v11 - 3) = &v7[56 * v13];
}
while ( v12 != v5 );
v14 = (pthread_t *)malloc(v4);
ptra = v14;
v15 = v14;
v16 = &v14[v22];
do
{
pthread_create(v14++, 0LL, philosopher_thread, v9);
v9 += 56;
}
while ( v16 != v14 );
do
{
v17 = *v15++;
pthread_join(v17, 0LL);
}
while ( v16 != v15 );
free(ptra);
}
free(v7);
free(v8);
pthread_mutex_destroy(&stdout_lock);
return 0;
}

original_code:
int
main (int argc, char *argv[])
{
  gettimeofday (&time0, ((void *)0));
  int n;
  double avg_wait;
  _Bool do_random;
  if (argc < 4)
    {
      usage (argv[0]);
    }
  n = atoi (argv[1]);
  avg_wait = atof (argv[2]);
  do_random = atoi (argv[3]);
  pthread_mutex_init (&stdout_lock, ((void *)0));
  pthread_mutex_init(&chopstick_manipulation_lock, ((void *)0));
  pthread_mutex_init(&canEat_mutex, ((void *)0));
  pthread_cond_init(&canEat_cv, ((void *)0));
  philosopher_t *philosophers =
    (philosopher_t *) malloc (sizeof (philosopher_t) * n);
  chopstick_t *chopsticks = (chopstick_t *) malloc (sizeof (chopstick_t) * n);
  for (int i = 0; i < n; i++)
    {
      chopsticks[i].down = 1;
    }
  for (int i = 0; i < n; i++)
    {
      philosophers[i].id = i;
      philosophers[i].left = &chopsticks[i];
      philosophers[i].right = &chopsticks[(i + 1) % n];
      philosophers[i].left_phil = &philosophers[(i + n - 1) % n];
      philosophers[i].right_phil = &philosophers[(i + 1) % n];
      philosophers[i].avg_wait = avg_wait;
      philosophers[i].do_random = do_random;
      philosophers[i].state = STATE_THINKING;
    }
  pthread_t *pids = (pthread_t *) malloc (sizeof (pthread_t) * n);
  for (int i = 0; i < n; i++)
    {
      pthread_create (&pids[i], ((void *)0), philosopher_thread, &philosophers[i]);
    }
  for (int i = 0; i < n; i++)
    {
      pthread_join (pids[i], ((void *)0));
    }
  free (pids);
  free (philosophers);
  free (chopsticks);
  pthread_mutex_destroy (&stdout_lock);
}

canonical_original_code:
int main(int argc, char *argv[])
{
  gettimeofday (&time0, ((void *)0));
  int n;
  double avg_wait;
  _Bool do_random;
  if (argc < 4)
    {
      usage (argv[0]);
    }
  n = atoi (argv[1]);
  avg_wait = atof (argv[2]);
  do_random = atoi (argv[3]);
  pthread_mutex_init (&stdout_lock, ((void *)0));
  pthread_mutex_init(&chopstick_manipulation_lock, ((void *)0));
  pthread_mutex_init(&canEat_mutex, ((void *)0));
  pthread_cond_init(&canEat_cv, ((void *)0));
  struct _philosopher *philosophers = (philosopher_t *) malloc (sizeof (philosopher_t) * n);
  struct _chopstick *chopsticks = (chopstick_t *) malloc (sizeof (chopstick_t) * n);
  for (int i = 0; i < n; i++)
    {
      chopsticks[i].down = 1;
    }
  for (int i = 0; i < n; i++)
    {
      philosophers[i].id = i;
      philosophers[i].left = &chopsticks[i];
      philosophers[i].right = &chopsticks[(i + 1) % n];
      philosophers[i].left_phil = &philosophers[(i + n - 1) % n];
      philosophers[i].right_phil = &philosophers[(i + 1) % n];
      philosophers[i].avg_wait = avg_wait;
      philosophers[i].do_random = do_random;
      philosophers[i].state = STATE_THINKING;
    }
  unsigned long *pids = (pthread_t *) malloc (sizeof (pthread_t) * n);
  for (int i = 0; i < n; i++)
    {
      pthread_create (&pids[i], ((void *)0), philosopher_thread, &philosophers[i]);
    }
  for (int i = 0; i < n; i++)
    {
      pthread_join (pids[i], ((void *)0));
    }
  free (pids);
  free (philosophers);
  free (chopsticks);
  pthread_mutex_destroy (&stdout_lock);
}

variable_types: n int

variable_types:
chopsticks
struct _chopstick { _Bool down; } *

variable_types: i int

variable_types:
pids
unsigned long *


canonical_decompiled_code:
double func7()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)(LODWORD(v1.tv_usec) - LODWORD(time0.tv_usec)) / 1000000.0
+ (double)(LODWORD(v1.tv_sec) - LODWORD(time0.tv_sec));
}

original_code:
double
elapsed_time ()
{
  struct timeval tv;
  gettimeofday (&tv, ((void *)0));
  return (tv.tv_sec - time0.tv_sec + (tv.tv_usec - time0.tv_usec) / 1.e6);
}

canonical_original_code:
double elapsed_time()
{
  struct timeval tv;
  gettimeofday (&tv, ((void *)0));
  return (tv.tv_sec - time0.tv_sec + (tv.tv_usec - time0.tv_usec) / 1.e6);
}


usage

decompiled_code:
void __fastcall __noreturn usage(const char *a1)
{
fprintf(stderr, "Usage: %s num_philosophers avg_wait_seconds use_randomness\nExample: %s 5 0.5 1\n", a1, a1);
exit(-1);
}

canonical_decompiled_code:
void __fastcall __noreturn func15(const char *a1)
{
fprintf(stderr, "Usage: %s num_philosophers avg_wait_seconds use_randomness\nExample: %s 5 0.5 1\n", a1, a1);
exit(-1);
}

original_code:
void
usage (char *arg0)
{
  fprintf (stderr,
    "Usage: %s num_philosophers avg_wait_seconds use_randomness\n"
    "Example: %s 5 0.5 1\n", arg0, arg0);
  exit (-1);
}

canonical_original_code:
void usage(char *arg0)
{
  fprintf (stderr,
    "Usage: %s num_philosophers avg_wait_seconds use_randomness\n"
    "Example: %s 5 0.5 1\n", arg0, arg0);
  exit (-1);
}


original_code:
unsigned int find_redirect(char **token_buf, unsigned int *token_buf_len)
{
  unsigned int i;
  for(i = 0; i < *token_buf_len; i++)
    {
      if( (strcmp(token_buf[i], ">") == 0) ||
   (strcmp(token_buf[i], ">>") == 0) ||
   (strcmp(token_buf[i], "<") == 0)) return i;
    }
  return 0;
}

variable_types:
i
unsigned int

return_type: unsigned int