PROMELA גרא וייס המחלקה למדעי המחשב אוניברסיטת בן-גוריון עדכון אחרון: 21:40 15/06/2013
2 שפת מ פ ר ט עם ס מ נ ט יק ה מוגדרת באופן מתמטי "שפת תכנות" למודלים המטרה: לאפשר גם לכאלה שאינם חוקרים בתחום לבנות מודל אותו ניתן יהיה לנתח באמצעות כלים פורמליים נקודה מרכזית: אנחנו דורשים שלמפרט תהיה ס מ נ ט יק ה פורמאלית! במקרה של :Promela ודרכה למערכת מעברים ס מ נ ט יק ה מוגדרת ע"י תרגום למערכת ערוצים לא ניתן להוכיח נכונות ללא ס מ נ ט יק ה פורמאלית מוגדרת ה יט ב
3 פקודות תנאי if :: g 1 ) stmt 1 :: :: g n ) stmt n fi בחירה לא דטרמיניסטית בין פקודות stmt i שהתנאים g i שלהן מתקיימים לצורך ה פ ש ט ות, נניח סמנטיקה של :test-and-set בדיקת התנאי + בחירת הפקודה + ביצוע הצעד האטומי הראשון של הפקודה מתבצעות באופן אטומי )זאת איננה הסמנטיקה של השפה ב- SPIN ( פקודת if-fi נתקעת אם אף אחד מהתנאים אינו מתקיים תהליכים מקבילים יכולים לשחרר את החסימה ע"י שינוי משתנים משותפים למשל: כאשר,y=0 הפקודה if :: y>0 ) x:=39 fi ממתינה ש y יהיה גדול מאפס קיצורים: if :: g)stmt 1 :: :g)stmt 2 fi שקול ל if g then stmt 1 else stmt 2 fi if :: g)stmt 1 :: :g)skip fi שקול ל if g then stmt 1 fi
4 פקודות לולאה do :: g 1 ) stmt 1 :: :: g n ) stmt n od ביצוע חוזר של כל הפקודות stmt i שתנאיהן g i מתקיימים אין תקיעה כשכל התנאים מ ופ ר ים - הלולאה מסתיימת. while g do stmt od ל שקול do :: g ) stmt od בגרסה המוקטנת אין פקודת break )יש בגרסה השלמה ב- SPIN ( ליציאה מלולאות
5 דוגמה: האלגוריתם של פטרסון : קוד עבור תהליך P 1 do :: true ) skip; /* Noncritical Section */ atomic { b 1 := true; x := 2 }; if :: (x=1) Ç :b 2 ) crit 1 := true fi; skip; /* Critical Section */ atomic { crit 1 := false; b 1 := false } od
6 דוגמה: מכונת מכירת משקאות do :: true ) skip; /* Coin Insertion */ od if :: nsprite > 0 ) nsprite := nsprite - 1 :: nbeer > 0 ) nbeer := nbeer - 1 :: nbeer = nsprite = 0 ) skip fi :: true ) atomic { nbeer := max; nsprite := max }
7 אימות אלגוריתם למניעה הדדית boolean array b(0;1) integer k, process i, with i either 0 or 1; C0: b(i) := false; C1: if k!= i then begin C2: if not (b(1-i)) then go to C2; else k := i; go to C1 end; else critical section; b(i) := true; remainder of program; go to C0; פרוטוקול שהוצע למניעה הדדית תרגום הפרוטוקול ל- PROMELA int cnt, k, b[2]; /* all variables are initially 0 */ active [2] proctype P() { assert(_pid == 0 _pid == 1); C0: b[_pid] = 0; C1: if :: (k!= _pid) -> C2: (b[1 - _pid]); /* wait for nonzero */ k = _pid; goto C1 } :: else -> cnt = cnt+1; assert(cnt == 1); /* critical section */ cnt = cnt-1; b[_pid] = 1; fi; goto C0
8 גילוי אוטומטי של טעות בפרוטוקול 1: proc 1 (P) line 5 "hy66" (state 1) [assert(((_pid==0) (_pid==1)))] 2: proc 1 (P) line 7 "hy66" (state 2) [b[_pid] = 0] 3: proc 1 (P) line 9 "hy66" (state 3) [((k!=_pid))] 4: proc 0 (P) line 5 "hy66" (state 1) [assert(((_pid==0) (_pid==1)))] 5: proc 0 (P) line 7 "hy66" 14: proc (state 12) (P)[b[_pid] line 11 = "hy66" 0] (state 5) [k = _pid] 6: proc 0 (P) line 14 "hy66" 15: proc (state 1 (P) 7) [else] line 14 "hy66" (state 7) [else] 7: proc 0 (P) line 15 "hy66" 16: proc (state 1 (P) 8) [cnt line = 15 (cnt+1)] "hy66" (state 8) [cnt = (cnt+1)] 8: proc 0 (P) line 16 "hy66" 17: proc (state 1 (P) 9) [assert((cnt==1))] line 16 "hy66" (state 9) [assert((cnt==1))] 9: proc 0 (P) line 17 "hy66" 18: proc (state 0 (P) 10) line [cnt = 15 (cnt-1)] "hy66" (state 8) [cnt = (cnt+1)] 10: proc 0 (P) line 19 "hy66" spin: line (state 16 "hy66", 11) [b[_pid] Error: = 1] assertion violated 11: proc 1 (P) line 10 "hy66" 19: proc (state 0 (P) 4) line [(b[(1-_pid)])] 16 "hy66" (state 9) [assert((cnt==1))] 12: proc 0 (P) line 7 "hy66" spin: trail (state ends 2) after [b[_pid] 19 steps = 0] 13: proc 0 (P) line 14 "hy66" #processes: (state 27) [else] cnt = 2 k = 1 b[0] = 0 b[1] = 0 19: proc 1 (P) line 17 "hy66" (state 10) 19: proc 0 (P) line 17 "hy66" (state 10) 2 processes created Reliable Design of Concurrent Software / Gerard Holzmann
9 חידה: גשר צר מאוד ארבעה חיילים צריכים לחצות גשר מהירויות החיילים: 5,10,20,25 דקות בהתאמה לכל היותר, שניים יכולים להיות על הגשר בו זמנית יש לפיד אחד מדובר בשעת לילה, הגשר צר מאוד, חייבים ללכת עם לפיד האם אפשר להעביר את כולם בתוך 60 דקות?
10 דוגמה: גשר צר מאוד #define FINISHED (where[0] == 1 && where[1] == 1 && where[2] == 1 && where[3] == 1) byte now = 0; byte time[4]; bit where[4]; bit torch; active proctype bridge() { byte i,j; time[0] = 5; time[1] = 10; time[2] = 20; time[3] = 25; do :: now <= 60 -> assert(!finished); if :: where[0] == torch -> i = 0 :: where[1] == torch -> i = 1 :: where[2] == torch -> i = 2 :: where[3] == torch -> i = 3 fi; if :: where[0] == torch -> j = 0 :: where[1] == torch -> j = 1 :: where[2] == torch -> j = 2 :: where[3] == torch -> j = 3 fi; where[i] = 1 - torch; where[j] = 1 - torch; torch = 1 - torch; now = now + MAX(time[i], time[j]) od }
11 סמנטיקה פורמאלית הסמנטיקה של פקודת Promela מעל Var, Chan ידי גרף תוכנית מעל Chan Var, מבוטאת על גרפי התוכנית PG 1,, PG n לתהליכי P 1,, P n מערכת ערוצים מעל Chan Var, פרומלה יוצרים דוגמה: cond_cmd = if :: x > 1 ) y := x + y fi :: true ) x := 0; y := x
12 דוגמה: גרף תוכנית למבנה תנאי cond_cmd = if :: x > 1 ) y := x + y fi :: true ) x := 0; y := x cond_cmd x>1 : y := x+y exit true : x := 0 y := x true : y := x
13 דוגמה: גרף תוכנית למבנה לולאה loop = do :: x > 1 ) y := x + y od :: y < x ) x := 0; y := x x > 1 : y := x + y y := x; loop true : y := x loop y < x : x := 0 :(x > 1) Æ :(y < x) exit
14 מקומות בגרף התוכנית = תת הפקודות מגדירים את המקומות בגרף התוכנית כתת הפקודות בתוכנית: Loc = sub(program) מקרה בסיס של ההגדרה ה ר ק ור ס יב ית: אם stmt {skip, x = expr, c?x, c!expr} מגדירים את תת הפקודות להיות: sub(stmt) = {stmt, exit} המשך ההגדרה, באופן ר ק ור ס יב י, בשקפים הבאים...
15 תת-פקודות של פקודות מורכבות הגדרות רקורסיביות sub(stmt 1 ; stmt 2 ) stmt ;stmt 2 : stmt sub stmt 1 exit sub(stmt 2 ) sub cond_cmd = if :: g 1 stmt 1 :: :: g n stmt n fi = cond_cmd sub stmt 1 sub(stmt n ) sub loop = do :: g 1 stmt 1 :: :: g n stmt n od = loop, exit stmt ;loop: stmt sub stmt i exit i=1,,n sub(atomic{stmt}) = {atomic{stmt}, exit}
16 כללי הסק בסיסיים מגדירים איך לחבר את הצמתים בגרף skip true : id! exit סימון: id אינה משנה את ערך המשתנים הפעולה x := expr true : assign(x;expr)! exit סימון: expr) assign(x, הפעולה משנה רק את x ומשאירה את ערך שאר המשתנים כמו שהוא c?x true : c?x! exit c!expr true : c!expr! exit
17 כללי הסק לקטע אטומי ולשרשור atomicfx 1 := expr 1 ; x m := expr m g true : m! exit α i = Effect(assign(x i, expr i ), Effect(α i 1, η)) באשר = id 0 וברקורסיה: g : stmt 1! stmt 0 1 ^ stmt 0 1 6= exit g : stmt 1 ; stmt 2! stmt 0 1 ; stmt 2 stmt 1 g :! exit stmt 1 ; stmt 2 g :! stmt 2
18 כללי הסק לתנאים וללולאות cond_cmd= if :: g 1 ) stmt 1 :: :: g n ) stmt n fi stmt i h :! stmt 0 i cond-cmd g i^h :! stmt 0 i loop= do :: g 1 ) stmt 1 :: :: g n ) stmt n od h : stmt i! stmt 0 i ^ stmt 0 i 6= exit stmt i loop g i^h :! stmt 0 i ; loop loop g i^h : h :! exit! loop loop :g 1^ ^:gh n : id! stmt i! exit loop loop g i^h :! loop
19 דוגמה cond_cmd = if :: x > 1 ) y := x + y fi :: true ) x := 0; y := x
20 דוגמה: תת הפקודות cond_cmd = if :: x > 1 ) y := x + y fi :: true ) x := 0; y := x cond_cmd y := x + y exit x := 0; y := x y := x
21 דוגמה: מעברים לפקודות השמה cond_cmd = if :: x > 1 ) y := x + y fi :: true ) x := 0; y := x true : y := x + y cond_cmd y := x + y exit x := 0; y := x y := x true : y := x
22 דוגמה: מעבר לפקודת הרכבה cond_cmd = if :: x > 1 ) y := x + y fi :: true ) x := 0; y := x true : y := x + y cond_cmd y := x + y exit x := 0; y := x true : x := 0 y := x true : y := x
23 דוגמה: מעברים לפקודת תנאי cond_cmd = if :: x > 1 ) y := x + y :: true ) x := 0; y := x fi x > 1 : y := x + y cond_cmd y := x + y true : y := x + y exit true : x := 0 x := 0; y := x true : x := 0 y := x true : y := x
24 Promela השפה מכילה מבנים נוספים שלא פרטנו: קטעים אטו מ י ים שלמים לא רק סדרות של השמות מערכים ומבני נתונים נוספים יצירה דינאמית של תהליכים ועוד... ה ס מ נ ט יק ה מוגדרת ע"י תרגום למערכות ערוצים ודרכן למערכות מעברים תיאור מלא של התחביר והסמנטיקה המלאים של Promela ב ס פ ר ות על SPIN )בשקף הבא( אפשר למצוא
25 מקורות נוספים ללימוד SPIN http://spinroot.com/spin/whatispin.html במעבדות המחלקה מותקנת התוכנה spin שהיא מימוש אלגוריתמי בדיקת המודל עצמם, והתוכנה ispin העוטפת את spin בממשק גרפי המאפשר קביעת פרמטרים באופן נוח ומציג את תוצאות הריצה בדרך שקל יותר להבין.