Library mcertikos.mcslock.MMCSLockAbsIntroCSource


Require Import Coqlib.
Require Import AST.
Require Import Integers.
Require Import Values.
Require Import Cop.
Require Import Clight.
Require Import CDataTypes.
Require Import Ctypes.
Require Import GlobalOracle.

Local Open Scope positive_scope.

// macros only for MCS_LOCK
#define BUSY 1
#define FREE 0
#define INVALID_MCS_NODE TOTAL_CPU
#define TRUE 1
#define FALSE 0

// num of CPUs and procs
#define TOTAL_CPU 8

// macros for num of chans and num of cvs
#define READ_Q_START 0
#define MSG_Q_START (READ_Q_START + TOTAL_CPU) // 8
#define SLEEP_Q_START (MSG_Q_START + TOTAL_CPU) // 16
#define num_cv 255
#define TDQ_SIZE (SLEEP_Q_START + num_proc * num_cv + 1) // 16 + 64 * 255 + 1 = 16337
#define num_chan TDQ_SIZE // 16337

// macros for lock index
#define ID_AT 0
#define ID_TCB 1
#define ID_SC 2
#define ID_range 3
#define ID_AT_range 1
#define ID_TCB_range num_chan // 16337
#define ID_SC_range num_cv // 255
#define lock_TCB_range (ID_AT_range + ID_TCB_range) // 1 + 16337 = 16338
#define lock_range (ID_AT_range + ID_TCB_range + ID_SC_range) // 1 + 16337 + 255 = 16593
#define lock_AT_start 0
#define lock_TCB_start ID_AT_range // 1
#define lock_SC_start lock_TCB_range // 16338
#define WRONG 123456789

// defined in MBoot layer
extern void boot_loader(unsigned int mbi_adr);
extern unsigned int get_CPU_ID(void);

extern void mcs_init_node_log(unsigned int lock_index);
extern void mcs_init_node_log(unsigned int lock_index);
extern void mcs_GET_NEXT_log(unsigned int lock_index, unsigned int cpuid);
extern void mcs_SET_NEXT_log(unsigned int lock_index, unsigned int cpuid, unsigned int prev_id);
extern void mcs_GET_BUSY_log(unsigned int lock_index, unsigned int cpuid);
extern void mcs_SET_BUSY_log(unsigned int lock_index, unsigned int cpuid);

// defined in MMCSLockIntro layer
extern void mcs_init_node(unsigned int lock_index);
extern void mcs_log(unsigned int lock_index, unsigned int cpuid);
extern unsigned int mcs_GET_NEXT(unsigned int lock_index, unsigned int cpuid);
extern void mcs_SET_NEXT(unsigned int lock_index, unsigned int cpuid, unsigned int prev_id);
extern unsigned int mcs_GET_BUSY(unsigned int lock_index, unsigned int cpuid);
extern void mcs_SET_BUSY(unsigned int lock_index, unsigned int cpuid);
extern unsigned int mcs_SWAP_TAIL(unsigned int bound, unsigned int lock_index, unsigned int cpuid);
extern unsigned int mcs_CAS_TAIL(unsigned int lock_index, unsigned int cpuid);

// defined in MMCSAbsLockIntro layer
extern void mcs_lock_init(unsigned int mbi_adr);
extern unsigned int mcs_get_next(unsigned int lock_index, unsigned int cpuid);
extern void mcs_set_next(unsigned int lock_index, unsigned int cpuid, unsigned int prev_id);
extern unsigned int mcs_get_busy(unsigned int lock_index, unsigned int cpuid);
extern void mcs_set_busy(unsigned int lock_index, unsigned int cpuid);
extern unsigned int mcs_swap_tail(unsigned int bound, unsigned int lock_index, unsigned int cpuid);
extern unsigned int mcs_cas_tail(unsigned int lock_index, unsigned int cpuid);
extern unsigned int mcs_lock_get_index(unsigned int lock_id, unsigned int offset);

