#define ERROR <=
#define NO_ERROR <
#define COMP NO_ERROR
#define N 4
byte pos0, pos1, pos2, pos3;
byte step0, step1, step2, step3;
bit inCS0, inCS1, inCS2, inCS3;

#define PROC(NAME, POS, INCS, ID)\
active proctype NAME()\
{\
byte j=0;\
byte k=0;\
NCS: if\
:: j = 1; goto wait;\
fi;\
CS: if\
:: atomic {POS = 0; INCS=0;} goto NCS;\
fi;\
wait: if\
::  atomic {j<N;POS = j;}  goto q2;\
::  atomic {j==N; INCS=1;} goto CS;\
fi;\
q2: if\
::  atomic\
{\
  if\
  :: j-1==0; step0 = ID;k = 0;\
  :: j-1==1; step1 = ID;k = 0;\
  :: j-1==2; step2 = ID;k = 0;\
  :: j-1==3; step3 = ID;k = 0;\
  fi;\
}  goto q3;\
fi;\
q3: if\
::  atomic\
{\
  if\
  :: k==0 && k<N && (k==ID || pos0 COMP j);k = k+1;\
  :: k==1 && k<N && (k==ID || pos1 COMP j);k = k+1;\
  :: k==2 && k<N && (k==ID || pos2 COMP j);k = k+1;\
  :: k==3 && k<N && (k==ID || pos3 COMP j);k = k+1;\
  fi;\
}  goto q3;\
::  atomic\
{\
  if\
  :: j-1==0 && (pos0!=ID || k==N);j = j+1;\
  :: j-1==1 && (pos1!=ID || k==N);j = j+1;\
  :: j-1==2 && (pos2!=ID || k==N);j = j+1;\
  :: j-1==3 && (pos3!=ID || k==N);j = j+1;\
  fi;\
}  goto wait;\
fi;\
}

PROC(P_0, pos0, inCS0, 0)

PROC(P_1, pos1, inCS1, 1)

PROC(P_2, pos2, inCS2, 2)

PROC(P_3, pos3, inCS3, 3)

never
{
again:
  if
  :: true; goto again;
  :: (inCS0 + inCS1 + inCS2 + inCS3)>1;
  fi;
}