OS PyramidTechnion 234123 · Operating Systemsbasics → exam
the pyramid
Stage 6 / 10 · Core Mechanics

Synchronization & Threadshigh-yield

Synchronization is crucial for managing concurrent access to shared resources by multiple threads or processes, preventing race conditions, deadlocks, and ensuring data consistency. Understanding various synchronization primitives like mutexes, semaphores, and spinlocks, along with their properties and correct application, is fundamental. This topic is frequently tested to assess your ability to design and analyze concurrent systems for correctness and efficiency.

Where to learn it

lectureLecture 6–7
67 slides
Start with slides 2, 3, 4, 5, 6
tutorialTutorial 7 · threads
55 slides
tutorialTutorial 8 · synchronization
58 slides

How to study it

  • Master the properties and invariants of semaphores and mutexes, including their correct usage and common pitfalls.
  • Understand the mechanisms of spinlocks and interrupt disabling for synchronization, and their respective contexts of use.
  • Practice tracing code snippets involving synchronization primitives to identify race conditions, deadlocks, or verify correct concurrent execution.

What the exam asks

Exam questions often involve analyzing code for synchronization correctness (e.g., mutex_correctness), tracing semaphore operations to determine final states (semaphore_trace), or designing synchronization solutions for given concurrent problems.

The components, basic → advanced

These are the atomic skills this stage is built from. Learn them in this order — later ones assume the earlier ones.

L3 · applied
Local vs global interrupt disable
needs first: non preemptible kernel
L3 · applied
Spinlock implementation properties
needs first: interrupt disable
L3 · applied
Semaphore blocking and busy-wait
needs first: spinlock properties
L3 · applied
Mutex correctness and deadlock avoidance
needs first: semaphore properties
L4 · advanced
Semaphore invariant tracing
needs first: semaphore properties

Exam subsections in this stage (101 parts across 21 questions)

2018B_Spring_BQ2core13 parts here

