anchor.diff:  %% Produce all possible process interleavings of (Mod, Fun, Args).
   interleave(Target, PreBound, Dpor) ->
       Self = self(),
  -    spawn_link(fun() -> interleave_dpor(Target, PreBound, Self, Dpor) end),
  +    spawn_link(fun() -> interleave_aux(Target, PreBound, Self, Dpor) end),
       receive
           {interleave_result, Result} -> Result
       end.
   
  -interleave_aux(Target, PreBound, Parent) ->
  -    register(?RP_SCHED, self()),
  -    %% The mailbox is flushed mainly to discard possible `exit` messages
  -    %% before enabling the `trap_exit` flag.
  -    concuerror_util:flush_mailbox(),
  -    process_flag(trap_exit, true),
  -    %% Initialize state table.
  -    state_start(),
  -    %% Save empty replay state for the first run.
  -    InitState = concuerror_state:empty(),
  -    state_save([InitState]),
  -    Result = interleave_outer_loop(Target, 0, [], -1, PreBound),
  -    state_stop(),
  -    unregister(?RP_SCHED),
  -    Parent ! {interleave_result, Result}.
  -
  -interleave_dpor(Target, PreBound, Parent, Dpor) ->
  +interleave_aux(Target, PreBound, Parent, Dpor) ->
       ?f_debug("Dpor is not really ready yet...\n"),
       register(?RP_SCHED, self()),
       Result = interleave_dpor(Target, PreBound, Dpor),
       ?stop_debug,
       Parent ! {interleave_result, Result}.
  -
  -interleave_outer_loop(_T, RunCnt, Tickets, MaxBound, MaxBound) ->
  -    interleave_outer_loop_ret(Tickets, RunCnt);
  -interleave_outer_loop(Target, RunCnt, Tickets, CurrBound, MaxBound) ->
  -    {NewRunCnt, TotalTickets, Stop} = interleave_loop(Target, 1, Tickets),
  -    TotalRunCnt = NewRunCnt + RunCnt,
  -    state_swap(),
  -    case state_peak() of
  -        no_state -> interleave_outer_loop_ret(TotalTickets, TotalRunCnt);
  -        _State ->
  -            case Stop of
  -                true -> interleave_outer_loop_ret(TotalTickets, TotalRunCnt);
  -                false ->
  -                    interleave_outer_loop(Target, TotalRunCnt, TotalTickets,
  -                                          CurrBound + 1, MaxBound)
  -            end
  -    end.
  -
  -interleave_outer_loop_ret([], RunCnt) ->
  -    {ok, RunCnt};
  -interleave_outer_loop_ret(Tickets, RunCnt) ->
  -    {error, RunCnt, Tickets}.
  -
  -%%------------------------------------------------------------------------------
   
   -type s_i()        :: non_neg_integer().
   -type instr()      :: term().
  
