[SAL-HELP] Array of contexts

Bruno Dutertre bruno at csl.sri.com
Mon Jun 18 11:17:18 PDT 2007


Romek.Krisztian at stud.u-szeged.hu wrote:
> Hi,
> 
> Is there any way to declare an array of modules in SAL? Or if not, is  
> there any workaround other than copy-pasting?
> 
> Thanks in advance.
> 
> Chris
> 
> ----------------------------------------------------------------
> This message was sent using IMP, the Internet Messaging Program.
> 

Hello,

There are many examples of this in the ./examples directory
distributed with SAL. The way to do this is to have parameterized
modules. For example, check module job in the bakery.sal example.

Bruno

-------------- next part --------------
bakery{; N : nznat, B : nznat}: CONTEXT =
BEGIN
  Job_Idx: TYPE = [1..N];

  Ticket_Idx: TYPE = [0..B];

  Next_Ticket_Idx: TYPE = [1..(B + 1)];

  %% RSRC models the system resources
  RSRC: TYPE =  [# data: ARRAY Job_Idx OF Ticket_Idx,
                   next_ticket: Next_Ticket_Idx #];

  %% min_non_zero_ticket returns
  %% 0 - if the ticket of each job is 0
  %% n, where n is the minimal non zero ticket
  %% min_non_zero_ticket_aux is a recursive auxiliary function used
  %% by min_non_zero_ticket
  min_non_zero_ticket_aux(rsrc : RSRC, idx : Job_Idx) : Ticket_Idx =
   IF idx = N THEN rsrc.data[idx]
   ELSE LET curr: Ticket_Idx = rsrc.data[idx],
            rest: Ticket_Idx = min_non_zero_ticket_aux(rsrc, idx + 1)
        IN IF curr = 0 THEN rest
           ELSIF rest = 0 THEN curr
           ELSE min(curr, rest) 
           ENDIF 
   ENDIF;

  min_non_zero_ticket(rsrc : RSRC) : Ticket_Idx =
    min_non_zero_ticket_aux(rsrc, 1);

  %% return true if a job is allowed to enter the critical section
  can_enter_critical?(rsrc : RSRC, job_idx : Job_Idx): BOOLEAN =
    LET min_ticket: Ticket_Idx = min_non_zero_ticket(rsrc),
        job_ticket: Ticket_Idx = rsrc.data[job_idx]
    IN job_ticket <= min_ticket;

  %% the number of tickets was exhausted
  saturated?(rsrc : RSRC): BOOLEAN =
    rsrc.next_ticket = B + 1;

  %% when next_ticket is called by job_idx:
  %% - a new ticket is issued to job_idx, that is, the entry 
  %%    rsrc.data[job_idx] is updated with the value rsrc.next_ticket
  %% - the value of rsrc.next_ticket is incremented
  %% Remark: if rsrc is saturated, then return rsrc
  next_ticket(rsrc : RSRC, job_idx : Job_Idx): RSRC =
    IF saturated?(rsrc) THEN rsrc
    ELSE (rsrc WITH .data[job_idx] := rsrc.next_ticket)
               WITH .next_ticket := rsrc.next_ticket + 1
    ENDIF;

  %% reset a job ticket
  reset_job_ticket(rsrc : RSRC, job_idx : Job_Idx): RSRC =
    rsrc WITH .data[job_idx] := 0;

  %% the ticket counter can be reseted, if the ticket of
  %% each job is zero
  can_reset_ticket_counter?(rsrc : RSRC): BOOLEAN  =
    (FORALL (j : Job_Idx): rsrc.data[j] = 0);

  reset_ticket_counter(rsrc : RSRC): RSRC =
    rsrc WITH .next_ticket := 1;

  Job_PC: TYPE = {sleeping, trying, critical};


  job [job_idx : Job_Idx]: MODULE =
    BEGIN
      GLOBAL rsrc : RSRC
      LOCAL pc : Job_PC 
      INITIALIZATION 
        pc = sleeping
      TRANSITION
        [
         wakening: 
           (pc = sleeping) AND NOT(saturated?(rsrc))
           --> pc' = trying; 
               rsrc' = next_ticket(rsrc, job_idx)
         []
         entering_critical_section: 
           (pc = trying) AND can_enter_critical?(rsrc, job_idx)
           --> pc' = critical
         []
         leaving_critical_section: 
           pc = critical --> pc' = sleeping; 
                             rsrc' = reset_job_ticket(rsrc, job_idx)
        ]
    END;


  controller: MODULE =
    BEGIN
      GLOBAL rsrc : RSRC
      INITIALIZATION
        rsrc = (# data := [[j : Job_Idx] 0], next_ticket := 1#)
      TRANSITION
        [
          reseting_ticket_counter: 
            can_reset_ticket_counter?(rsrc)
            --> rsrc' = reset_ticket_counter(rsrc)
        ]
    END;

  system: MODULE =
     controller 
     [] 
     ([] (job_idx : Job_Idx): job[job_idx]);

  mutex: THEOREM system
                 |- G(NOT (EXISTS (i : Job_Idx, j : Job_Idx):
                             i /= j AND pc[i] = critical AND pc[j] = critical));

  %% invalid property
  liveness_bug: THEOREM system
                        |- (FORALL (i : Job_Idx): G(F(pc[i] = critical)));

  liveness: THEOREM system
                    |- (FORALL (i : Job_Idx):
                         G(pc[i] = trying => F(pc[i] = critical)));

  liveness2: THEOREM system
                     |- (FORALL (i : Job_Idx):
                          G(F(pc[i] = trying)) => G(F(pc[i] = critical)));

  aux: THEOREM system
               |- G((FORALL (i : Job_Idx):
                      (pc[i] = trying) => rsrc.data[i] > 0));
END


More information about the SAL-HELP mailing list