סינכרוניזציה

  1. מימוש 1 (6 נק') 1· mcq· 1 pts

    struct mutex { int locked; // initialized to 0 } void lock(mutex* m) { while (m->locked == 1); // busy wait m->locked = 1; } void unlock(mutex* m) { m->locked = 0; } הקיפו בעיגול את התשובה הנכונה ונמקו או הפריכו. 1. האם המימוש מקיים את תכונת מניעה הדדית? כן \ לא נימוק:

    Spinlock implementation propertiesMutex correctness and deadlock avoidance
  2. מימוש 1 (6 נק') 2· mcq· 1 pts

    2. האם המימוש מקיים את תכונת אין קיפאון? נימוק:

    Process state transitions
  3. מימוש 1 (6 נק') 3· mcq· 1 pts

    3. האם המימוש מקיים את תכונת אין הרעבה? כן \ לא נימוק:

    Process state transitions
  4. מימוש 1 (6 נק') 4· mcq· 1 pts

    4. האם המימוש מקיים את תכונת המתנה חסומה (אם כן, יש לציין עבור איזה N)? כן \ לא נימוק:

    Process state transitions
  5. מימוש 2 (8 נק') 1· mcq· 2 pts

    הקיפו בעיגול את התשובה הנכונה ונמקו או הפריכו. 1. האם המימוש מקיים את תכונת מניעה הדדית? כן \ לא נימוק:

    Process state transitions
  6. מימוש 2 (8 נק') 2· mcq· 2 pts

    2. האם המימוש מקיים את תכונת אין קיפאון? כן \ לא נימוק:

    Process state transitions
  7. מימוש 2 (8 נק') 3· mcq· 2 pts

    3. האם המימוש מקיים את תכונת אין הרעבה? כן \ לא נימוק:

    Process state transitions
  8. מימוש 2 (8 נק') 4· mcq· 2 pts

    4. האם המימוש מקיים את תכונת המתנה חסומה (אם כן, יש לציין עבור איזה N)? כן \ לא נימוק:

    Process state transitions
  9. מימוש 3 (10 נק') 1· mcq· 2 pts

    הקיפו בעיגול את התשובה הנכונה ונמקו או הפריכו. 1. האם המימוש מקיים את תכונת מניעה הדדית? כן \ לא נימוק:

    Process state transitions
  10. מימוש 3 (10 נק') 2· mcq· 2 pts

    2. האם המימוש מקיים את תכונת אין קיפאון? כן \ לא נימוק:

    Process state transitions
  11. מימוש 3 (10 נק') 3· mcq· 2 pts

    3. האם המימוש מקיים את תכונת אין הרעבה? כן \ לא נימוק:

    Process state transitions
  12. מימוש 3 (10 נק') 4· mcq· 2 pts

    4. האם המימוש מקיים את תכונת המתנה חסומה (אם כן, יש לציין עבור איזה N)? כן \ לא נימוק:

    Process state transitions
  13. ב· short_answer· 6 pts

    נניח שהפעולות fetchAndInc i testAndSet הינן פעולות כבדות מבחינה חישובית, כלומר, פעולות אלו לוקחות זמן רב ביחס לפקודת מעבד רגילה, אך עדיין הן לוקחות פחות זמן מאשר החלפת הקשר בגרעין. ב. (6 נק') קים ג'ונג-און, רודן ידוע ומעצב שיער בהתהוות, ידוע בשל חיבתו לאטומיות ולכן החליט לבצע את המבחן הבא לבדיקת ביצועי מנעולים: 1. mutex m; 2. void* func(void* param) { 3. m.lock(); 4. m.unlock(); 5. return null; 6. } 7. 8. int main() { 9. m.init(); 10. pthread_t threads [5000];; 11. for (int i = 0 ; i < 5000 ; i++) { 12. 13. } 14. for (int i 15. pthread_create(threads + i, NULL, func, NULL); = 0; i < 5000; i++) { pthread_join(threads[i], NULL); 16. } 17. return 0; 18. } להפתעתו גילה קים כי עבור מנעול ממימוש 3 שהוצג לעיל, בממוצע התוכנית איטית באופן ניכר ביחס לשימוש במנעול mutex מסוג מהיר שנלמד בתרגולים. הסבירו לקים את התופעה (אבל בזהירות, הוא בחור עצבני...) הסבר:

    Voluntary vs preemptive context switchPipe IPC semanticsMutex correctness and deadlock avoidance
examB-spring2020Q3corecritical11 parts here

סנכרון

  1. 1.1· short_answer· 1 pts

    ייתכן מקרה בו הספר ישן ויש לקוחות שממתינים לתורם (נכון / לא נכון)

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  2. 1.2· short_answer· 1 pts

    ייתכן שלקוח יצא מהמספרה בלי להסתפר (נכון / לא נכון)

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  3. 1.3· short_answer· 1 pts

    במצב שיש יותר מספר אחד, ייתכן שאחד הספרים ישן כאשר יש מספר לקוחות (ממתינים + מסתפרים כעת) גדול ממספר הספרים (נכון / לא נכון)

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  4. 2.a· mcq· 1 pts

    (4 נק') בהתייחס לקוד הנ״ל, הקיפו את התשובות הנכונות הסבר a. קיימת בעיית נכונות עקב race condition למשאבים משותפים.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  5. 2.c· mcq· 1 pts

    c. הקוד משתמש ב-Busy Wait שפוגע בנצילות המעבד.

    Spinlock implementation properties
  6. 2.d· mcq· 1 pts

    d. הקוד מפר את כללי הכניסה לחדר ההמתנה (שהוגדרו בתחילת השאלה).

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  7. 3.a· mcq· 2 pts

    (8 נק') בהתייחס לקוד הנ״ל, הקיפו את התשובות הנכונות (בהתייחסות לספר יחיד) a. קיימת בעיית נכונות עקב race condition למשאבים משותפים.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  8. 3.c· mcq· 2 pts

    c. הקוד משתמש ב-Busy Wait שפוגע בנצילות המעבד.

    Spinlock implementation properties
  9. 3.d· mcq_with_explanation· 2 pts

    d. הקוד מפר את כללי הכניסה לחדר ההמתנה (שהוגדרו בתחילת השאלה). הסבירו, והדגימו באמצעות תרחישים אפשריים.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  10. 4· short_answer· 5 pts

    (5 נק') הציעו דרך פשוטה לתקן את הקוד (תיאור מילולי - בהתייחסות לספר אחד)

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
  11. 5· short_answer· 5 pts

    (5 נק') סאמי שם לב שהקוד הנ"ל (מסעיף ג) לא עובד כמו שצריך ולכן עבד קשה לתקן אותו. לאחר שהוא תיקן את כל הבעיות שיש בקוד, הוא שם לב שהקוד המתוקן עדיין לא עובד במקרה של יותר מספר אחד. תארו תרחיש בעייתי שקורה רק במצב שיש יותר מספר אחד (בעיה שלא הוזכרה קודם) ואיך לתקן אותו.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSRT / preemptive Gantt construction
2018A_Winter_BQ1core8 parts here

חלק 1 - סינכרון

  1. 1· mcq· 7 pts

    (7 נק') לקוד זה 7 אופציות להדפסה מתוך ה-15 הבאות. יש להקיף את האופציות הנכונות. אין צורך להסביר את פתרונכם. כלום Andrey Leonid Sasha Andrey Leonid Andrey Sasha Sasha Leonid Andrey Andrey Andrey Leonid Sasha Sasha Andrey Leonid Leonid Sasha Leonid Andrey Leonid Sasha Andrey Sasha Andrey Leonid Andrey Sasha Leonid

    Voluntary vs preemptive context switchlibc syscall wrapper caching pitfallsSignal delivery and handler timing
  2. 2· mcq· 6 pts

    (6 נק') הקוד של אחינועם בעייתי כאשר מספר חוטים משתמשים במחלקה במקביל. סמנו את כל התשובות הנכונות (תיתכן יותר מאחת) מהתשובות הבאות: a. הקוד בזבזני בגלל שמבצע Busy Wait לשווא b. השימוש במחלקה יכול לגרום ל-Deadlock c. יתכן Race condition אם החוטים קוראים לפונקציה plusOne במקביל d. יתכן Race condition אם החוטים קוראים לפונקציות getVal ו-plusOne במקביל e. יתכן Race condition אם החוטים קוראים לפונקציות doubleVal ו-getVal במקביל f. בקוד זה תתכן הרעבה של כותבים g. בקוד זה תתכן הרעבה של קוראים

    Pipe IPC semanticsSpinlock implementation propertiesMutex correctness and deadlock avoidanceBanker's algorithm safety check
  3. נימוק סעיף 2· short_answer

    הסבירו רק על הבעיות שסימנתם, ללא התייחסות לסעיפים שלא סומנו.

    Voluntary vs preemptive context switchlibc syscall wrapper caching pitfallsSignal delivery and handler timing
  4. 3· mcq· 6 pts

    (6 נק') הקוד החדש של אחינועם עדיין בעייתי. סמנו את כל התשובות הנכונות (תיתכן יותר מאחת) מהתשובות הבאות: a. הקוד בזבזני בגלל שמבצע Busy Wait לשווא b. השימוש במחלקה יכול לגרום ל-Deadlock c. יתכן Race condition אם החוטים קוראים לפונקציה plusOne במקביל d. יתכן Race condition אם החוטים קוראים לפונקציות getVal ו-plusOne במקביל e. יתכן Race condition אם החוטים קוראים לפונקציות doubleVal ו-getVal במקביל f. בקוד זה תתכן הרעבה של כותבים g. בקוד זה תתכן הרעבה של קוראים

    Pipe IPC semanticsSpinlock implementation propertiesMutex correctness and deadlock avoidanceBanker's algorithm safety check
  5. נימוק סעיף 3· short_answer

    הסבירו רק על הבעיות שסימנתם, ללא התייחסות לסעיפים שלא סומנו.

    Voluntary vs preemptive context switchlibc syscall wrapper caching pitfallsSignal delivery and handler timing
  6. 4· mcq· 6 pts

    (6 נק') בקוד הנתון בעיה חמורה בעת שימוש במחלקה זו ע"י מספר חוטים במקביל. סמנו את כל התשובות הנכונות (תיתכן יותר מאחת) מהתשובות הבאות: a. הקוד בזבזני בגלל שמבצע Busy Wait לשווא b. השימוש במחלקה יכול לגרום ל-Deadlock c. יתכן Race condition אם החוטים קוראים לפונקציה plusOne במקביל d. יתכן Race condition אם החוטים קוראים לפונקציות getVal ו-plusOne במקביל e. יתכן Race condition אם החוטים קוראים לפונקציות doubleVal ו-getVal במקביל f. בקוד זה תתכן הרעבה של כותבים g. בקוד זה תתכן הרעבה של קוראים

    Pipe IPC semanticsSpinlock implementation propertiesMutex correctness and deadlock avoidanceBanker's algorithm safety check
  7. נימוק סעיף 4· short_answer

    הסבירו רק על הבעיות שסימנתם, ללא התייחסות לסעיפים שלא סומנו.

    Voluntary vs preemptive context switchlibc syscall wrapper caching pitfallsSignal delivery and handler timing
  8. 5· short_answer· 5 pts

    (5 נק') שימו לב: בסעיף זה נתייחס לנכונות הפונקציה getVal בלבד. נביט בסעיף זה על המימוש הראשוני מסעיף (ב). המהנדס הנודע (וחובב הטחינה המושבע) איליה טען שאין צורך במנעול בפונקציה getVal, והציע מימוש חדש לפונקציה getVal: מימוש קודם int getVal() { int ret_val; mutex_lock(&m); ret_val = val; mutex_unlock(&m); return ret_val; } מימוש חדש מוצע int getVal() { return val; } בהנחה שהמשתנה val יכול להיקרא ולהיכתב במקביל בפונקציות אחרות בקוד ע"י מספר חוטים, כתבו במשפט אחד את התנאי לכך שהמימוש שאיליה הציע יהיה נכון: הסבירו:

    Pipe IPC semanticsMutex correctness and deadlock avoidance
examA-spring2020_mergedQ2core7 parts here

סינכרון

  1. 1· mcq· 1 pts

    (1 נק') יכולים להיות שני סטודנטים מפקולטות שונות באותו חדר במקביל: נכון / לא נכון

    Signal delivery and handler timingMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
  2. 2· mcq· 1 pts

    (1 נק') יכולים להיות שני סטודנטים מפקולטות זהות בחדר במקביל: נכון / לא נכון

    Signal delivery and handler timingMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
  3. 3· mcq· 1 pts

    (1 נק') סטודנטי פקולטה אחת עלולים להרעיב (כניסת) סטודנטי פקולטה אחרת: נכון / לא נכון

    Signal delivery and handler timingMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
  4. 4· mcq· 8 pts

    (8 נק') בהתייחס לקוד הנ״ל, הקיפי את כל התשובות הנכונות (עשויה להיות יותר מאחת). עבור כל תשובה שהקפת, תארי דוגמת הרצה המובילה לתשובה זו. a. קיימת בעיית נכונות עקב condition race למשאבים משותפים. b. קיימת בעיית Livelock / DeadLock בקוד. c. הקוד משתמש ב-Wait Busy שפוגע בנצילות המעבד. d. הקוד מפר את כלל הכניסה לחדר (שהוגדר בתחילת השאלה). נימוק:

    Mutex correctness and deadlock avoidanceBanker's algorithm safety check
  5. 5· short_answer· 4 pts

    אך דני (עתודאי במדמ"ח) טען שקוד זה גורם לחוטים להתעורר שלא לצורך ומיד לחזור למצב המתנה. (4 נק') הסבירי את טענתו של דני באמצעות דוגמת ריצה קונקרטית.

    Pipe IPC semantics
  6. 6· short_answer· 5 pts

    (5 נק') כיצד ניתן לתקן את הבעיה שהציג דני בסעיף הקודם? נימוק:

    Signal delivery and handler timingMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
  7. 7· mcq· 8 pts

    (8 נק') בהתייחס לקוד הנ״ל, הקיפי את כל התשובות הנכונות (עשויה להיות יותר מאחת). עבור כל תשובה שהקפת, תארי דוגמת הרצה המובילה לתשובה זו. a. יתכנו 2 סטודנטים מפקולטות שונות בתוך החדר ביחד, עקב race condition למשאב משותף. b. יתכן סטודנט שלא נכנס לחדר למרות כלל הכניסה שמתיר זאת, עקב race condition למשאב משותף. c. קיימת בעיית DeadLock / Livelock בקוד. d. סיגנלים עלולים ללכת לאיבוד. נימוק:

    Signal delivery and handler timingMutex correctness and deadlock avoidanceBanker's algorithm safety check
OS-Spring2021-examBQ4core6 parts here

סנכרון (Synchronization)

  1. a· short_answer· 4 pts

    הסבירו את המונחים הבאים בקצרה: a. קטע קריטי b. מניעה הדדית c. Race condition d. Deadlock

    Mutex correctness and deadlock avoidanceBanker's algorithm safety check
  2. b· mcq· 4 pts

    בהינתן קטעי הקוד משני חוטים (X ו-Y משתנים בוליאניים משותפים שמאותחלים באופן רנדומלי לפני שהחוטים מגיעים לקטעי קוד הבאים): Thread1: while (X == Y); // critical section X = Y; Thread 2: while(X != Y); // critical section X = !Y; אילו מהטיעונים הבאים נכון: a. הקוד מבטיח מניעה הדדית, אבל לא מבטיח ״התקדמות" (progress). b. הקוד מבטיח התקדמות, אבל לא מבטיח מניעה הדדית. c. הקוד לא מבטיח התקדמות ולא מבטיח מניעה הדדית. d. הקוד מבטיח מניעה הדדית והתקדמות. נימוק:

    Pipe IPC semantics
  3. c· code· 4 pts

    להלן הצעה למימוש מנעול: המשתנה L משתנה מסוג int שמאותחל ל- 0, הפונקציה (fetch_and_add(x,c מבצעת את הפעולות הבאות באופן אטומי: קוראת ערך המשתנה x, מוסיפה אליו c ומחזירה את הערך לפני ההוספה. lock(L) { while (fetch_and_add(L, 1)) { L = 1; } } unlock(L) { L = 0; } האם המימוש הנ"ל עובד? כן / לא הסבירו בקצרה (אם המימוש לא עובד, תארו תרחיש בעייתי): נימוק:

    Mutex correctness and deadlock avoidance
  4. d· code· 4 pts

    בהינתן השינוי הבא בקוד מסעיף קודם: lock(L) { while (fetch_and_add(L, 1)); } unlock(L) { L = 0; } האם המימוש החדש עובד? כן / לא הסבירו בקצרה (אם המימוש לא עובד, תארו תרחיש בעייתי): נימוק:

    libc syscall wrapper caching pitfallsSpinlock implementation propertiesSemaphore blocking and busy-wait
  5. e· mcq· 3 pts

    יונתן, סטודנט לקורס מערכות הפעלה מימש מנעול חדש שתומך בשתי הפעולות הבאות: struct my_lock { unsigned int value = 0; }; void lock (struct my_lock *s) { unsigned int y; unsigned int *x = &(s->value); do { fetch_and_set(x, &y); } while (y); } void unlock (struct my_lock *s) { s->value = 0; } כאשר (fetch_and_set(x,y פעולה אטומית שמעדכנת את הערך ש- x מצביע עליו ל- 1, ושומרת את הערך הקודם בתוך המשתנה y. א ) אילו מהטיעונים הבאים נכון: 1. הקוד לא מבטיח מניעה הדדית. 2. המנעול עובד באופן תקין. 3. במערכת מרובת מעבדים, הקוד עלול ליצור deadlock. 4. במערכת מרובת מעבדים, הקוד לא מבטיח מניעה הדדית. נימוק:

    libc syscall wrapper caching pitfallsMutex correctness and deadlock avoidanceBanker's algorithm safety check
  6. f· short_answer· 2 pts

    ב) בהנחה שהמנעול הנ"ל עובד (תוקן במידת הצורך), משיקולי יעילות, באיזה מרחב (גרעין או משתמש) עדיף להשתמש במנעול כזה? גרעין / משתמש נימוק:

    fork/exec address-space semanticsMutex correctness and deadlock avoidance
2017B_Spring_BQ3core5 parts here

סנכרון

  1. א· code· 4 pts

    (4 נק') בניסיון הראשון כתב אוהד את הקוד הבא: int done; void initialize() { done = 0; } void* first(void* p) { printf("I should run first.\n"); done = 1; return NULL; } void* second(void* p) { while (!done); printf("I should run second.\n"); return NULL; } void finalize() { } דנית טענה ללא היסוס כי הקוד של אוהד אמנם נכון, אבל בזבזני. הסבירו את טענתה של דנית.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingSemaphore blocking and busy-wait
  2. ב· code· 5 pts

    (5 נק') דנית הציעה להשתמש במשתנה תנאי ומנעול mutex כדי לפתור את הבעיה שהייתה בקוד של אוהד: pthread_cond_t c; pthread_mutex_t m; void initialize() { pthread_mutex_init(&m, NULL); pthread_cond_init(&c, NULL); } void* first(void* p) { printf("I should run first.\n"); pthread_cond_signal(&c); return NULL; } void* second(void* p) { pthread_mutex_lock(&m); pthread_cond_wait(&c, &m); pthread_mutex_unlock(&m); printf("I should run second.\n"); return NULL; } void finalize() { pthread_mutex_destroy(&m); pthread_cond_destroy(&c); } למרבה הצער, אוהד הבחין מיד כי הפתרון של דנית שגוי. תארו בפירוט מדוע הקוד שגוי, כלומר תארו תרחיש מסוים שבו הקוד של דנית לא יפעל כנדרש.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingPipe IPC semanticsMutex correctness and deadlock avoidance
  3. ג· code· 5 pts

    (5 נקודות) אוהד ודנית לא התייאשו והציעו פתרון שלישי לבעיה: pthread_cond_t c; pthread_mutex_t m; int done; void initialize() { done = 0; pthread_mutex_init(&m, NULL); pthread_cond_init(&c, NULL); } void* first(void* p) { printf("I should run first.\n"); done = 1; pthread_cond_signal(&c); return NULL; } void* second(void* p) { pthread_mutex_lock(&m); while (!done) { pthread_cond_wait(&c, &m); } pthread_mutex_unlock(&m); printf("I should run second.\n"); return NULL; } void finalize() { pthread_mutex_destroy(&m); pthread_cond_destroy(&c); } אך שוב אוהד ודנית התאכזבו כאשר המתרגל רמז להם כי הפתרון הנ"ל שגוי. תארו בפירוט מדוע הקוד שגוי, כלומר תארו תרחיש מסוים שבו הקוד הנ"ל לא יפעל כנדרש.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingPipe IPC semanticsMutex correctness and deadlock avoidance
  4. ד· code· 6 pts

    (6 נקודות) השלימו את המימוש המוצע מטה, תוך שימוש במשתנה תנאי יחיד ומנעול mutex יחיד. pthread_cond_t c; pthread_mutex_t m; int done; void initialize() { done = 0; pthread_mutex_init(&m, NULL); pthread_cond_init(&c, NULL); } void* first(void* p) { printf("I should run first.\n"); return NULL; } void* second(void* p) { printf("I should run second.\n"); return NULL; } void finalize() { pthread_mutex_destroy(&m); pthread_cond_destroy(&c); }

    Pipe IPC semanticsMutex correctness and deadlock avoidance
  5. ה· code· 5 pts

    (5 נקודות) הציעו מימוש תקין העושה שימוש בסמפור יחיד. sem_t s; void initialize() { sem_init(&s, 0, ); /* the 3rd argument is the initial value */ } void* first(void* p) { printf("I should run first.\n"); } return NULL; void* second(void* p) { } printf("I should run second.\n"); return NULL; void finalize() { sem_destroy(&s); } הסבר:

    Semaphore blocking and busy-wait
2018B_Spring_BQ3core5 parts here

חוטים

  1. 1· mcq· 5 pts

    (5 נק') אילו אובייקטים הם ייחודיים לכל חוט (כלומר מוקצים בנפרד לכל אחד מהחוטים של אותו תהליך)? .a הערימה (heap) b. מחסנית המשתמש (user stack). c. הקוד של התכנית (text section). d. טבלת הקבצים הפתוחים (file descriptor table) e. טבלת הדפים (page table) f. מתאר מרחב הזיכרון (memory descriptor) נמקו:

    fork/exec address-space semanticsPipe IPC semanticsVirtual-to-physical address translation
  2. 2· mcq· 5 pts

    (5 נק') מה תדפיס התוכנית? (A1)(B1) .a (A1)(A2)(v=1).b (A1)(A2)(v=1)(B1)(B2)(v=2) .C (A1)(B1)(A2)(v=3) .d (A1)(B1)(A2)(v=2)(B2)(v=1) .е (A1)(B1)(A2)(v=3)(B2)(v=1) .f נמקו:

    pthread create/cancel/join lifecyclePipe IPC semanticsMutex correctness and deadlock avoidance
  3. 3· code· 5 pts

    (5 נק') ספריית ULTL שומרת את הקשרי הביצוע של החוטים במערך גלובאלי בגודל N: jmp_buf g_buf[N]; החלפת הקשר בין חוטים של אותו תהליך מתבצעת ע"י קריאה לפונקציה context_switch אשר מקבלת שני פרמטרים: prev - מזהה החוט הנוכחי, next - מזהה החוט הבא לביצוע. מה המימוש הנכון של הפונקציה context_switch? void context_switch(int prev, int next){ a. b. if(setjmp(g_buf[prev]) == 0) if(setjmp(g_buf[prev]) == 1) longjmp(g_buf[next], 1); longjmp(g_buf[next], 1); c. d. if(setjmp(g_buf[next]) == 0) if(setjmp(g_buf[next]) == 1) longjmp(g_buf[prev], 1); longjmp(g_buf[prev], 1); e. f. longjmp(g_buf[next], 1); setjmp(g_buf[prev]); setjmp(g_buf[prev]); longjmp(g_buf[next], 1); } נמקו:

    Voluntary vs preemptive context switchPipe IPC semantics
  4. 4· mcq· 5 pts

    (5 נק') מה היתרונות של ספריית ULTL על-פני pthreads a. ניתן להריץ חוטים שונים של אותו תהליך על מעבדים שונים בו-זמנית. b. ביצוע של חוט לא יכול להיקטע ע"י פסיקת חומרה. c. החלפת הקשר בין חוטים של אותו תהליך היא זולה יותר כי אין צורך לחמם מטמונים. d. החלפת הקשר בין חוטים של אותו תהליך היא זולה יותר כי לא מחליפים טבלת דפים. e. קבצים שנפתחו ע"י חוט אחד יהיו נגישים גם לשאר החוטים באותו תהליך. f. הספריה פורטבילית, כלומר ניתן להדר את הקוד כמו שהוא על מערכות הפעלה שונות. נמקו:

    Voluntary vs preemptive context switchLocal vs global interrupt disablePipe IPC semanticsPreemption trigger identification
  5. 5· mcq· 5 pts

    (5 נק') מה היתרונות של ספריית pthreads על-פני ULTL? a. ניתן להריץ חוטים שונים של אותו תהליך על מעבדים שונים בו-זמנית. b. ביצוע של חוט לא יכול להיקטע ע"י פסיקת חומרה. c. החלפת הקשר בין חוטים של אותו תהליך היא זולה יותר כי אין צורך לחמם מטמונים. d. החלפת הקשר בין חוטים של אותו תהליך היא זולה יותר כי לא מחליפים טבלת דפים. e. קבצים שנפתחו ע"י חוט אחד יהיו נגישים גם לשאר החוטים באותו תהליך. f. הספריה פורטבילית, כלומר ניתן להדר את הקוד כמו שהוא על מערכות הפעלה שונות. נמקו:

    Voluntary vs preemptive context switchLocal vs global interrupt disablePipe IPC semanticsPreemption trigger identification
OS-Winter2022-examBQ3core5 parts here

תכנות מקבילי

  1. 1· mcq· 4 pts

    1. (4 נק) האם הקוד הבא ממש מנעול מסוג spin lock ? (כל החוטים ניגשים לאותו משתנה גלובלי lock) 01 int32 lock = 0; // initially the lock is free 02 03 void lock() { 04 while (CAS(&lock, 0, 1) == true); 05 } 06 07 void unlock() { 08 lock = 1; 09 } a. כן b. לא, כי זה מממש spinlock ולא wait lock c. לא, כי הערך המצופה (expectedValue) של CAS בשורה 4 צריך להיות 1 ולא 0 d. לא, כי צריך השמה של 0 ולא 1 בשורה 8 e. תשובות d ו-c נכונות f. אף תשובה לא נכונה נימוק:

    Pipe IPC semanticsSpinlock implementation propertiesMutex correctness and deadlock avoidance
  2. 2· mcq· 5 pts

    2. (5 נק) האם הקוד הבא ממש מנעול מסוג spin lock ? (כל החוטים ניגשים לאותו משתנה גלובלי lock) 01 int32 lock = 0; // initially the lock is free 02 03 void lock() { 04 while (CAS(&lock, 0, 1) == true); 05 } 06 07 void unlock() { 08 lock = 0; 09 } a. כן b. לא, כי זה מממש spinlock ולא wait lock c. לא, כי הערך המצופה (expectedValue) של CAS בשורה 4 צריך להיות 1 ולא 0 d. לא, כי צריך השמה של 1 ולא 0 בשורה 8 e. לא, כי צריך memory fence לפני ואחרי שורה 8 או השמה דרך פקודת מכונה אטומית בשורה 8 f. תשובות d ו-c נכונות g. אף תשובה לא נכונה נימוק:

    Pipe IPC semanticsSpinlock implementation propertiesMutex correctness and deadlock avoidance
  3. 3· mcq· 6 pts

    3. (6 נק) האם הקוד הבא מממש מחסנית מקבילית (concurrent lock-free stack) תקינה? (כל החוטים ניגשים לאותו משתנה גלובלי top) 01 typedef struct node { 02 int data; 03 Struct node* next; 04 } Node; 05 06 Node* top = NULL; 07 08 void push(int newData) { 09 // assume correctness and success of the following allocation 10 Node* newNode = allocateNewNodeWithData(newData); 11 Node* expectedTopNode; 12 do { 13 expectedTopNode = top; 14 newNode.next = expectedTopNode; 15 } while (!CAS(&top, expectedTopNode, newNode)); 16 } a. כן b. לא, כי newNode.next זה משתנה שנמצא בערימה ולכן ערכו עלול להשתנות c. לא, כי צריך memory fence לפחות במקום אחד d. לא, כי יכולה להיות החלפת הקשר בזמן ביצוע פקודת CAS e. לא, כי יכולה להיות החלפת הקשר בין השורות 13 ו-14 f. אף תשובה לא נכונה נימוק:

    Voluntary vs preemptive context switchPipe IPC semanticsSRT / preemptive Gantt construction
  4. 4· mcq· 5 pts

    4. (5 נק) סטודנט אחד טוען שאפשר לא להשתמש במשתנה expectedTopNode וכך לחסוך בזיכרון. האם הקוד הבא ממש מחסנית מקבילית (concurrent lock-free stack) תקינה? (כל החוטים ניגשים לאותו משתנה גלובלי top) 01 typedef struct node { 02 int data; 03 Struct node* next; 04 } Node; 05 06 Node* top = null; 07 08 void push(int newData) { 09 // assume correctness and success of the following allocation 10 Node* newNode = allocateNewNodeWithData(newData); 11 do { 12 newNode.next = top; 13 } while (!CAS(&top, top, newNode)); 14 } a. כן, בכל מקרה הערך של expectedTopNode נלקח מ-top b. לא, כי newNode.next זה משתנה שנמצא בערימה ולכן ערכו עלול להשתנות c. לא, כי צריך memory fence לפחות במקום אחד d. לא, כי יכולה להיות החלפת הקשר בזמן ביצוע פקודת CAS e. לא, כי יכולה להיות החלפת הקשר בין השורות 12 ו-13 f. אף תשובה לא נכונה נימוק:

    Voluntary vs preemptive context switchPipe IPC semanticsSRT / preemptive Gantt construction
  5. 5· mcq· 5 pts

    5. (5 נק) סטודנטית אחת טוענת שאפשר לא להשתמש במשתנה expectedTopNode וכך לחסוך בזיכרון, אבל עושה את זה באופן אחר. האם הקוד הבא ממש מחסנית מקבילית (concurrent lock-free stack) תקינה? (כל החוטים ניגשים לאותו משתנה גלובלי top) 01 typedef struct node { 02 int data; 03 Struct node* next; 04 } Node; 05 06 Node* top = null; 07 08 void push(int newData) { 09 // assume correctness and success of the following allocation 10 Node* newNode = allocateNewNodeWithData(newData); 11 do { 12 newNode.next = top; 13 } while (!CAS(&top, newNode.next, newNode)); 14 } a. כן b. לא, כי newNode.next זה משתנה שנמצא בערימה ולכן ערכו עלול להשתנות c. לא, כי צריך memory fence לפחות במקום אחד d. לא, כי יכולה להיות החלפת הקשר בזמן ביצוע פקודת CAS e. לא, כי יכולה להיות החלפת הקשר בין השורות 12 ו-13 f. אף תשובה לא נכונה נימוק:

    Voluntary vs preemptive context switchPipe IPC semanticsSRT / preemptive Gantt construction
2018A_Winter_AQ4core4 parts here

חלק 4 - סינכרוניזציה

  1. 15· mcq· 6 pts

    (6 נק') איזה תכונות מתקיימות עבור spinlock כפי שנלמד בהרצאה? a. A בלבד b. B בלבד c. C בלבד d. A,B בלבד e. A,C בלבד f. B,C בלבד

    Spinlock implementation properties
  2. 16· mcq· 6 pts

    (6 נק') איזה תכונות מתקיימות עבור semaphore כפי שנלמד בהרצאה? a. A בלבד b. B בלבד c. C בלבד d. A,B בלבד e. A,C בלבד f. B,C בלבד

    Semaphore blocking and busy-wait
  3. 18· mcq· 6 pts

    (6 נק') האם הטענה של ליאוניד נכונה? a. הטענה נכונה. שורה זו הכרחית רק במערכת מרובת ליבות כדי למנוע deadlock. b. הטענה נכונה. שורה זו הכרחית רק במערכת מרובת ליבות כדי להבטיח מניעה הדדית. c. הטענה נכונה. שורה זו הכרחית רק במערכת מרובת ליבות כדי להבטיח סדר ביצוע נכון. d. הטענה שגויה. ללא שורה זו שימוש במנעול עלול לגרום ל-deadlock. e. הטענה שגויה. ללא שורה זו המנעול לא מבטיח מניעה הדדית. f. הטענה שגויה. ללא שורה זו המעבד עלול לבצע את הפקודות בסדר לא נכון.

    libc syscall wrapper caching pitfallsMutex correctness and deadlock avoidanceBanker's algorithm safety check
  4. 19· mcq· 6 pts

    (6 נק') האם שורה 2 צריכה לבטל את הפסיקות מקומית (רק בליבת המעבד הנוכחית) או גלובאלית (בכל הליבות במערכת)? a. מקומית, כי אחרת יהיה deadlock. b. מקומית, כדי לשפר את הביצועים. c. מקומית, אחרת המנעול לא יבטיח מניעה הדדית. d. גלובאלית, כי אחרת יהיה deadlock. e. גלובאלית, כדי לשפר את הביצועים. f. גלובאלית, אחרת המימוש לא מבטיח שהמעבד יבצע את הפקודות בסדר הנכון.

    libc syscall wrapper caching pitfallsLocal vs global interrupt disableMutex correctness and deadlock avoidanceBanker's algorithm safety check
2017B_Spring_AQ4core4 parts here

סנכרוניזציה

  1. א· short_answer· 5 pts

    (5 נק') האם המימוש הנ"ל נכון? (כלומר אכן תומך בהפרדה הדדית עבור המשתנה המשותף X?) נמקו.

    fork/exec address-space semanticslibc syscall wrapper caching pitfallsSRT / preemptive Gantt construction
  2. ב· short_answer· 5 pts

    (5 נק') לדעת דני, הקוד נכון במערכת שהינה בעלת ליבת מעבד יחידה. האם הוא צודק? נמקו.

    libc syscall wrapper caching pitfalls
  3. ד· short_answer· 5 pts

    (5 נק') האם המחשב של דני היה נתקע אילו היינו משתמשים בסמפור במקום ב-spinlock? (כלומר, חישבו על aux_lock-כסמפור והחליפו את הקריאות ל-spin_lock/spin_unlock ב-sem_down/sem_up?)

    Spinlock implementation propertiesSemaphore blocking and busy-wait
  4. ה· code· 5 pts

    כעת נדון בקוד שונה במעט אשר משתמש בשני המאקרו-ים הבאים: • cond_wait - מקבל שלושה פרמטרים: (i) תור המתנה, (ii) משתנה mutex המספק מניעה הדדית, ו- (iii) תנאי בולאני. פעולתו של cond_wait היא אטומית: הוא בודק את התנאי הבוליאני ואם התנאי מתקיים משחררים את ה- mutex ונכנסים להמתנה (בשינה) על התור. כאשר cond_wait חוזרת, מתבצעת נעילה mutex-חוזרת של ה • cond_signal - מקבל תור המתנה ומעיר תהליך יחיד מתור זה. המימוש הבא יוצר מנעול תקין: Mutex m; int sys_global_lock() { lock(m); while (global_lock != 0) { cond_wait(global_queue, m, (global_lock!=0)); } unlock(m); } int sys_global_unlock() { lock(m); global_lock=0; //Free lock cond_signal(global_queue); //Wakes a single process waiting in uni_queue unlock(m); } דנה שמה לב שעל אף שהמימוש תקין, לעתים הוא עלול לגורם למצבי קיפאון בעקבות נעילה כפולה מאותו החוט (קריאה של מספר פעמים ברצף לפונקציה uni_lock) או בעקבות שחרור המנעול ע"י חוט שלא נעל אותו. (5 נק') הציעו שיפור למנעול כפי שהוא כתוב לעיל, המאפשר לאותו החוט לקרוא לפונקציית הנעילה כמה פעמים ברצף מבלי להיתקע (בכל נעילה נוספת לאחר הראשונה יוחזר הערך EPERM), ושעבור חוט שמנסה לשחרר מנעול שלא נעל בעצמו יוחזר ערך השגיאה EPERM. על הקוד שלכם להיות כתוב בשפת C (אך לא יורדו נקודות על שגיאות תחביר קטנות). הקפידו על תיעוד שמנמק את הנכונות של הקוד שלכם.

    libc syscall wrapper caching pitfallsSignal delivery and handler timingPipe IPC semanticsMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
OS-Spring2021-examAQ2core4 parts here

שאלה 2 - תהליכים

  1. 1· short_answer· 2 pts

    (2 נק') בקוד של אברהם יש בעיה: במקרים מסוימים התוכנית very_special רצה בתור תהליך רגיל למשך פרק זמן כלשהו. הסבירו באילו מקרים הבעיה מתרחשת ומדוע היא אינה בהכרח מתרחשת תמיד. נימוק:

    System call trap and kernel entryfork/exec address-space semanticslibc syscall wrapper caching pitfalls
  2. 2· short_answer· 3 pts

    אברהם ניסה לתקן את הבעיה וכתב תוכנית חדשה: prog2.c ```c 1. #include <sys/types.h> 2. #include <unistd.h> 3. 4. int main() { 5. pid_t p1 = fork(); 6. if (p1 > 0) { // parent 7. set_special(p1); 8. } else if (p1 == 0) { // child 9. pid_t p2 = fork(); 10. if (p2 == 0) { // grand-child 11. execv("/usr/bin/very_special", ...); 12. } 13. } 14. return 0; 15. } ``` (3 נק') למרבה הצער, הבעיה רק החריפה: במקרים מסוימים התוכנית very_special רצה בתור תהליך רגיל *לנצח* (ולא רק למשך פרק זמן כלשהו). הסבירו באילו מקרים הבעיה מתרחשת ומדוע היא גורמת לתוכנית very_special להיתקע לנצח בתור תהליך רגיל. נימוק:

    fork/exec address-space semanticslibc syscall wrapper caching pitfalls
  3. 3· short_answer· 5 pts

    אברהם ביקש מחבריו לקורס "מערכות הפעלה" לעזור לו לפתור את הבעיות שתוארו לעיל. לשמחתו הוא קיבל ארבע הצעות לתיקון. בכל אחד מהסעיפים הבאים מציגים הצעה לפתרון הבעיה על ידי הוספת שורות קוד לתוכנית המקורית prog1 (לנוחותכם, השורות שהתווספו מודגשות). הצעה ראשונה לתיקון הבעיה: prog3.c ```c 1. #include <sys/types.h> 2. #include <unistd.h> 3. 4. int main() { 5. pid_t p = fork(); 6. if (p > 0) { // parent 7. set_special(p); 8. } else if (p == 0) { // child 9. If (is_special()) 10. execv("/usr/bin/very_special", ...); 11. } 12. return 0; 13. } ``` (5 נק') האם שינוי זה פותר את הבעיה? כן / לא נימוק: אם לא, האם אתם יכולים להציע שינוי בשורת קוד אחת ויחידה שהתווספה כדי לתקן את הבעיה? כן / לא אם כן, נא לציין איזה שורה ואיך לתקן אותה: מספר שורה התיקון (שורת קוד החדשה במקום השורה הקיימת)

    fork/exec address-space semanticslibc syscall wrapper caching pitfalls
  4. 4· short_answer· 5 pts

    הצעה שניה לתיקון הבעיה: prog4 ```c 1. // includes all necessary headers... 2. int main() { 3. // declare and initialize semaphore with initial value=0 4. pid_t p = fork(); 5. if (p > 0) { // parent 6. set_special(p); 7. sem_post(&sem); 8. } else if (p == 0) { // child 9. sem_wait(&sem); 10. execv("/usr/bin/very_special", ...); 11. } 12. // destroy the semaphore 13. return 0; 14. } ``` (5 נק') האם שינוי זה פותר את הבעיה? כן / לא נימוק: אם לא, האם אתם יכולים להציע שינוי בשורת קוד אחת ויחידה שהתווספה כדי לתקן את הבעיה? כן / לא אם כן, נא לציין איזה שורה ואיך לתקן אותה: מספר שורה התיקון (שורת קוד החדשה במקום השורה הקיימת)

    fork/exec address-space semanticslibc syscall wrapper caching pitfallsSemaphore blocking and busy-wait
OS-Winter2022-examCQ3core4 parts here

סנכרון

  1. א'· short_answer· 6 pts

    (6 נק') בפתרון הבעיה (שמוצג בסעיפים הבאים) יש שימוש במספר סמפורים, כתבו איזה סמפור: 1. מאפשר הגעה אטומית של נוסעים או של האוטובוס לתחנה: 2. נועד להעלות נוסע בצורה אטומית לאוטובוס באמצעות הפונקציה boardBus: 3. נועד להודיע לאוטובוס שעלה נוסע לאוטובוס:

    Semaphore blocking and busy-wait
  2. ב'· code· 6 pts

    (6 נק') לצורך מימוש בעיית הסנכרון הזאת, יש צורך בקוד עבור האוטובוס. השלימו את המימוש: 1 void depart(); 2 void boardBus(); 3 4 sem_t mutex, bus, boarded; 5 sem_init(&mutex, 0, 1); //Notice. 6 sem_init(&bus, 0, 0); 7 sem_init(&boarded, 0, 0); 8 int waiting = 0; 9 10 // bus code 11 sem_wait(mutex); 12 int n = waiting < 50 ? waiting : 50; 13 for(int i = 0; i < n; i++){ 14 sem_post(bus); 15 // add your code here 16 } 17 waiting = waiting-50 > 0 ? waiting-50: 0; 18 // add your code here 19 depart();

    Mutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
  3. ג'· code· 6 pts

    (6 נק') כמו כן, יש צורך בקוד עבור סטודנט שבא לתחנה. השלימו את המימוש: 20 // rider code 21 sem_wait(mutex); 22 // add your code here 23 sem_post(mutex); 24 // add your code here 25 board(); 26 sem_post(boarded);

    Mutex correctness and deadlock avoidance
  4. ד'· short_answer· 7 pts

    (7 נק') יכול להיות מתסכל עבור הנוסעים שמגיעים בזמן שהאוטובוס בתחנה להמתין לאוטובוס הבא. איזה שינוי בשורה אחת יש לבצע בקוד כדי לאפשר גם להם אפשרות לעלות לאוטובוס? עליכם להוסיף שורה (או יותר) בקוד משני סעיפים קודמים שלא ציינו בנוסף לשורות שלכם. (רמז: בקוד של האוטובוס). שורת קוד להוספה: מיקום (לאן להוסיף): הסבר:

    Semaphore blocking and busy-waitMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction
Winter2022-examAQ4core4 parts here

סנכרון

  1. 1· short_answer· 2 pts

    (2 נק') האם הקוד הנ"ל תקין ונכון (מקיים את התנאים של המסעדה) עבור מושב יחיד (כלומר, NUM_SEATS=1)? (כן / לא)

    Pipe IPC semantics
  2. 2· short_answer· 2 pts

    (2 נק') האם הקוד הנ"ל תקין ונכון (מקיים את התנאים של המסעדה) עבור יותר ממושב יחיד (למשל, NUM_SEATS=5)? (כן / לא)

    Pipe IPC semantics
  3. 3· short_answer· 9 pts

    (9 נק') בהתייחס לקוד הנ"ל, סמנו עבור כל אחת מהבעיות בטבלה אם היא מתקיימת (ואז תנו דוגמא), או שלא מתקיימת (ואז הסבירו בקצרה) שאלה תשובה (כן / לא) הסבר קיימת בעיית הוגנות? קיימת בעיית נכונות? קיימת בעיית ? DeadLock / Livelock

    Mutex correctness and deadlock avoidanceBanker's algorithm safety check
  4. 4· code· 12 pts

    (12 נק') אחרי ש- USHI התחיל ללמוד לבחינה במערכות הפעלה, סוף סוף הוא התחיל להרגיש שהוא שולט יותר טוב בחומר שלמד בקורס ואז נזכר שהוא צריך לשפר ולשכתב את התוכנית הנ"ל בצורה יותר טובה. USHI התייעץ עם השותף שלו בקורס SHUSHI איך לשכתב את הקוד, ואכן הם הצליחו לשכתב את רוב הקוד חוץ מכמה שורות ריקות שעדיין מתלבטים לגביהן. אתם יכולים לעזור ל- USHI ו- SHUSHI לכתוב את הקוד החסר כך שהתוכנית הזו תעבוד בצורה תקינה (כך שהקוד יהיה נקי מהבעיה/ות שגיליתם בסעיף הקודם)? והסבירו בקצרה איך הקוד החדש מתקן את הבעיה/ות מסעיף קודם. 1 #define NUM_SEATS (5) 2 int eating = waiting = 0; // hint: where should be updated? 3 bool must_wait = false; // hint: where should be updated? 4 sem_t mutex, block; 5 sem_init(&mutex, 0, 1); // value=1 6 sem_init(&block, 0, 0); // value=0 7 8 enter_OSUSHI() { 9 sem_wait(&mutex) 10 if (must_wait) { 11 waiting += 1; 12 sem_post(&mutex); 13 sem_wait(&block); 14 } 15 sem_wait(&mutex); // reacquire mutex 16 waiting -= 1; 17 } 18 eating += 1; 19 must_wait = (eating == NUM_SEATS); 20 sem_post(&mutex); 21 } 22 23 exit_OSUSHI() { 24 sem_wait(&mutex); 25 eating -= 1; 26 if (eating == 0) { 27 int n = min(NUM_SEATS, waiting ); 28 sem_post(&block, n); 29 must_wait = false; 30 } 31 sem_post(&mutex); 32 }

    Mutex correctness and deadlock avoidanceSRT / preemptive Gantt construction