positive.code:         Tickets -> {error, RunCnt, Tickets}
      end.
  
  %%------------------------------------------------------------------------------
  
  %% Main loop for producing process interleavings.
  %% The first process (FirstPid) is created linked to the scheduler,
  %% so that the latter can receive the former's exit message when it
  %% terminates. In the same way, every process that may be spawned in
  %% the course of the program shall be linked to the scheduler process.
  interleave_loop(Target, RunCnt, Tickets) ->
      %% Lookup state to replay.
      case state_load() of
          no_state -> {RunCnt - 1, Tickets, false};
          ReplayState ->
              ?debug_1("Running interleaving ~p~n", [RunCnt]),
              ?debug_1("----------------------~n"),
              concuerror_lid:start(),
              %% Save current process list (any process created after
              %% this will be cleaned up at the end of the run)
              ProcBefore = processes(),
              %% Spawn initial user process
              {Mod, Fun, Args} = Target,
              NewFun = fun() -> wait(), apply(Mod, Fun, Args) end,
              FirstPid = spawn_link(NewFun),
              %% Initialize scheduler context
              FirstLid = concuerror_lid:new(FirstPid, noparent),
              Active = ?SETS:add_element(FirstLid, ?SETS:new()),
              Blocked = ?SETS:new(),
              State = concuerror_state:empty(),
              Context = #context{active=Active, state=State,
                  blocked=Blocked, actions=[]},
              %% Interleave using driver
              Ret = driver(Context, ReplayState),
              %% Cleanup
              proc_cleanup(processes() -- ProcBefore),
              concuerror_lid:stop(),
              NewTickets =
                  case Ret of
                      {error, Error, ErrorState} ->
                          Ticket = concuerror_ticket:new(Error, ErrorState),
                          concuerror_log:show_error(Ticket),
                          [Ticket|Tickets];
                      _OtherRet1 -> Tickets
                  end,
              NewRunCnt =
                  case Ret of
                      abort ->
                          ?debug_1("-----------------------~n"),
                          ?debug_1("Run aborted.~n~n"),
                          RunCnt;
                      _OtherRet2 ->
                          ?debug_1("-----------------------~n"),
                          ?debug_1("Run terminated.~n~n"),
                          RunCnt + 1
                  end,
              receive
                  stop_analysis -> {NewRunCnt - 1, NewTickets, true}
              after 0 ->
                      interleave_loop(Target, NewRunCnt, NewTickets)
              end
      end.
  
  %%%----------------------------------------------------------------------
  %%% Core components
  %%%----------------------------------------------------------------------
  
  driver(Context, ReplayState) ->
      case concuerror_state:is_empty(ReplayState) of
          true -> driver_normal(Context);
          false -> driver_replay(Context, ReplayState)
      end.
  
  driver_replay(Context, ReplayState) ->
      {Next, Rest} = concuerror_state:trim_head(ReplayState),
      NewContext = run(Context#context{current = Next, error = ?NO_ERROR}),
      #context{blocked = NewBlocked} = NewContext,
      case concuerror_state:is_empty(Rest) of
          true ->
              case ?SETS:is_element(Next, NewBlocked) of
                  %% If the last action of the replayed state prefix is a block,
                  %% we can safely abort.
                  true -> abort;
                  %% Replay has finished; proceed in normal mode, after checking
                  %% for errors during the last replayed action.
                  false -> check_for_errors(NewContext)
              end;
          false ->
              case ?SETS:is_element(Next, NewBlocked) of
                  true -> concuerror_log:internal(
                          "Proc. ~p should be active.", [Next]);
                  false -> driver_replay(NewContext, Rest)
              end
      end.
  
  driver_normal(#context{active=Active, current=LastLid,
                         state = State} = Context) ->
      Next =
          case ?SETS:is_element(LastLid, Active) of
              true ->
                  TmpActive = ?SETS:to_list(?SETS:del_element(LastLid, Active)),
                  {LastLid,TmpActive, next};
              false ->
                  [Head|TmpActive] = ?SETS:to_list(Active),
                  {Head, TmpActive, current}
          end,
      {NewContext, Insert} = run_no_block(Context, Next),
      insert_states(State, Insert),
      check_for_errors(NewContext).
  
  %% Handle four possible cases:
  %% - An error occured during the execution of the last process =>
  %%   Terminate the run and report the erroneous interleaving sequence.
  %% - Only blocked processes exist =>
  %%   Terminate the run and report a deadlock.
  %% - No active or blocked processes exist =>
  %%   Terminate the run without errors.
  %% - There exists at least one active process =>
  %%   Continue run.
  check_for_errors(#context{error=NewError, actions=Actions, active=NewActive,
                            blocked=NewBlocked} = NewContext) ->
      case NewError of
          ?NO_ERROR ->
              case ?SETS:size(NewActive) of
                  0 ->
                      case ?SETS:size(NewBlocked) of
                          0 -> ok;
                          _NonEmptyBlocked ->
                              Deadlock =
                                  concuerror_error:new({deadlock, NewBlocked}),
                              ErrorState = lists:reverse(Actions),
                              {error, Deadlock, ErrorState}
                      end;
                  _NonEmptyActive -> driver_normal(NewContext)
              end;
          _Other ->
              ErrorState = lists:reverse(Actions),
              {error, NewError, ErrorState}
      end.
  
  run_no_block(#context{state = State} = Context, {Next, Rest, W}) ->
      NewContext = run(Context#context{current = Next, error = ?NO_ERROR}),
      #context{blocked = NewBlocked} = NewContext,
      case ?SETS:is_element(Next, NewBlocked) of
          true ->
              case Rest of
                  [] -> {NewContext#context{state = State}, {[], W}};
                  [RH|RT] ->
                      NextContext = NewContext#context{state = State},
                      run_no_block(NextContext, {RH, RT, current})
              end;
          false -> {NewContext, {Rest, W}}
      end.
  
  insert_states(State, {Lids, current}) ->
      Extend = lists:map(fun(L) -> concuerror_state:extend(State, L) end, Lids),
      state_save(Extend);
  insert_states(State, {Lids, next}) ->
      Extend = lists:map(fun(L) -> concuerror_state:extend(State, L) end, Lids),
      state_save_next(Extend).
  
  %% Run process Lid in context Context until it encounters a preemption point.
  run(#context{current = Lid, state = State} = Context) ->
      ?debug_2("Running process ~s.~n", [concuerror_lid:to_string(Lid)]),
      %% Create new state by adding this process.
      NewState = concuerror_state:extend(State, Lid),
      %% Send message to "unblock" the process.
      continue(Lid),
      %% Dispatch incoming notifications to the appropriate handler.
      NewContext = dispatch(Context#context{state = NewState}),
      %% Update context due to wakeups caused by the last action.
      ?SETS:fold(fun check_wakeup/2, NewContext, NewContext#context.blocked).
  
  check_wakeup(Lid, #context{active = Active, blocked = Blocked} = Context) ->
      continue(Lid),
      receive
          #special{msg = wakeup} ->
              NewBlocked = ?SETS:del_element(Lid, Blocked),
              NewActive = ?SETS:add_element(Lid, Active),
              Context#context{active = NewActive, blocked = NewBlocked};
          #special{msg = no_wakeup} -> Context
      end.
  
  %% Delegate notifications sent by instrumented client code to the appropriate
  %% handlers.
  dispatch(Context) ->
      receive
          #sched{msg = Type, lid = Lid, misc = Misc} ->
              handler(Type, Lid, Context, Misc);
          %% Ignore unknown processes.
          {'EXIT', Pid, Reason} ->
              case concuerror_lid:from_pid(Pid) of
                  not_found -> dispatch(Context);
                  Lid -> handler(exit, Lid, Context, Reason)
              end
      end.
  
  %%%----------------------------------------------------------------------
  %%% Handlers
  %%%----------------------------------------------------------------------
  
  handler('after', Lid, #context{actions=Actions}=Context, _Misc) ->
      Action = {'after', Lid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  %% Move the process to the blocked set.
  handler(block, Lid,
          #context{active=Active, blocked=Blocked, actions=Actions} = Context,
          _Misc) ->
      Action = {'block', Lid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      NewActive = ?SETS:del_element(Lid, Active),
      NewBlocked = ?SETS:add_element(Lid, Blocked),
      Context#context{active=NewActive, blocked=NewBlocked, actions=NewActions};
  
  handler(demonitor, Lid, #context{actions=Actions}=Context, _Ref) ->
      %% TODO: Get LID from Ref?
      TargetLid = concuerror_lid:mock(0),
      Action = {demonitor, Lid, TargetLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  %% Remove the exited process from the active set.
  %% NOTE: This is called after a process has exited, not when it calls
  %%       exit/1 or exit/2.
  handler(exit, Lid, #context{active = Active, actions = Actions} = Context,
          Reason) ->
      NewActive = ?SETS:del_element(Lid, Active),
      %% Cleanup LID stored info.
      concuerror_lid:cleanup(Lid),
      %% Handle and propagate errors.
      case Reason of
          normal ->
              Action1 = {exit, Lid, normal},
              NewActions1 = [Action1 | Actions],
              ?debug_1(concuerror_proc_action:to_string(Action1) ++ "~n"),
              Context#context{active = NewActive, actions = NewActions1};
          _Else ->
              Error = concuerror_error:new(Reason),
              Action2 = {exit, Lid, concuerror_error:type(Error)},
              NewActions2 = [Action2 | Actions],
              ?debug_1(concuerror_proc_action:to_string(Action2) ++ "~n"),
              Context#context{active=NewActive, error=Error, actions=NewActions2}
      end;
  
  %% Return empty active and blocked queues to force run termination.
  handler(halt, Lid, #context{actions = Actions}=Context, Misc) ->
      Action =
          case Misc of
              empty  -> {halt, Lid};
              Status -> {halt, Lid, Status}
          end,
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{active=?SETS:new(),blocked=?SETS:new(),actions=NewActions};
  
  handler(is_process_alive, Lid, #context{actions=Actions}=Context, TargetPid) ->
      TargetLid = concuerror_lid:from_pid(TargetPid),
      Action = {is_process_alive, Lid, TargetLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(link, Lid, #context{actions = Actions}=Context, TargetPid) ->
      TargetLid = concuerror_lid:from_pid(TargetPid),
      Action = {link, Lid, TargetLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(monitor, Lid, #context{actions = Actions}=Context, {Item, _Ref}) ->
      TargetLid = concuerror_lid:from_pid(Item),
      Action = {monitor, Lid, TargetLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(process_flag, Lid, #context{actions=Actions}=Context, {Flag, Value}) ->
      Action = {process_flag, Lid, Flag, Value},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  %% Normal receive message handler.
  handler('receive', Lid, #context{actions = Actions}=Context, {From, Msg}) ->
      Action = {'receive', Lid, From, Msg},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  %% Receive message handler for special messages, like 'EXIT' and 'DOWN',
  %% which don't have an associated sender process.
  handler('receive_no_instr', Lid, #context{actions = Actions}=Context, Msg) ->
      Action = {'receive_no_instr', Lid, Msg},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(register, Lid, #context{actions=Actions}=Context, {RegName, RegLid}) ->
      Action = {register, Lid, RegName, RegLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(send, Lid, #context{actions = Actions}=Context, {DstPid, Msg}) ->
      DstLid = concuerror_lid:from_pid(DstPid),
      Action = {send, Lid, DstLid, Msg},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  %% Link the newly spawned process to the scheduler process and add it to the
  %% active set.
  handler(spawn, ParentLid,
          #context{active= Active, actions = Actions} = Context, ChildPid) ->
      link(ChildPid),
      ChildLid = concuerror_lid:new(ChildPid, ParentLid),
      Action = {spawn, ParentLid, ChildLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      NewActive = ?SETS:add_element(ChildLid, Active),
      Context#context{active = NewActive, actions = NewActions};
  
  %% FIXME: Refactor this (it's exactly the same as 'spawn')
  handler(spawn_link, ParentLid,
          #context{active = Active, actions = Actions} = Context, ChildPid) ->
      link(ChildPid),
      ChildLid = concuerror_lid:new(ChildPid, ParentLid),
      Action = {spawn_link, ParentLid, ChildLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      NewActive = ?SETS:add_element(ChildLid, Active),
      Context#context{active = NewActive, actions = NewActions};
  
  %% FIXME: Refactor this (it's almost the same as 'spawn')
  handler(spawn_monitor, ParentLid,
          #context{active=Active, actions=Actions}=Context, {ChildPid, _Ref}) ->
      link(ChildPid),
      ChildLid = concuerror_lid:new(ChildPid, ParentLid),
      Action = {spawn_monitor, ParentLid, ChildLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      NewActive = ?SETS:add_element(ChildLid, Active),
      Context#context{active = NewActive, actions = NewActions};
  
  %% Similar to above depending on options.
  handler(spawn_opt, ParentLid,
          #context{active=Active, actions=Actions}=Context, {Ret, Opt}) ->
      {ChildPid, _Ref} =
          case Ret of
              {_C, _R} = CR -> CR;
              C -> {C, noref}
          end,
      link(ChildPid),
      ChildLid = concuerror_lid:new(ChildPid, ParentLid),
      Opts = sets:to_list(sets:intersection(sets:from_list([link, monitor]),
                                            sets:from_list(Opt))),
      Action = {spawn_opt, ParentLid, ChildLid, Opts},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      NewActive = ?SETS:add_element(ChildLid, Active),
      Context#context{active = NewActive, actions = NewActions};
  
  handler(unlink, Lid, #context{actions = Actions}=Context, TargetPid) ->
      TargetLid = concuerror_lid:from_pid(TargetPid),
      Action = {unlink, Lid, TargetLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(unregister, Lid, #context{actions = Actions}=Context, RegName) ->
      Action = {unregister, Lid, RegName},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  handler(whereis, Lid, #context{actions = Actions}=Context, {RegName, Result}) ->
      ResultLid = concuerror_lid:from_pid(Result),
      Action = {whereis, Lid, RegName, ResultLid},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions};
  
  %% Handler for anything "non-special". It just passes the arguments
  %% for logging.
  %% TODO: We may be able to delete some of the above that can be handled
  %%       by this generic handler.
  handler(CallMsg, Lid, #context{actions = Actions}=Context, Args) ->
      Action = {CallMsg, Lid, Args},
      NewActions = [Action | Actions],
      ?debug_1(concuerror_proc_action:to_string(Action) ++ "~n"),
      Context#context{actions = NewActions}.
  
  %%%----------------------------------------------------------------------
  %%% Helper functions
  %%%----------------------------------------------------------------------
  
negative.code: %%%----------------------------------------------------------------------
  %%% Records
  %%%----------------------------------------------------------------------
  
  
  %% 'next' messages are about next instrumented instruction not yet dispatched
  