// Data Type 
typedef struct _mcs_node{
    unsigned int next;
    unsigned int busy;
}mcs_node;

typedef struct _mcs_lock{
    unsigned int last;
    mcs_node node_pool[TOTAL_CPU];
}mcs_lock;

mcs_lock MCS_LOCK_LOC[lock_range];


void
mcs_wait_lock(unsigned int bound, unsigned int lock_id, unsigned int offset)
{
    unsigned int lock_index, cpuid, prev_id, current_busy, busy_var;

    // pre-setting 
    lock_index = mcs_lock_get_index(lock_id, offset);
    cpuid = get_CPU_ID();
    prev_id = mcs_swap_tail(bound, lock_index, cpuid);

    if(prev_id == INVALID_MCS_NODE){
        return;
    } else {
        busy_var = BUSY;
        mcs_set_next(lock_index, cpuid, prev_id);
        
        // busy waiting
        current_busy = mcs_get_busy(lock_index, cpuid);
        while(current_busy == busy_var){
            current_busy = mcs_get_busy(lock_index, cpuid);
        }
        return;
    }
} 

void
mcs_pass_lock(unsigned int lock_id, unsigned int offset)
{
    unsigned int lock_index, cpuid, current_next, cas_res, null_var;

    // pre-setting
    lock_index = mcs_lock_get_index(lock_id, offset);
    cpuid = get_CPU_ID();
    cas_res = mcs_cas_tail(lock_index, cpuid);
    
    if(cas_res == 1){
        return;
    } else {
        null_var = INVALID_MCS_NODE;
        current_next = mcs_get_next(lock_index, cpuid);
        while (current_next == null_var){
            current_next = mcs_get_next(lock_index, cpuid);
        }
        mcs_set_busy(lock_index, cpuid);
        return;
    }
}

Definition _lock_id : positive := 11.
Definition _offset : positive := 12.
Definition _lock_index : positive := 13.
Definition _cpuid : positive := 14.
Definition _prev_id : positive := 15.
Definition _current_busy : positive :=16.
Definition _current_next : positive := 17.
Definition _cas_res : positive := 18.
Definition _null_var : positive := 19.
Definition _busy_var : positive := 20.
Definition _bound : positive := 21.


Definition f_mcs_wait_lock_while_condition :=
  (Ebinop Oeq (Etempvar _current_busy tuint)
          (Etempvar _busy_var tint) tint).

Definition f_mcs_wait_lock_while_body :=
  (Scall (Some _current_busy)
         (Evar mcs_get_busy (Tfunction
                               (Tcons tuint (Tcons tuint Tnil))
                               tuint cc_default))
         ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) :: nil)).

Definition f_mcs_wait_lock_body :=
  (Ssequence
     (Scall (Some _lock_index)
            (Evar mcs_lock_get_index (Tfunction (Tcons tuint (Tcons tuint Tnil))
                                                tuint cc_default))
            ((Etempvar _lock_id tuint) :: (Etempvar _offset tuint) :: nil))
     (Ssequence
        (Scall (Some _cpuid)
               (Evar get_CPU_ID (Tfunction Tnil tuint cc_default)) nil)
        (Ssequence
           (Scall (Some _prev_id)
                  (Evar mcs_swap_tail (Tfunction (Tcons tuint (Tcons tuint (Tcons tuint Tnil)))
                                                 tuint cc_default))
                  ((Etempvar _bound tuint) :: (Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) :: nil))
           (Sifthenelse (Ebinop Oeq (Etempvar _prev_id tuint)
                                (Econst_int (Int.repr TOTAL_CPU) tint) tint)
                        (Sreturn None)
                        (Ssequence
                              (Sset _busy_var (Econst_int (Int.repr 1) tint))
                              (Ssequence
                                 (Scall None
                                        (Evar mcs_set_next (Tfunction
                                                              (Tcons tuint
                                                                     (Tcons tuint (Tcons tuint Tnil))) tvoid
                                                              cc_default))
                                        ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) ::
                                                                      (Etempvar _prev_id tuint) :: nil))
                                 (Ssequence
                                    (Scall (Some _current_busy)
                                           (Evar mcs_get_busy (Tfunction
                                                                 (Tcons tuint (Tcons tuint Tnil)) tuint
                                                                 cc_default))
                                           ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) ::
                                                                         nil))
                                    (Ssequence
                                       (Swhile
                                          f_mcs_wait_lock_while_condition
                                          f_mcs_wait_lock_while_body)
                                       (Sreturn None))))))))).

