Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp@0:d95c16be6bc4, 2014-03-20 (annotated)
- Committer:
- dstlouis
- Date:
- Thu Mar 20 08:43:48 2014 +0000
- Revision:
- 0:d95c16be6bc4
lab9-4 deadlock condition example
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| dstlouis | 0:d95c16be6bc4 | 1 | #include "mbed.h" |
| dstlouis | 0:d95c16be6bc4 | 2 | #include "rtos.h" |
| dstlouis | 0:d95c16be6bc4 | 3 | |
| dstlouis | 0:d95c16be6bc4 | 4 | //if you want to expose the deadlock, uncomment the DEADLOCK define |
| dstlouis | 0:d95c16be6bc4 | 5 | #define DEADLOCK |
| dstlouis | 0:d95c16be6bc4 | 6 | |
| dstlouis | 0:d95c16be6bc4 | 7 | //if you want to fix the deadlock by having the mutex lock timeout, uncomment the DEADLOCK_FIX define |
| dstlouis | 0:d95c16be6bc4 | 8 | #define DEADLOCK_FIX |
| dstlouis | 0:d95c16be6bc4 | 9 | |
| dstlouis | 0:d95c16be6bc4 | 10 | // I recommend running with the following order |
| dstlouis | 0:d95c16be6bc4 | 11 | // 1. do not define any macro to see normal execution |
| dstlouis | 0:d95c16be6bc4 | 12 | // 2. define DEADLOCK to see program hang |
| dstlouis | 0:d95c16be6bc4 | 13 | // 3. define DEADLOCK and DEADLOCK_FIX to see the hang fixed |
| dstlouis | 0:d95c16be6bc4 | 14 | |
| dstlouis | 0:d95c16be6bc4 | 15 | typedef struct account{ |
| dstlouis | 0:d95c16be6bc4 | 16 | double balance; |
| dstlouis | 0:d95c16be6bc4 | 17 | int id; |
| dstlouis | 0:d95c16be6bc4 | 18 | } Account; |
| dstlouis | 0:d95c16be6bc4 | 19 | |
| dstlouis | 0:d95c16be6bc4 | 20 | // Globals |
| dstlouis | 0:d95c16be6bc4 | 21 | //two accounts |
| dstlouis | 0:d95c16be6bc4 | 22 | Account personA; |
| dstlouis | 0:d95c16be6bc4 | 23 | Account personB; |
| dstlouis | 0:d95c16be6bc4 | 24 | //pointers to those accounts |
| dstlouis | 0:d95c16be6bc4 | 25 | Account * personA_ptr; |
| dstlouis | 0:d95c16be6bc4 | 26 | Account * personB_ptr; |
| dstlouis | 0:d95c16be6bc4 | 27 | //mutexes for the two accounts |
| dstlouis | 0:d95c16be6bc4 | 28 | Mutex personA_mutex; |
| dstlouis | 0:d95c16be6bc4 | 29 | Mutex personB_mutex; |
| dstlouis | 0:d95c16be6bc4 | 30 | |
| dstlouis | 0:d95c16be6bc4 | 31 | // function: withdraw |
| dstlouis | 0:d95c16be6bc4 | 32 | // inputs: Account pointer, double amount to withdraw |
| dstlouis | 0:d95c16be6bc4 | 33 | // description: subtracts input amount from the Account's balance |
| dstlouis | 0:d95c16be6bc4 | 34 | void withdraw (Account * person, double amount){ |
| dstlouis | 0:d95c16be6bc4 | 35 | person->balance -= amount; |
| dstlouis | 0:d95c16be6bc4 | 36 | printf("Balance withdraw: %f from id %d\n", person->balance, person->id); |
| dstlouis | 0:d95c16be6bc4 | 37 | } |
| dstlouis | 0:d95c16be6bc4 | 38 | |
| dstlouis | 0:d95c16be6bc4 | 39 | // function: deposit |
| dstlouis | 0:d95c16be6bc4 | 40 | // inputs: Account pointer, double amount to deposit |
| dstlouis | 0:d95c16be6bc4 | 41 | // description: adds input amount to the Account's balance |
| dstlouis | 0:d95c16be6bc4 | 42 | void deposit(Account * person, double amount){ |
| dstlouis | 0:d95c16be6bc4 | 43 | person->balance += amount; |
| dstlouis | 0:d95c16be6bc4 | 44 | printf("Balance deposit: %f from id %d\n", person->balance, person->id); |
| dstlouis | 0:d95c16be6bc4 | 45 | } |
| dstlouis | 0:d95c16be6bc4 | 46 | |
| dstlouis | 0:d95c16be6bc4 | 47 | // function: transfer |
| dstlouis | 0:d95c16be6bc4 | 48 | // inputs: From Account mutex, To Account mutex, From Account pointer, To Account pointer, double amount to transfer |
| dstlouis | 0:d95c16be6bc4 | 49 | // description: protects access to each account using correspoinding mutex |
| dstlouis | 0:d95c16be6bc4 | 50 | // withdraws amount from From Account and deposits amount to To Account |
| dstlouis | 0:d95c16be6bc4 | 51 | void transfer(Mutex f_m, Mutex t_m, Account * from, Account* to, double amount){ |
| dstlouis | 0:d95c16be6bc4 | 52 | #ifdef DEADLOCK_FIX |
| dstlouis | 0:d95c16be6bc4 | 53 | f_m.lock(500); |
| dstlouis | 0:d95c16be6bc4 | 54 | #else |
| dstlouis | 0:d95c16be6bc4 | 55 | f_m.lock(); |
| dstlouis | 0:d95c16be6bc4 | 56 | #endif |
| dstlouis | 0:d95c16be6bc4 | 57 | |
| dstlouis | 0:d95c16be6bc4 | 58 | //putting a wait between grabing the locks allows the higher priority task to come in and grab the other lockk |
| dstlouis | 0:d95c16be6bc4 | 59 | #ifdef DEADLOCK |
| dstlouis | 0:d95c16be6bc4 | 60 | Thread::wait(5000); |
| dstlouis | 0:d95c16be6bc4 | 61 | #endif |
| dstlouis | 0:d95c16be6bc4 | 62 | |
| dstlouis | 0:d95c16be6bc4 | 63 | #ifdef DEADLOCK_FIX |
| dstlouis | 0:d95c16be6bc4 | 64 | t_m.lock(500); |
| dstlouis | 0:d95c16be6bc4 | 65 | #else |
| dstlouis | 0:d95c16be6bc4 | 66 | t_m.lock(); |
| dstlouis | 0:d95c16be6bc4 | 67 | #endif |
| dstlouis | 0:d95c16be6bc4 | 68 | |
| dstlouis | 0:d95c16be6bc4 | 69 | withdraw(from, amount); |
| dstlouis | 0:d95c16be6bc4 | 70 | deposit(to, amount); |
| dstlouis | 0:d95c16be6bc4 | 71 | t_m.unlock(); |
| dstlouis | 0:d95c16be6bc4 | 72 | f_m.unlock(); |
| dstlouis | 0:d95c16be6bc4 | 73 | } |
| dstlouis | 0:d95c16be6bc4 | 74 | |
| dstlouis | 0:d95c16be6bc4 | 75 | // thread: AtoB |
| dstlouis | 0:d95c16be6bc4 | 76 | // description: transfers 500 from A to B, prints balance after transfer |
| dstlouis | 0:d95c16be6bc4 | 77 | void AtoB(void const *args) { |
| dstlouis | 0:d95c16be6bc4 | 78 | transfer(personA_mutex, personB_mutex, personA_ptr, personB_ptr, 500); |
| dstlouis | 0:d95c16be6bc4 | 79 | printf("Balance A (AtoB): %f\n", personA_ptr->balance); |
| dstlouis | 0:d95c16be6bc4 | 80 | printf("Balance B (AtoB): %f\n", personB_ptr->balance); |
| dstlouis | 0:d95c16be6bc4 | 81 | } |
| dstlouis | 0:d95c16be6bc4 | 82 | |
| dstlouis | 0:d95c16be6bc4 | 83 | // thread: BtoA |
| dstlouis | 0:d95c16be6bc4 | 84 | // description: transfers 200 from B to A, prints balance after transfer |
| dstlouis | 0:d95c16be6bc4 | 85 | void BtoA(void const *args) { |
| dstlouis | 0:d95c16be6bc4 | 86 | transfer(personB_mutex, personA_mutex, personB_ptr, personA_ptr, 200); |
| dstlouis | 0:d95c16be6bc4 | 87 | printf("Balance A (BtoA): %f\n", personA_ptr->balance); |
| dstlouis | 0:d95c16be6bc4 | 88 | printf("Balance B (BtoA): %f\n", personB_ptr->balance); |
| dstlouis | 0:d95c16be6bc4 | 89 | } |
| dstlouis | 0:d95c16be6bc4 | 90 | |
| dstlouis | 0:d95c16be6bc4 | 91 | int main () { |
| dstlouis | 0:d95c16be6bc4 | 92 | printf("\n\nStart new transaction\n"); |
| dstlouis | 0:d95c16be6bc4 | 93 | |
| dstlouis | 0:d95c16be6bc4 | 94 | //populate values for Account personA, set pointer |
| dstlouis | 0:d95c16be6bc4 | 95 | personA_ptr = &personA; |
| dstlouis | 0:d95c16be6bc4 | 96 | personA_ptr->id = 1; |
| dstlouis | 0:d95c16be6bc4 | 97 | personA_ptr->balance = 1000; |
| dstlouis | 0:d95c16be6bc4 | 98 | |
| dstlouis | 0:d95c16be6bc4 | 99 | //populate values for Account personB, set pointer |
| dstlouis | 0:d95c16be6bc4 | 100 | personB_ptr = &personB; |
| dstlouis | 0:d95c16be6bc4 | 101 | personB_ptr->id = 2; |
| dstlouis | 0:d95c16be6bc4 | 102 | personB_ptr->balance = 1000; |
| dstlouis | 0:d95c16be6bc4 | 103 | |
| dstlouis | 0:d95c16be6bc4 | 104 | //start threads |
| dstlouis | 0:d95c16be6bc4 | 105 | Thread thread1(AtoB); |
| dstlouis | 0:d95c16be6bc4 | 106 | Thread thread2(BtoA); |
| dstlouis | 0:d95c16be6bc4 | 107 | |
| dstlouis | 0:d95c16be6bc4 | 108 | thread1.set_priority(osPriorityNormal); |
| dstlouis | 0:d95c16be6bc4 | 109 | //second thread needs to have a higher priority than the first thread to crate the deadlock condition |
| dstlouis | 0:d95c16be6bc4 | 110 | thread2.set_priority(osPriorityHigh); |
| dstlouis | 0:d95c16be6bc4 | 111 | |
| dstlouis | 0:d95c16be6bc4 | 112 | while (true){ |
| dstlouis | 0:d95c16be6bc4 | 113 | } |
| dstlouis | 0:d95c16be6bc4 | 114 | |
| dstlouis | 0:d95c16be6bc4 | 115 | } |