Definition f_mcs_wait_lock :=
  {| fn_return := tvoid;
     fn_callconv := cc_default;
     fn_params := ((_bound, tuint)::(_lock_id, tuint) :: (_offset, tuint) :: nil);
     fn_vars := nil;
     fn_temps := ((_lock_index, tuint) :: (_cpuid, tuint) :: (_prev_id, tuint) ::
                                       (_busy_var, tuint) :: (_current_busy, tuint) :: nil);
     fn_body := f_mcs_wait_lock_body
  |}.


Definition f_mcs_pass_lock_while_condition :=
  (Ebinop Oeq (Etempvar _current_next tuint)
          (Etempvar _null_var tint) tint).

Definition f_mcs_pass_lock_while_body :=
  (Scall (Some _current_next)
         (Evar mcs_get_next (Tfunction
                               (Tcons tuint (Tcons tuint Tnil))
                               tuint cc_default))
         ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) :: nil)).

Definition f_mcs_pass_lock_body :=
  (Ssequence
     (Scall (Some _lock_index)
            (Evar mcs_lock_get_index (Tfunction (Tcons tuint (Tcons tuint Tnil))
                                                tuint cc_default))
            ((Etempvar _lock_id tuint) :: (Etempvar _offset tuint) :: nil))
     (Ssequence
        (Scall (Some _cpuid)
               (Evar get_CPU_ID (Tfunction Tnil tuint cc_default)) nil)
        (Ssequence
              (Scall (Some _cas_res)
                     (Evar mcs_cas_tail (Tfunction (Tcons tuint (Tcons tuint Tnil))
                                                   tuint cc_default))
                     ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) :: nil))
              (Sifthenelse (Ebinop Oeq (Etempvar _cas_res tuint)
                                   (Econst_int (Int.repr 1) tint) tint)
                           (Sreturn None)
                           (Ssequence
                              (Sset _null_var (Econst_int (Int.repr TOTAL_CPU) tint))
                              (Ssequence
                                 (Scall (Some _current_next)
                                        (Evar mcs_get_next (Tfunction (Tcons tuint (Tcons tuint Tnil))
                                                                      tuint cc_default))
                                        ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) ::
                                                                      nil))
                                 (Ssequence
                                    (Swhile
                                       f_mcs_pass_lock_while_condition
                                       f_mcs_pass_lock_while_body)
                                    (Ssequence
                                       (Scall None
                                              (Evar mcs_set_busy (Tfunction
                                                                    (Tcons tuint (Tcons tuint Tnil)) tvoid
                                                                    cc_default))
                                              ((Etempvar _lock_index tuint) :: (Etempvar _cpuid tuint) ::
                                                                            nil))
                                       (Sreturn None))))))))).

Definition f_mcs_pass_lock :=
  {| fn_return := tvoid;
     fn_callconv := cc_default;
     fn_params := ((_lock_id, tuint) :: (_offset, tuint) :: nil);
     fn_vars := nil;
     fn_temps := ((_lock_index, tuint) :: (_cpuid, tuint) :: (_current_next, tuint) ::
                                       (_cas_res, tuint) :: (_null_var, tuint) :: nil);
     fn_body := f_mcs_pass_lock_body
  |}.