AAAB8nicdVDJSgNBEK2JW4zbuNy8NAZBCAw9RtzFgAc9RnBMIAmhp9OTNOlZ6O4RYsiXeFE8KeJ3+At+hn/gZKKHuDwo6vHea7qq3EhwpTF+NzITk1PTM9nZ3Nz8wuKSubxyrcJYUubQUISy6hLFBA+Yo7kWrBpJRnxXsIrbPRv6lRsmFQ+DK92LWMMn7YB7nBKdSE1zjR+e4CNUR/wYBWkvFFDTzNsWToH+J/nTj/NXBADlpvlWb4U09lmgqSBK1Wwc6UafSM2pYINcPVYsIrRL2qyfzjxAm4nUQl4okwo0StWxHPGV6vlukvSJ7qif3lD8y6vF2ttv9HkQxZoFdPSRFwukQzQ8AGpxyagWvYQQKnkyIaIdIgnVyZlyyerYKu7u2EWMfpPv1Z1t68CyL3G+hGGELKzDBmyBDXtQggsogwMUbuEenuDZiI0748F4HEUzxtebVRiD8fIJI4qQJA==sha1_base64="xOrmWCDG9Z/Wkj5gPaC/9o7j9QA=">AAAB8nicdVDLSgMxFM3UV62vUbtzEyyCUBgyVnyLBRd2WcGxhbaUTJppQzOZIckIbemXuFFcKeJ3+Asu/QT/wOlUF/Vx4HIP55yQe68bcqY0Qm9Gamp6ZnYuPZ9ZWFxaXjFX165VEElCHRLwQFZdrChngjqaaU6roaTYdzmtuN3zkV+5oVKxQFzpXkgbPm4L5jGCdSw1zSw7OkXHsA7ZCRRJz+dh08zZFkoA/ye5s4+Ll2z/vVRumq/1VkAinwpNOFaqZqNQNwZYakY4HWbqkaIhJl3cpoNk5iHciqUW9AIZl9AwUSdy2Feq57tx0se6o356I/EvrxZp76AxYCKMNBVk/JEXcagDODoAbDFJiea9mGAiWTwhJB0sMdHxmTLx6sgq7O3aBQR/k+/VnR3r0LIvUa6IwBhpsAE2wTawwT4oghIoAwcQ0Ad34BE8GZFxa9wbD+Noyvh6sw4mYDx/AjH/kbs=sha1_base64="fFtj5f4o+eWhd+F60c/nry8W5TY=">AAAB8nicdVDLSgMxFL3js9bX+Ni5CRZBKAwZK76FghuXFRxbaEvJpJk2NPMgyQi19EvcKK4UP8Rf8G9Mp3VRHwdCDueckHuPnwiuNMaf1szs3PzCYm4pv7yyurZub2zeqTiVlHk0FrGs+UQxwSPmaa4FqyWSkdAXrOr3rkZ+9Z5JxePoVvcT1gxJJ+IBp0QbqWVv87NLfI4aiF+gKLuLRdSyC66DM6D/SQEmqLTsj0Y7pmnIIk0FUaru4kQ3B0RqTgUb5hupYgmhPdJhg2zmIdozUhsFsTQn0ihTp3IkVKof+iYZEt1VP72R+JdXT3Vw0hzwKEk1i+j4oyAVSMdoVABqc8moFn1DCJXcTIhol0hCtakpb1bHTuno0C1h9Jt8r+4dOKeOe4MLZTzpIAc7sAv74MIxlOEaKuABhQd4gld4s1Lr0Xq2XsbRGWvyZgumYL1/ASqRjd8= flag [i ]:= false; ticket [i]:=0; Requires to read N
AAAB8XicdVDLSgMxFL1TX7W+ql26CRbB1TDjiC8QC25cVnBsoS0lk2baYOZBckcYSn/EjeJK8Uf8BT/DPzBtdVEfBwKHc07IOQlSKTQ6zrtVmJtfWFwqLpdWVtfWN8qbWzc6yRTjPktkopoB1VyKmPsoUPJmqjiNAskbwe3F2G/ccaVFEl9jnvJORPuxCAWjaKRuudKOKA4EDkNJ+6OW6JDTs2656trOBOR/Uj3/8LwaANS75bd2L2FZxGNkkmrdcp0UO0OqUDDJR6V2pnlK2S3t8+Gk8ojsGqlHwkSZEyOZqDM5GmmdR4FJjgvqn95Y/MtrZRged4YiTjPkMZs+FGaSYELG+0lPKM5Q5oZQpoRpSNiAKsrQ/FLJTHds7/DA9Rzym3xP9/ftE9u9cqo1G6YowjbswB64cAQ1uIQ6+MAghwd4hhcLrXvr0XqaRgvW150KzMB6/QT9npIGsha1_base64="X4KNnxpphaIsSYr0iDKU4xLYyAY=">AAAB8XicdVBLS8NAGNzUV62vaI9eFovgKSRWfIFY8OKxgrGFNpTNdtMubh7sfhFC6B/xonhS/CP+BX+G/8BNqof6GFgYZmbZmfUTwRXY9rtRmZtfWFyqLtdWVtfWN8zNrRsVp5Iyl8Yill2fKCZ4xFzgIFg3kYyEvmAd//ai8Dt3TCoeR9eQJcwLySjiAacEtDQw6/2QwJhDHggymvS4h0/PBmbDsewS+H/SOP9olmgPzLf+MKZpyCKggijVc+wEvJxI4FSwSa2fKpYQektGLC8rT/CuloY4iKU+EeBSncmRUKks9HWyKKh+eoX4l9dLITj2ch4lKbCITh8KUoEhxsV+POSSURCZJoRKrhtiOiaSUNC/VNPTbat5eOA0bfybfE93960Ty7myGy0LTVFF22gH7SEHHaEWukRt5CKKMvSAntGLAca98Wg8TaMV4+tOHc3AeP0EspeSkg==sha1_base64="C4tMknNJczhTRLfii9dVQPTgEcQ=">AAAB8XicdVDLSsNAFL2pr1pf0S7dDBbBVUis+AKh4MZlBWMLbSiT6aQdOnkwcyOU0B9xo7hS/BF/wb8xaeuiPg4MHM45w73n+okUGm370ygtLa+srpXXKxubW9s75u7evY5TxbjLYhmrtk81lyLiLgqUvJ0oTkNf8pY/ui781gNXWsTRHY4T7oV0EIlAMIq51DOr3ZDiUGAWSDqYdIRHLq96Zs2x7CnI/6QGczR75ke3H7M05BEySbXuOHaCXkYVCib5pNJNNU8oG9EBz6YrT8hhLvVJEKv8RUim6kKOhlqPQz9PFgvqn14h/uV1UgzOvUxESYo8YrNBQSoJxqToT/pCcYZynBPKlMg3JGxIFWWYX6mSV7et+umJU7fJb/Jd3T22Lizn1q41rPkNyrAPB3AEDpxBA26gCS4wGMMTvMKbgcaj8Wy8zKIlY/6nCgsw3r8AlbqQMA== AAAB9nicdVDLSgMxFL3js9ZX1Y3gJlgEV8OMIz4RC25cVrC20JaSSdM2NPMguSMMQ/0VN4orxc/wF/wM/8C01UV9HAgczjlJzr1+LIVGx3m3pqZnZufmcwv5xaXlldXC2vqNjhLFeIVFMlI1n2ouRcgrKFDyWqw4DXzJq37/YuhXb7nSIgqvMY15M6DdUHQEo2ikVmGzEVDsCcxQsD7HQV00yckZcU5bhaJrOyOQ/0nx/MPzSgBQbhXeGu2IJQEPkUmqdd11YmxmVJmXJR/kG4nmMWV92uXZqPeA7BipTTqRMidEMlIncjTQOg18kxy21D+9ofiXV0+wc9TMRBgnyEM2/qiTSIIRGS6BtIXiDGVqCGVKmIaE9aiiDM2q8mZ0x/YO9l3PIb/J9+iVPfvYdq+cYsmGMXKwBduwCy4cQgkuoQwVYHAHD/AML1Zq3VuP1tM4OmV93dmACVivnwZ/k60=sha1_base64="J7AuRsjR5zH7nxY6EpQ0+MZjTOA=">AAAB9nicdVDLSsNAFJ34rPUVdSO4GSyCq5BY8YlYcOOygrGFNpTJdNoOnTyYuRFCqL/iRnGl+Bn+gp/hHzhJdVEfBwYO55yZOff6seAKbPvdmJqemZ2bLy2UF5eWV1bNtfUbFSWSMpdGIpJNnygmeMhc4CBYM5aMBL5gDX94kfuNWyYVj8JrSGPmBaQf8h6nBLTUMTfbAYEBhww4HTIYtbiHT86wfdoxK45lF8D/k8r5R7VAvWO+tbsRTQIWAhVEqZZjx+BlROqXBRuV24liMaFD0mdZ0XuEd7TUxb1I6hMCLtSJHAmUSgNfJ/OW6qeXi395rQR6R17GwzgBFtLxR71EYIhwvgTc5ZJREKkmhEquG2I6IJJQ0Ksq69Ftq3qw71Rt/Jt8j+7uWceWc2VXahYao4S20DbaRQ46RDV0ierIRRTdoQf0jF6M1Lg3Ho2ncXTK+LqzgSZgvH4Cu2mUOQ==sha1_base64="eT5r9A0en3+h3PpzRkVKVXg7+SI=">AAAB9nicdVDLSgMxFM3UV62vUTeCm2ARXA0zVnwiFNy4rODYQjuUTJppQzMPkjvCMNRfcaO4UvwMf8G/MdPWRX1cCBzOOUnOPX4iuALb/jRKc/MLi0vl5crK6tr6hrm5dafiVFLm0ljEsuUTxQSPmAscBGslkpHQF6zpD68KvXnPpOJxdAtZwryQ9CMecEpAU11zpxMSGHDIgdMhg1Gbe/j8EtsXXbPqWPZ48P+giqbT6JofnV5M05BFQAVRqu3YCXg5kfplwUaVTqpYQuiQ9Fk+zj3C+5rq4SCW+kSAx+yMj4RKZaGvnUVK9VMryL+0dgrBqZfzKEmBRXTyUZAKDDEuSsA9LhkFkWlAqOQ6IaYDIgkFXVVFr25bteMjp2bj3+B7dffQOrOcG7tat6YdlNEu2kMHyEEnqI6uUQO5iKIH9IRe0ZuRGY/Gs/EysZaM6Z1tNDPG+xeejJHX Proof Suppose T 1 and T 2 in } Fair mutual exclusion, and that distinct variables } (ticket[T1],T1) ticket[T2],T2) ⌧ public void acquire () { when T 2 entered CS, flag [T1]
AAAB8nicdVDLSgMxFL3js9bX+Ni5CRahboaMFR8rCy50WcHaQltKJs20oZmHSUaoQ7/EjeJKEb/DX/Az/AMzrS7q40DgcM4J957rxYIrjfG7NTU9Mzs3n1vILy4tr6zaa+tXKkokZVUaiUjWPaKY4CGraq4Fq8eSkcATrOb1TzO/dsOk4lF4qQcxawWkG3KfU6KN1LY3mwHRPa5TQq8TLtmwuItQ2y64Dh4B/U8KJx9nrwgAKm37rdmJaBKwUFNBlGq4ONatlEjNqWDDfDNRLCa0T7osHe08RDtG6iA/kuaFGo3UiRwJlBoEnklmG6qfXib+5TUS7R+1Uh7GiWYhHQ/yE4F0hLIDoI5pSbUYGEKo5GZDRHtEEqrNmfKmOnZKB/tuCaPf5Lt6dc85dtwLXChjGCMHW7ANRXDhEMpwDhWoAoVbuIcneLYS6856sB7H0Snr688GTMB6+QT4qZKqsha1_base64="zvHyNHGDfK7u66BAcCgCIdmj9Zw=">AAAB8nicdVDJSgNBFOxxjXEbNTcvjUGIl6HHiMvJgAdzjOCYQBJCT6cnadKz2IuQhHyJF8WTIn6Hv+DRT/AP7En0EJeChqKqmvfq+QlnUiH0Zs3Mzs0vLGaWsssrq2vr9sbmlYy1INQjMY9FzceSchZRTzHFaS0RFIc+p1W/d5b61RsqJIujS9VPaDPEnYgFjGBlpJada4RYdZkaYnKtmaCjwh6ELTvvOmgM+D/Jn36cv+QG7+VKy35ttGOiQxopwrGUdRclqjnEQjHC6Sjb0JImmPRwhw7HO4/grpHaMIiFeZGCY3Uqh0Mp+6FvkumG8qeXin95da2C4+aQRYlWNCKTQYHmUMUwPQBsm5ZE8b4hmAhmNoSkiwUmypwpa6ojp3h44BYR/E2+q3v7zonjXqB8CYEJMmAb7IACcMERKIEyqAAPEDAAd+ARPFnaurXurYdJdMb6+rMFpmA9fwIHLZRBsha1_base64="ONf/duOkmlMh5VPqQOGSp8BA4ik=">AAAB8nicdVDLSgMxFM3UV62v8bFzEyxC3QwzVnzsCm5cVnBsoS0lk2ba0MzD5EaoQ7/EjeJK8UP8Bf/GTFsX9XEhcDjnhHvPCVLBFbjup1VYWFxaXimultbWNza37O2dW5VoSZlPE5HIZkAUEzxmPnAQrJlKRqJAsEYwvMz1xj2TiifxDYxS1olIP+YhpwQM1bX32hGBAYeM0DvNJRtXjjDu2mXPcSeD/wdlNJt61/5o9xKqIxYDFUSpluem0MmIBE4FG5faWrGU0CHps2xy8xgfGqqHw0SaFwOesHM+Eik1igLjzC9UP7Wc/EtraQjPOxmPUw0sptNFoRYYEpwXgHsmJQUxMoBQyc2FmA6IJBRMTSUT3XWqpyde1cW/wXd0/9i5cLxrt1xzZx0U0T46QBXkoTNUQ1eojnxE0QN6Qq/ozdLWo/VsvUytBWv2ZxfNjfX+Bf+wkGU= int i := ThreadID.get(); must have been false.
AAAB+3icdVDbSkJBFN2nq9nN6jGCIQns5XBORlcioR7qzUBTUJE546iDcy7M7BOI2Eu/0kvRU9E/9At9Rn/QqPVglwUDi7XWZtbeXiSFRsd5tyYmp6ZnZhNzyfmFxaXl1MrqtQ5jxXiRhTJUZY9qLkXAiyhQ8nKkOPU9yUte52zgl2640iIMCtiNeM2nrUA0BaNopHpqQ5CjE1L1KbYF9gptM9u4PLdbHPuZ7eN6Ku3azhDkf5I+/chmcwCQr6feqo2QxT4PkEmqdcV1Iqz1qELBJO8nq7HmEWUd2uK9Yfk+2TJSgzRDZV6AZKiO5aivddf3THLQUv/0BuJfXiXG5kGtJ4IoRh6w0UfNWBIMyeASpCEUZyi7hlCmhGlIWJsqytDcK2lWd+zs3q6bdchv8r16ccc+tN0rJ52zYYQErMMmZMCFfcjBBeShCAzu4AGe4cW6te6tR+tpFJ2wvmbWYAzW6yemepUXsha1_base64="RluwXy7GukY6rENbv4qwyKwxaXg=">AAAB+3icdVDLSgMxFM34rPVVdSlCsAh1M8xY8YlY0IXuKnRsoS0lk2ba0MyD5I5QSt34K24UV4r/4C/4Gf6Bmaku6uNA4HDOueTc60aCK7Csd2Nicmp6ZjYzl51fWFxazq2sXqswlpQ5NBShrLlEMcED5gAHwWqRZMR3Bau6vbPEr94wqXgYVKAfsaZPOgH3OCWgpVZug+OjE9zwCXQ5DCpdPdu+PDc7DIaF7eNWLm+bVgr8P8mffhRTlFu5t0Y7pLHPAqCCKFW3rQiaAyKBU8GG2UasWERoj3TYIC0/xFtaamMvlPoFgFN1LEd8pfq+q5NJS/XTS8S/vHoM3kFzwIMoBhbQ0UdeLDCEOLkEbnPJKIi+JoRKrhti2iWSUND3yurVLbO4t2sXLfybfK/u7JiHpn1l5UsmGiGD1tEmKiAb7aMSukBl5CCK7tADekYvxq1xbzwaT6PohPE1s4bGYLx+AltzlaM=sha1_base64="HkHOfu5/AJopFPEODDDWOugr3yI=">AAAB+3icdVDLSgMxFM3UV62vUZciBItQN8OMFZ8IBV3orkLHFtpSMmnahmYeJHeEMtSNv+JGcaX4D/6Cf2OmrYv6OBA4nHMuufd4keAKbPvTyMzMzs0vZBdzS8srq2vm+satCmNJmUtDEcqaRxQTPGAucBCsFklGfE+wqte/SP3qHZOKh0EFBhFr+qQb8A6nBLTUMrc5Pj3HDZ9Aj0NS6enZ9vWl1WUwLOydtcy8Y9kj4P9JHk1QbpkfjXZIY58FQAVRqu7YETQTIoFTwYa5RqxYRGifdFkyWn6Id7XUxp1Q6hcAHqlTOeIrNfA9nUy3VD+9VPzLq8fQOW4mPIhiYAEdf9SJBYYQp03gNpeMghhoQqjkekNMe0QSCrqvnD7dtoqHB07Rxr/J9+nuvnViOTd2vmRNOsiiLbSDCshBR6iErlAZuYiiB/SEXtGbcW88Gs/GyziaMSYzm2gKxvsXPpaTQQ== flag [ i ]:= true; T 1 computed its ticket after T2
AAAB8HicdVBLSwMxGPy2vmp9rfXoJVgET8uuK75ALHjxWMG1hXYp2TTbhmYfJFmxLP0hXhRPir/Ev+DP8B+YbfVQHwOBYWZCZhKknEll2+9GaW5+YXGpvFxZWV1b3zA3qzcyyQShHkl4IloBlpSzmHqKKU5bqaA4CjhtBsOLwm/eUiFZEl+rUUr9CPdjFjKClZa6ZrUTYTVgKg857o/bzD8965o1x7InQP+T2vmH69YBoNE13zq9hGQRjRXhWMq2Y6fKz7FQjHA6rnQySVNMhrhP80njMdrVUg+FidAnVmiizuRwJOUoCnSy6Cd/eoX4l9fOVHjs5yxOM0VjMn0ozDhSCSrmox4TlCg+0gQTwXRDRAZYYKL0J1X0dNtyDw8c10a/yfd0b986sZwru1a3YIoybMMO7IEDR1CHS2iABwTu4AGe4cWQxr3xaDxNoyXj684WzMB4/QSijpHcsha1_base64="NoEa57LetuKZtwHgH920Kv2VleY=">AAAB8HicdVBLSwMxGPy2vmp9rfXoJVgET8uuFV8gFrx4rODaQruUbJptQ7MPkqxYlv4QL4onxV/iX/Bn+A/MbvVQHwOBYWZCZuInnEll2+9GaW5+YXGpvFxZWV1b3zA3qzcyTgWhLol5LNo+lpSziLqKKU7biaA49Dlt+aOL3G/dUiFZHF2rcUK9EA8iFjCClZZ6ZrUbYjVkKgs4Hkw6zDs965k1x7ILoP9J7fyjXqDZM9+6/ZikIY0U4VjKjmMnysuwUIxwOql0U0kTTEZ4QLOi8QTtaqmPgljoEylUqDM5HEo5Dn2dzPvJn14u/uV1UhUcexmLklTRiEwfClKOVIzy+ajPBCWKjzXBRDDdEJEhFpgo/UkVPd226ocHTt1Gv8n3dHffOrGcK7vWsGCKMmzDDuyBA0fQgEtoggsE7uABnuHFkMa98Wg8TaMl4+vOFszAeP0EV4eSaA==sha1_base64="LsAKndOVoikjRgjDohCamo3eC/o=">AAAB8HicdVDLSsNAFL2pr1pfsS7dDBbBVUhUfIFQcOOygrGFNpTJdNIOnTyYuRFL6Ie4UVwpfom/4N+YtHVRHwcGDuec4d5z/UQKjbb9aZQWFpeWV8qrlbX1jc0tc7t6p+NUMe6yWMaq5VPNpYi4iwIlbyWK09CXvOkPrwq/ec+VFnF0i6OEeyHtRyIQjGIudc1qJ6Q4EJgFkvbHbeFdXHbNmmPZE5D/SQ1maHTNj04vZmnII2SSat127AS9jCoUTPJxpZNqnlA2pH2eTTYek/1c6pEgVvmLkEzUuRwNtR6Ffp4s9tM/vUL8y2unGJx5mYiSFHnEpoOCVBKMSVGf9ITiDOUoJ5QpkW9I2IAqyjA/UiWvbltHJ8fOkU1+k+/q7qF1bjk3dq1uzW5Qhl3YgwNw4BTqcA0NcIHBAzzBK7wZ2ng0no2XabRkzP7swByM9y86qpAG ticket [ i ]:= max (ticket[0],...,ticket[n 1]) + 1; contradiction with AAAB83icdVDLSgMxFL1TX7W+quLKTbAIroYZK75ALLhxWcGxhbaUTJq2oZkHyZ1CGfonbhRXiv/hL/gZ/oGZVhf1cSBwOOckOff6sRQaHefdys3NLywu5ZcLK6tr6xvFza07HSWKcY9FMlJ1n2ouRcg9FCh5PVacBr7kNX9wlfm1IVdaROEtjmLeCmgvFF3BKBqpXdxpBhT7AlMUbMBx3BCt8wvSLpZc25mA/E9Klx/lcgUAqu3iW7MTsSTgITJJtW64ToytlCrzrOTjQjPRPKZsQHs8nZQek30jdUg3UuaESCbqTI4GWo8C3ySzivqnl4l/eY0Eu6etVIRxgjxk04+6iSQYkWwDpCMUZyhHhlCmhGlIWJ8qytDsqWBGd+zy8ZFbdshv8j26d2if2e6NU6rYMEUedmEPDsCFE6jANVTBAwYpPMAzvFhD6956tJ6m0Zz1dWcbZmC9fgKxypMEsha1_base64="4MD9CV74IMwJ+NxpYeVITynMfcE=">AAAB83icdVDLSsNAFJ3UV62vqLhyM1gEVyGx4gvEghuXFYwttKFMppN26OTBzE2hhP6JG8WV4n/4C36Gf+Ak1UV9HBg4nHNm5tzrJ4IrsO13ozQ3v7C4VF6urKyurW+Ym1t3Kk4lZS6NRSxbPlFM8Ii5wEGwViIZCX3Bmv7wKvebIyYVj6NbGCfMC0k/4gGnBLTUNXc6IYEBhww4HTKYtLl3foG7ZtWx7AL4f1K9/KgVaHTNt04vpmnIIqCCKNV27AS8jEj9rGCTSidVLCF0SPosK0pP8L6WejiIpT4R4EKdyZFQqXHo62ReUf30cvEvr51CcOplPEpSYBGdfhSkAkOM8w3gHpeMghhrQqjkuiGmAyIJBb2nih7dtmrHR07Nxr/J9+juoXVmOTd2tW6hKcpoF+2hA+SgE1RH16iBXERRhh7QM3oxRsa98Wg8TaMl4+vONpqB8foJZsOTkA==sha1_base64="d1hzWtr26RDstmRuZhEKirMfYW0=">AAAB83icdVDLSgMxFL3js9bXqLhyEyyCq2HGii8QCm5cVrC20A4lk6ZtaOZBcqdQhv6JG8WV4n/4C/6NmbYu6uNC4HDOSXLuCRIpNLrup7WwuLS8slpYK65vbG5t2zu7DzpOFeM1FstYNQKquRQRr6FAyRuJ4jQMJK8Hg5tcrw+50iKO7nGUcD+kvUh0BaNoqLa93wop9gVmKNiA47gp/Ktr0rZLnuNOhvwPSjCbatv+aHViloY8Qiap1k3PTdDPqDLPSj4utlLNE8oGtMezSegxOTJUh3RjZU6EZMLO+Wio9SgMjDOPqH9qOfmX1kyxe+FnIkpS5BGbftRNJcGY5A2QjlCcoRwZQJkSJiFhfaooQ9NT0azuOuWzU6/skt/ge/XaiXPpeHduqeLMOijAARzCMXhwDhW4hSrUgEEGT/AKb9bQerSerZepdcGa3dmDubHevwBJ5pEu AAACFHicdVDLSgMxFL3js9ZX1aWbYBEUdZixUhUXFty4rOCo0A4lk6Y2NPMguSOUod/hxl9xowiC4t7P8A9MW13Ux4GQwzn3JvfcIJFCo+O8W2PjE5NT07mZ/Ozc/MJiYWn5QsepYtxjsYzVVUA1lyLiHgqU/CpRnIaB5JdB56TvX95wpUUcnWM34X5IryPREoyikRqF8kY9pNgWmKFgHY69muNvk7psxqjN/cOLdlx/k2y5R41C0bWdAcj/pHj8USpVAKDaKDzXmzFLQx4hk1Trmusk6GdUmacl7+XrqeYJZR16zbNBqh5ZN1KTtGJlToRkoI7U0VDrbhiYyv6Y+qfXF//yaim2DvxMREmKPGLDj1qpJBiT/opIUyjOUHYNoUwJMyFhbaooQ7PIvInu2KXynltyyG/yHd3btQ9t98wpVmwYIgersAYb4MI+VOAUquABgzt4gBd4tW6te+vRehqWjllfPSswAuvtE8QAn4M=sha1_base64="pHgE/z3mbRlavlKtgn2e/bRMrHI=">AAACFHicdVDLSgMxFM3UV62vqks3wSJU1GHGSlVcWHDjsoJjC+1QMmnahmYeJHeEMvQ73PgrbhRBUNz7Gf6BmVYXrXog5HDOvck914sEV2BZH0ZmZnZufiG7mFtaXlldy69v3KgwlpQ5NBShrHtEMcED5gAHweqRZMT3BKt5/YvUr90yqXgYXMMgYq5PugHvcEpAS618udj0CfQ4JMBpn8GwYbn7uCnaISh9T3nBge3u4j37rJUv2KY1Av6fFM4/SyNUW/mXZjuksc8CoIIo1bCtCNyESP20YMNcM1YsIrRPuiwZpRriHS21cSeU+gSAR+pEHfGVGvierkzHVNNeKv7lNWLonLgJD6IYWEDHH3VigSHE6Ypwm0tGQQw0IVRyPSGmPSIJBb3InI5umaXykV2y8G/yE905NE9N+8oqVEw0RhZtoW1URDY6RhV0iarIQRTdo0f0it6MO+PBeDKex6UZ47tnE03AeP8CePmgDw==sha1_base64="byOwBQjD02xtzE+QwqMVe0rmGmU=">AAACFHicdVDLSgMxFM3UV62vqks3wSJU1CFjpSpuCm5cVrC20BlKJs3U0MyD5I5QSr/Djb/iRhEExb1/Y/pw0aoHQi7nnJvcc/1ECg2EfFmZufmFxaXscm5ldW19I7+5davjVDFeY7GMVcOnmksR8RoIkLyRKE5DX/K6370c6vV7rrSIoxvoJdwLaScSgWAUDNXKl4tuSOFOQB8E63IYNIl3iF3ZjkGbe0aLjhxvHx84F618wbHJCPj/ooAmqLbyb247ZmnII2CSat10SAJenyrztOSDnJtqnlDWpR3eH6Ua4D1DtXEQK3MiwCN2ykdDrXuhb5zDMfWsNiT/0popBGdeX0RJCjxi44+CVGKI8XBFuC0UZyB7pqBMCTMhZndUUQZmkTkTndil8olTIvh38RO9dmyf2841KVTsyQ6yaAftoiJy0CmqoCtURTXE0CN6Ru/ow3qwnqwX63VszViTnm00BevzG1wcna0= while (( k = i)(flag[k] (ticket[k],k ticket[i],i))) ; AAACSXicdVBNixNBEK3O+rHGr6hHL4VBSCAMM2ZZXTwY8OJxBeMupIfQ06nJNtPzQXfP7oYh/28Pe/Hoz9CL4smeRJFdtZqGx3tVvKqXVFpZF4afWWfnxs1bt3fvdO/eu//gYe/R44+2rI2kqSx1aY4TYUmrgqZOOU3HlSGRJ5qOkuxtqx+dkrGqLD64VUVxLpaFSpUUzlPzXjYYcDr3PhYz5AWhGvIRDngu3IlyTarFcj3LYuRntFjSH8EpmZFrpZGf0xqvCyoeqeFwiNw/5A3y9et5rx8F4abw/6D/5st4PAGAw3nvgi9KWedUOKmFtbMorFzcCONNNK27vLZUCZmJJTWbKNb43FMLTEvjf+Fww17pE7m1qzzxne3C9rrWkv/SZrVLX8WNKqraUSG3Rmmt0ZXY5ooLZUg6vfJASKP8hihPhBHS+fS7/vQwGO/vReMQ/wa/T5++CA6C6H3YnwSwrV14Cs9gABG8hAm8g0OYgoRP8I0BY+ySfWXf2Y9ta4f9mnkCV6qz8xOs4rC8sha1_base64="CBIsK/kGl+Lt+by3Fxl2402w+AI=">AAACSXicdVBNaxRBEO3eRI3r16pHL0UWYReWYcYVP/BgwEuOEdwksD0sPb01m2Z6PuiuUZdh/58HLx79GcnF4Mme3YSQqK9pKN57RVW9pDLaURj+5J2t7Vu37+zc7d67/+Dho97jJ4eurK3CiSpNaY8T6dDoAiekyeBxZVHmicGjJPvQ6kef0TpdFp9oWWGcy0WhU60keWrWywYDgV/9HAcZiAJBD8UIBiKXdKKpSY1crKZZDOILzhd4JZBWGVIrjXyfMXBT0PFID4dDEP6BaECs3s16/SgI14D/F/33p+M1Dma9b2JeqjrHgpSRzk2jsKK4kdYPMbjqitphJVUmF9iso1jBc0/NIS2t/wXBmr3mk7lzyzzxznZhd1NryX9p05rSN3Gji6omLNRmUFoboBLaXGGuLSoyS19IZbXfENSJtFKRT7/rTw+D8auX0TiEv4vL0ycvgrdB9DHs7wVsgx32jO2yAYvYa7bH9tkBmzDFfrBfnHHOv/Mzfs5/b6wdftHzlF1DZ+sPYduxSA==sha1_base64="j4E56898kWWFpkELOZqgkmgktv4=">AAACSXicdVBNaxRBEO3eGI2bxGzi0UvhIuzCMswkQSO5BLx4jOAmge1h6emt2TTT80F3jboM+/88ePHo3/CieLJnsxIS9TUNxXuvqKqXVEY7CsNvvLPxYPPho63H3e2d3Sd7vf2DC1fWVuFYlaa0V4l0aHSBY9Jk8KqyKPPE4GWSvWn1yw9onS6L97SoMM7lvNCpVpI8Ne1lg4HAT36OgwxEgaCHYgQDkUu61tSkRs6XkywG8RFnc7wVSKsMqZVGvs8YuC/oeKSHwyEI/0A0IJan014/CsIV4P9Fn61xPu19FrNS1TkWpIx0bhKFFcWNtH6IwWVX1A4rqTI5x2YVxRJeeGoGaWn9LwhW7B2fzJ1b5Il3tgu7+1pL/kub1JSexI0uqpqwUDeD0toAldDmCjNtUZFZ+EIqq/2GoK6llYp8+l1/ehgcvTyOjkL4u/hz+vgweB1E78L+WbDOYIs9Y8/ZgEXsFTtjb9k5GzPFvrIfnHHOv/Dv/Cf/dWPt8HXPU3YHnY3fRP6u5g== 9 6 ^ ⌧ {} } Lemma 3 Bakery-lock is a FIFO lock public void release () {
AAAB8HicdVDLSgMxFL1TX7W+xrp0EyxC3QwZKz5WFlzosoJjC20pmTRtQzMPkoxYhn6IG8WV4sLv8Bf8DP/ATKuL+jgQOJxzc3NO/FhwpTF+t3Jz8wuLS/nlwsrq2vqGvVm8VlEiKfNoJCLZ8IligofM01wL1oglI4EvWN0fnmV+/YZJxaPwSo9i1g5IP+Q9Tok2UscutgKiB1ynkglm9ozLex275Dp4AvQ/KZ1+nL8iAKh17LdWN6JJwEJNBVGq6eJYt1MiNaeCjQutRLGY0CHps3SSeIx2jdRFvUiaE2o0UWfmSKDUKPDNZJZP/fQy8S+vmejecTvlYZxoFtLpQ71EIB2hrD7qcsmoFiNDCJXcJER0QCSh2nxSwVTHTuXwwK1g9Jt8V/f2nRPHvcSlKoYp8rANO1AGF46gChdQAw8o3MI9PMGzpaw768F6nI7mrK87WzAD6+UTNKiSTQ==sha1_base64="C2LajEbMmu0/KyKgeFZ6syn4soA=">AAAB8HicdVDLTgIxFL2DL8TXiO7cNBIT3ExmxPhYSeJClpg4QgKEdEoHGjqPtB0jTvgQNxpXGhd+h7/g0k/wDyygC3ycpMnJObe359SLOZPKtt+MzMzs3PxCdjG3tLyyumau5y9llAhCXRLxSNQ9LClnIXUVU5zWY0Fx4HFa8/qnI792RYVkUXihBjFtBbgbMp8RrLTUNvPNAKseU6mgnOo9w+Ju2yw4lj0G+p8UTj7OXjZv3ivVtvna7EQkCWioCMdSNhw7Vq0UC8UIp8NcM5E0xqSPuzQdJx6iHS11kB8JfUKFxurUHA6kHASenhzlkz+9kfiX10iUf9RKWRgnioZk8pCfcKQiNKqPOkxQovhAE0wE0wkR6WGBidKflNPVbat0sO+UbPSbfFd396xjyzm3C2UbJsjCFmxDERw4hDJUoAouELiGO3iEJ0Mat8a98TAZzRhfdzZgCsbzJ0Mdk+Q=sha1_base64="Vd+UwuZ16yw9DL29JAcu36qwpcY=">AAAB8HicdVDLSgMxFM3UV62vsS7dBItQN8OMFR+7ghuXFRxbaEvJpHfa0MyD5I5YSj/EjeJK8Uv8Bf/GTFsXvg4EDuecJPfcIJVCo+t+WIWl5ZXVteJ6aWNza3vH3i3f6iRTHHyeyES1AqZBihh8FCihlSpgUSChGYwuc795B0qLJL7BcQrdiA1iEQrO0Eg9u9yJGA4FThRIMO9Mq0c9u+I57gz0f1IhCzR69nunn/Asghi5ZFq3PTfF7oQpFFzCtNTJNKSMj9gAJrOJp/TQSH0aJsqcGOlM/ZZjkdbjKDDJfD7908vFv7x2huF5dyLiNEOI+fyjMJMUE5rXp32hgKMcG8K4EmZCyodMMY5mSSVT3XVqpydezaW/yVd1/9i5cLxrt1J3Fzsokn1yQKrEI2ekTq5Ig/iEk3vySF7Iq6WtB+vJep5HC9bizh75BuvtEzuvkAg= flag[ThreadID.get()] := Proof If D T 1 D T 2 , ticket[T2] > ticket[T1] AAACB3icdVDLSgMxFL3js9ZX1aWbYBHqZpix4gvEgi50p2C10JaSSTNtaOZBckcopT/gxl9xo7hS3PkLfoZ/YKa1i/q4EDg559zknuvFUmh0nA9rYnJqemY2M5edX1hcWs6trF7rKFGMl1kkI1XxqOZShLyMAiWvxIrTwJP8xuucpPrNLVdaROEVdmNeD2grFL5gFA3VyG3VAoptgT1f0la/Orpdtc0jzfNTu8WxX9iqk8OjRi7v2s6gyP8gf/xZLJYA4KKRe681I5YEPEQmqdZV14mx3qMKBZO8n60lmseUdWiL9wZB+mTTUE3iR8qcEMmAHfPRQOtu4BlnOqj+qaXkX1o1QX+/3hNhnCAP2fAjP5EEI5JuhTSF4gxl1wDKlDATEtamijI0u8ua6I5d3N1xiw75DUbRy9v2ge1eOvmSDcPKwDpsQAFc2IMSnMEFlIHBPTzCC7xad9aD9WQ9D60T1nfPGoyV9fYFHWKa+A==sha1_base64="pWbJm3GajI1+amMS+rzqjbBPoXY=">AAACB3icdVDLSgMxFM34rPVVdekmWIR2M8xY8QViQRe6q9CxhbaUTJppQzMPkjtCKf0BN/6KG8WV4s5f8DP8AzNTu6iPA4GTc+5N7rluJLgCy/owZmbn5hcWM0vZ5ZXVtfXcxuaNCmNJmUNDEcq6SxQTPGAOcBCsHklGfFewmts/T/zaLZOKh0EVBhFr+aQbcI9TAlpq54pNn0CPw9ATpDtqTG7Vnn6kc3VhdhmMCsUWPjlt5/K2aaXA/5P82WcpRaWde292Qhr7LAAqiFIN24qgNSQSOBVslG3GikWE9kmXDdMgI7yrpQ72QqlPADhVp+qIr9TAd3VlMqj66SXiX14jBu+oNeRBFAML6PgjLxYYQpxsBXe4ZBTEQBNCJdcTYtojklDQu8vq6JZZOti3Sxb+TSbRnT3z2LSvrXzZRGNk0DbaQQVko0NURpeoghxE0T16RC/o1bgzHown43lcOmN892yhKRhvX9JMm4Q=sha1_base64="1JvX2MyvRenmA4gvL4+Uw0l2wNc=">AAACB3icdVDLSgMxFM3UV62vUZdugkVoN8OMFV8gFHShuwodW2iHkkkzbWjmQXJHKKU/4MZfcaO4Utz5C/6N6WtRHxcCJ+ecm9xz/URwBbb9ZWQWFpeWV7KrubX1jc0tc3vnTsWppMylsYhl3SeKCR4xFzgIVk8kI6EvWM3vXY702j2TisdRFfoJ80LSiXjAKQFNtcxiMyTQ5TAIBOkMG7Nbtasfad9cWR0Gw0LRw+cXLTPvWPa48P8gj6ZVaZmfzXZM05BFQAVRquHYCXgDIoFTwYa5ZqpYQmiPdNhgHGSIDzTVxkEs9YkAj9k5HwmV6oe+do4GVT+1EfmX1kghOPUGPEpSYBGdfBSkAkOMR1vBbS4ZBdHXgFDJ9YSYdokkFPTucjq6bZWOj5ySjX+DWXT30DqznFs7X7amO8iiPbSPCshBJ6iMrlEFuYiiR/SM3tC78WA8GS/G68SaMaY9u2iujI9vtW+ZIg== false; ! } so T 2 cannot enter CS while flag [ T 1 ] . } Corollary Bakery-lock is starvation-free Surely we can do better… A New Hope
Theorem Deadlock-free mutual exclusion among How can we do better? N threads requires at least N multi-reader/ single-writer (MRSW) registers. Use hardware to support atomic operations beyond load and store
Theorem Deadlock-free mutual exclusion among Define higher-level programming abstractions that leverage hardware support N threads requires at least N multi-reader/ multi-writer (MRMW) registers.
58
Only Disabling Interrupts uni- Only Disabling Interrupts: uni- processors processors on for Mutual Exclusion on A Refinement
Use a variable to implement the lock; enforce lock.acquire() { disable interrupts} mutual exclusion only on the operations that test and modify that variable lock.release() { enable interrupts} class lock { int value := FREE } lock.acquire() { lock.release() { Simple, but flawed disableInterrupts(); disableInterrupts(); while (value == BUSY) { value := FREE; thread may never give up CPU! enableInterrupts(); enableInterrupts(); Thou disableInterrupts(); busy } } ShalT wait even if it does, it could it take too long to value := BUSY; not respond to an interrupt enableInterrupts(); Busy-waits! } 59 60 Only Lock Implementation: uni- Also Atomic multi- processors processors on Uniprocessor for Read/Modify/Write
If lock is BUSY, wait on a queue and switch to On a multiprocessor, disabling interrupts does not ensure atomicity another process other CPUs could still enter the critical section class lock { int value := FREE } costly to disable interrupts on all CPUs lock.acquire() { disableInterrupts(); Hardware provides special machine instructions if (value == BUSY) { lock.release() { current->state = WAITING disableInterrupts; Te st- a n d - S et ( TA S) waiting.Add(current); if (!waiting.Empty()) { reads in a register the value of a memory location, writes back TRUE in its place next = scheduler(); next = waiting.Remove(); next->state = RUNNING; next->state = READY; TAS (value, r): r := value; value := TRUE (r is usually not explicit) readyQueue.add(next); h i ctx_switch(¤t->sp, next->sp); Compare-and-Swap (CAS) bool CAS (*int p, int old, int new) { current = next; } else { if *p ≠ old return FALSE; compares contents of a memory location to given value; } else { value := FREE; *p := new; who’s returning? } if same, sets memory location to a new given value return TRUE value := BUSY; } } enableInterrupts(); Many others (e.g. Load Link Store Conditional) enableInterrupts(); } } 61 62
Spinlocks How Many Spinlocks?
A lock where the lockValue := FREE Various data structures need safe concurrent processor waits in a access, e.g., tight loop for the spinLock.acquire() { list of threads waiting on lock I lock to become free while (TAS(lockValue) ==BUSY ; list of threads waiting on lock J lock should be held } ready queue for a short time spinLock.release() { used to protect CPU lockValue := FREE; One spinlock for the entire kernel? Bottleneck! scheduler and } implement more Instead general locks *well, certainly Thou not for the one spinlock per lock ShalT busy time needed wait* to complete one spinlock for ready queue Busy-waits!not an arbitrarily long CS! Per-core ready list: one spinlock per core Lock Implementation: Lock Implementation: Multiprocessor Multiprocessor
suspend(SpinLock ∗lock) { lock.acquire() { lock.release() { struct PCB ∗next; makeReady(struct PCB ∗thread) { disableInterrupts(); disableInterrupts(); disableInterrupts(); spinLock.acquire(); spinLock.acquire(); disableInterrupts(); schedSpinLock.acquire(); if (value == BUSY) { if (!waiting.Empty()) { schedSpinLock.acquire(); readyQueue.add(thread); next = waiting.Remove() thread >state = READY; waiting.Add(current); lock−>release(); − suspend(&spinlock); makeReady(next); schedSpinLock.release(); current−>state = WAITING; } else { } else { enableInterrupts(); value = BUSY; value := FREE; next = scheduler(); } } } next->state = RUNNING: spinLock.release(); spinLock.release(); ctx_switch(current, next); enableInterrupts(); enableInterrupts; current = next; } } schedSpinLock.release(); enableInterrupts(); } 65 66
S Semaphores (Dijkstra, 1962)
E Introduced in THE Operating System M catchy name… A Stateful Interface P a non-negative integer Init (starting value) (count) H P(): decrement Probeer (“Try”) O a lock procure a queue V(): increment Verhoog (“+1”) R vacate E No operation to read the semaphore’s value S N U J V NONE! 67 68 Semantics of P and V Semaphore’s count
Must be initialized P(): P() { wait until count > 0 while (n = 0); Maintains the semaphore’s state n := n-1; Reflects sequence of past P, V operations when so, decrement count by 1 } Positive value indicates how many future P operations will succeed
V(): V() { Important increment count by 1 n := n+1; It is not possible to read the count } It is not possible to increase or decrease the count but through P and V Binary Semaphores: count can be either 0 or 1 It is not possible to increment/decrement by more than 1 69 70
Implementing Semaphores with semaphores interrupts
Been there, done that: class Semaphore { int value := k } by enabling/disabling interrupts Semaphore.P() { Disable interrupts; by using TAS while (value == 0) { Semaphore.V() { Enable interrupts; Disable interrupts; with a queue, to avoid busy waiting Disable interrupts; value := value + 1; } Enable interrupts; value := value - 1; } Enable interrupts; }
71 72 Semaphores using TAS P() vs lock.acquire()
class Semaphore { int value := k } Semaphore.P() { lock.acquire() { disableinterrupts(); disableInterrupts(); Semaphore.P() { Semaphore.V() { spinLock.acquire(); spinLock.acquire(); disableinterrupts(); disableinterrupts(); if (value == 0) { if (value == BUSY) { spinLock.acquire(); spinLock.acquire(); waiting.Add(current); waiting.Add(current); if (value == 0) { if (!waiting.Empty()) { suspend(&spinlock); suspend(&spinlock); waiting.Add(current); next = waiting.Remove() } else { } else { suspend(&spinlock); makeReady(next); value := value - 1; value = BUSY; } else { } else { } } value := value - 1; value := value + 1; spinLock.release(); spinLock.release(); } } enableInterrupts(); enableInterrupts(); spinLock.release(); spinLock.release(); } } enableInterrupts(); enableInterrupts; } } 73 74
V() vs lock.release() How to use Semaphores
Binary semaphores good for Mutual Exclusion Semaphore.V() { lock.release() { disableinterrupts(); disableInterrupts(); spinLock.acquire(); spinLock.acquire(); Semaphore S if (!waiting.Empty()) { if (!waiting.Empty()) { S.init(1) next = waiting.Remove() next = waiting.Remove() makeReady(next); makeReady(next); } else { } else { T1 T2 value := value + 1; value := FREE; } } S.P(); S.P(); spinLock.release(); spinLock.release(); CriticalSection(); CriticalSection(); enableInterrupts; enableInterrupts; S.V(); S.V(); } }
75 76 Producer-Consumer How to use Semaphores with Bounded Buffer 0 N-1 Counting semaphores good for signaling or counting resources One thread performs P() to await an event in out Another thread performs V() to inform waiting A set of producer and consumer threads thread that event has occurred communicate through a buffer of size N
Semaphore packetarrived producer inserts resources into the buffer (writes to packetarrived.init(0) “in” and moves right)
T1 T2 disk blocks, output, memory pages, characters… consumer removes resources from the buffer (reads from pkt := getpacket(); packetarrived.P(); out and moves right) enqueue(pcketq, pkt); pkt := dequeue(packetq) packjetarrived.V() print(pkt); Producer and consumer execute at different rates 77 78
How to go about Safety this problem
Sequence of consumed values is a prefix of Are there shared variables? If so, we’ll need the sequence of produced values to make sure the code accessing them is in a critical section Let variable in (shared by producers) AAAB3nicdVDLSgMxFL1TX7W+qi7dBIvgaphR8bHRghuXVRxbaEvNpJk2NJMZkjtCKV27UVwpfpK/4G/4BaatLurjwIXDOeeSexKmUhj0vHcnNzM7N7+QXywsLa+srhXXN25MkmnGA5bIRNdCargUigcoUPJaqjmNQ8mrYe985FfvuDYiUdfYT3kzph0lIsEoWulKsVax5LveGOR/Ujr7iKJbAKi0im+NdsKymCtkkhpT970UmwOqUTDJh4VGZnhKWY92+GB835DsWKlNokTbUUjG6lSOxsb049AmY4pd89MbiX959Qyj4+ZAqDRDrtjkoSiTBBMyKkvaQnOGsm8JZVrYCwnrUk0Z2i8p2Oqeu3944O975Df5rh7suSeuf+mVyqcwQR62YBt2wYcjKMMFVCAABhE8wDO8ONS5dx6dp0k053ztbMIUnNdPJKGLZg==sha1_base64="GkYpHv5/UsAbEGx8pi2dl/LDSmk=">AAAB3nicdVDLSgMxFL1TX7W+qi7dBIvgapix4mOjBTcuq1hbaEvJpJk2NJMZkjtCKV27UVwpfpK/4G/4BaZTXdTHgQuHc84l9yRIpDDoee9Obm5+YXEpv1xYWV1b3yhubt2aONWM11gsY90IqOFSKF5DgZI3Es1pFEheDwYXE79+x7URsbrBYcLbEe0pEQpG0UrXinWKJd/1MpD/Sen8I8xQ7RTfWt2YpRFXyCQ1pul7CbZHVKNgko8LrdTwhLIB7fFRdt+Y7FmpS8JY21FIMnUmRyNjhlFgkxHFvvnpTcS/vGaK4Ul7JFSSIlds+lCYSoIxmZQlXaE5Qzm0hDIt7IWE9ammDO2XFGx1zy0fHfplj/wm39VrB+6p6195pcoZTJGHHdiFffDhGCpwCVWoAYMQHuAZXhzq3DuPztM0mnO+drZhBs7rJ7gkjJ4=sha1_base64="jvD6jTyYFkOhi/GSJMybx6qd51A=">AAAB3nicdVDLSgMxFL1TX7W+qi7dBIvgapixxcdGCm5cVnFsoS0lk2ba0ExmSO4IpXTtRnGl+En+gn9j+nBRHwcCh3NOuPfcMJXCoOd9Orml5ZXVtfx6YWNza3unuLt3b5JMMx6wRCa6EVLDpVA8QIGSN1LNaRxKXg8HVxO//sC1EYm6w2HK2zHtKREJRtFKt4p1iiXf9aYg/5MSzFHrFD9a3YRlMVfIJDWm6XsptkdUo2CSjwutzPCUsgHt8dF0vzE5slKXRIm2TyGZqgs5GhszjEObjCn2zU9vIv7lNTOMztsjodIMuWKzQVEmCSZkUpZ0heYM5dASyrSwGxLWp5oytCcp2OqeWz6t+GWP/Cbf1YMT98L1b7xS9XJ+gzwcwCEcgw9nUIVrqEEADCJ4gld4c6jz6Dw7L7Nozpn/2YcFOO9fDHeJCQ== nc = number consumed
np AAAB3nicdVDLSgMxFL1TX7W+qi7dBIvgaphR8bHRghuXVRxbaEvNpJk2NJMZkjtCKV27UVwpfpK/4G/4BaatLurjwIXDOeeSexKmUhj0vHcnNzM7N7+QXywsLa+srhXXN25MkmnGA5bIRNdCargUigcoUPJaqjmNQ8mrYe985FfvuDYiUdfYT3kzph0lIsEoWulKpa1iyXe9Mcj/pHT2EUW3AFBpFd8a7YRlMVfIJDWm7nspNgdUo2CSDwuNzPCUsh7t8MH4viHZsVKbRIm2o5CM1akcjY3px6FNxhS75qc3Ev/y6hlGx82BUGmGXLHJQ1EmCSZkVJa0heYMZd8SyrSwFxLWpZoytF9SsNU9d//wwN/3yG/yXT3Yc09c/9IrlU9hgjxswTbsgg9HUIYLqEAADCJ4gGd4cahz7zw6T5Nozvna2YQpOK+fN8aLcw==sha1_base64="9aJJXZI+RPZqAYVWMg10FIy05Z8=">AAAB3nicdVDLSgMxFL1TX7W+qi7dBIvgapix4mOjBTcuq1hbaEvJpJk2NJMZkjtCKV27UVwpfpK/4G/4BaZTXdTHgQuHc84l9yRIpDDoee9Obm5+YXEpv1xYWV1b3yhubt2aONWM11gsY90IqOFSKF5DgZI3Es1pFEheDwYXE79+x7URsbrBYcLbEe0pEQpG0UrXKukUS77rZSD/k9L5R5ih2im+tboxSyOukElqTNP3EmyPqEbBJB8XWqnhCWUD2uOj7L4x2bNSl4SxtqOQZOpMjkbGDKPAJiOKffPTm4h/ec0Uw5P2SKgkRa7Y9KEwlQRjMilLukJzhnJoCWVa2AsJ61NNGdovKdjqnls+OvTLHvlNvqvXDtxT17/ySpUzmCIPO7AL++DDMVTgEqpQAwYhPMAzvDjUuXcenadpNOd87WzDDJzXT8tJjKs=sha1_base64="jJrDk+YFvmLRC/geHw72PGYSyac=">AAAB3nicdVDLSgMxFL1TX7W+qi7dBIvgapixxcdGCm5cVnFsoS0lk2ba0ExmSO4IpXTtRnGl+En+gn9j+nBRHwcCh3NOuPfcMJXCoOd9Orml5ZXVtfx6YWNza3unuLt3b5JMMx6wRCa6EVLDpVA8QIGSN1LNaRxKXg8HVxO//sC1EYm6w2HK2zHtKREJRtFKtyrtFEu+601B/iclmKPWKX60ugnLYq6QSWpM0/dSbI+oRsEkHxdameEpZQPa46PpfmNyZKUuiRJtn0IyVRdyNDZmGIc2GVPsm5/eRPzLa2YYnbdHQqUZcsVmg6JMEkzIpCzpCs0ZyqEllGlhNySsTzVlaE9SsNU9t3xa8cse+U2+qwcn7oXr33il6uX8Bnk4gEM4Bh/OoArXUIMAGETwBK/w5lDn0Xl2XmbRnDP/sw8LcN6/AB+ciRY= = number produced variable out (shared by consumers) N = size of buffer, then maintain the following invariant: the buffer (shared by all)
0 np nc How many locks we need? AAAB73icdVDLSgMxFL3js9bXVJdugkVw45Cx4mNl0YUuKzi20JaSSTNtaCYzJBmllP6HG6UrxT/xF1z6C36BM60u6uPAhcM555J74seCa4PxmzUzOze/sJhbyi+vrK6t24WNGx0lijKPRiJSNZ9oJrhknuFGsFqsGAl9wap+7zzzq7dMaR7Ja9OPWTMkHckDTolJpZZdwKghGJIx2kOSZrxlF10Hj4H+J8XTj/eLEQBUWvZrox3RJGTSUEG0rrs4Ns0BUYZTwYb5RqJZTGiPdNhgfPAQ7aRSGwWRSkcaNFanciTUuh/6aTIkpqt/epn4l1dPTHDcHHAZJ4ZJOnkoSAQyEcraozZXjBrRTwmhiqcXItolilCT/lE+rY6d0uGBW8LoN/mu7u07J457hYvlM5ggB1uwDbvgwhGU4RIq4AGFO3iAJ3i2lHVvPVqjSXTG+trZhClYL5/p8JECsha1_base64="Vp90/iVWAtPh19qTYgk358X90zc=">AAAB73icdVDLTgIxFO3gC/E1qDs3jcTEjZOOGB8riS50iYkjJEBIp3SgodOZtB0NEv7DjcaVxo3f4S+45Bf8AjugC3yc5CYn55yb3lM/5kxphN6tzNT0zOxcdj63sLi0vGLnV69UlEhCPRLxSFZ9rChngnqaaU6rsaQ49Dmt+N3T1K9cU6lYJC51L6aNELcFCxjB2khNO49gnVMoYrgDBUl50y64DhoB/k8Kxx/Ds9f122G5ab/VWxFJQio04Vipmoti3ehjqRnhdJCrJ4rGmHRxm/ZHBw/glpFaMIikGaHhSJ3I4VCpXuibZIh1R/30UvEvr5bo4LDRZyJONBVk/FCQcKgjmLaHLSYp0bxnCCaSmQsh6WCJiTZ/lDPVkVPc33OLCP4m39W9XefIcS9QoXQCxsiCDbAJtoELDkAJnIMy8AABN+AePIFnS1p31oP1OI5mrK+dNTAB6+UT1fySfw==sha1_base64="erKf//9lwmBsQRe0hCliiBYuggQ=">AAAB73icdVDLSgMxFL3js9bXVJdugkVw45Cx4mNXdOOygmMLbSmZNNOGZjJDklFK6X+4UVwp/om/4N+YaeuiPg4EDueccO+5YSq4Nhh/OguLS8srq4W14vrG5ta2W9q500mmKAtoIhLVCIlmgksWGG4Ea6SKkTgUrB4OrnK/fs+U5om8NcOUtWPSkzzilBgrddwSRi3BkEzREZI05x237Ht4AvQ/KcMMtY770eomNIuZNFQQrZs+Tk17RJThVLBxsZVplhI6ID02miw8RgdW6qIoUfZJgybqXI7EWg/j0CZjYvr6p5eLf3nNzETn7RGXaWaYpNNBUSaQSVDeHnW5YtSIoSWEKm43RLRPFKHG3qhoq2OvcnriVzD6Tb6rB8feheff4HL1cnaDAuzBPhyCD2dQhWuoQQAUHuAJXuHNUc6j8+y8TKMLzuzPLszBef8CBgOOCQ== N
79 80 Step 1: Guard Shared Step 1: Guard Shared Resources Resources* *with Semaphores Shared: Shared: Implement mutual int buf[N]; Invariant int buf[N]; exclusion with a binary int in := 0, out := 0; 0 np nc int in := 0, out := 0;
AAAB73icdVDLSgMxFL3js9bXVJdugkVw45Cx4mNl0YUuKzi20JaSSTNtaCYzJBmllP6HG6UrxT/xF1z6C36BM60u6uPAhcM555J74seCa4PxmzUzOze/sJhbyi+vrK6t24WNGx0lijKPRiJSNZ9oJrhknuFGsFqsGAl9wap+7zzzq7dMaR7Ja9OPWTMkHckDTolJpZZdwKghGJIx2kOSZrxlF10Hj4H+J8XTj/eLEQBUWvZrox3RJGTSUEG0rrs4Ns0BUYZTwYb5RqJZTGiPdNhgfPAQ7aRSGwWRSkcaNFanciTUuh/6aTIkpqt/epn4l1dPTHDcHHAZJ4ZJOnkoSAQyEcraozZXjBrRTwmhiqcXItolilCT/lE+rY6d0uGBW8LoN/mu7u07J457hYvlM5ggB1uwDbvgwhGU4RIq4AGFO3iAJ3i2lHVvPVqjSXTG+trZhClYL5/p8JECsha1_base64="Vp90/iVWAtPh19qTYgk358X90zc=">AAAB73icdVDLTgIxFO3gC/E1qDs3jcTEjZOOGB8riS50iYkjJEBIp3SgodOZtB0NEv7DjcaVxo3f4S+45Bf8AjugC3yc5CYn55yb3lM/5kxphN6tzNT0zOxcdj63sLi0vGLnV69UlEhCPRLxSFZ9rChngnqaaU6rsaQ49Dmt+N3T1K9cU6lYJC51L6aNELcFCxjB2khNO49gnVMoYrgDBUl50y64DhoB/k8Kxx/Ds9f122G5ab/VWxFJQio04Vipmoti3ehjqRnhdJCrJ4rGmHRxm/ZHBw/glpFaMIikGaHhSJ3I4VCpXuibZIh1R/30UvEvr5bo4LDRZyJONBVk/FCQcKgjmLaHLSYp0bxnCCaSmQsh6WCJiTZ/lDPVkVPc33OLCP4m39W9XefIcS9QoXQCxsiCDbAJtoELDkAJnIMy8AABN+AePIFnS1p31oP1OI5mrK+dNTAB6+UT1fySfw==sha1_base64="erKf//9lwmBsQRe0hCliiBYuggQ=">AAAB73icdVDLSgMxFL3js9bXVJdugkVw45Cx4mNXdOOygmMLbSmZNNOGZjJDklFK6X+4UVwp/om/4N+YaeuiPg4EDueccO+5YSq4Nhh/OguLS8srq4W14vrG5ta2W9q500mmKAtoIhLVCIlmgksWGG4Ea6SKkTgUrB4OrnK/fs+U5om8NcOUtWPSkzzilBgrddwSRi3BkEzREZI05x237Ht4AvQ/KcMMtY770eomNIuZNFQQrZs+Tk17RJThVLBxsZVplhI6ID02miw8RgdW6qIoUfZJgybqXI7EWg/j0CZjYvr6p5eLf3nNzETn7RGXaWaYpNNBUSaQSVDeHnW5YtSIoSWEKm43RLRPFKHG3qhoq2OvcnriVzD6Tb6rB8feheff4HL1cnaDAuzBPhyCD2dQhWuoQQAUHuAJXuHNUc6j8+y8TKMLzuzPLszBef8CBgOOCQ== N lock: in_lock, out_lock lock: in_lock, out_lock semaphore initialized to 1
// remove item from buffer // remove item from buffer // add item to buffer int consume() { // add item to buffer int consume() { void produce(int item) { out_lock.acquire(); void produce(int item) { out_lock.acquire(); in_lock.acquire(); int item := buf[out]; in_lock.acquire(); int item := buf[out%N]; buf[in] := item; out := (out+1)%N; buf[in%N] := item; out := out+1; in := (in+1)%N out_lock.release(); in := in+1; out_lock.release(); in_lock.release(); return(item); in_lock.release(); return(item); } } } }
81 82
Step 1: Guard Shared Step 1: Guard Shared Resources* Resources* *with Semaphores *with Semaphores Shared: Shared: Implement mutual Implement mutual int buf[N]; int buf[N]; exclusion with a binary exclusion with a binary int in := 0, out := 0; int in := 0, out := 0; Semaphore mutex_in(1), mutex_out(1); semaphore initialized to 1 Semaphore mutex_in(1), mutex_out(1); semaphore initialized to 1
// remove item from buffer // remove item from buffer // add item to buffer int consume() { // add item to buffer int consume() { void produce(int item) { out_lock.acquire(); void produce(int item) { out_lock.acquire(); in_lock.acquire(); int item := buf[out%N]; mutex_in.P(); int item := buf[out%N]; buf[in%N] := item; out := out+1; buf[in%N] := item; out := out+1; in := in+1; out_lock.release(); in := in+1; out_lock.release(); in_lock.release(); return(item); mutex_in.V(); return(item); } } } }
83 84 Step 1: Guard Shared Step 1: Coordinate Actions Resources* *with Semaphores Shared: Shared: Implement mutual Need a full buffer entry to int buf[N]; int buf[N]; exclusion with a binary remove an item; and an empty int in := 0, out := 0; int in := 0, out := 0; Semaphore mutex_in(1), mutex_out(1); semaphore initialized to 1 Semaphore mutex_in(1), mutex_out(1); one to add an item
// remove item from buffer // remove item from buffer // add item to buffer int consume() { // add item to buffer int consume() { void produce(int item) { mutex_out.P(); void produce(int item) { mutex_out.P(); mutex_in.P(); int item := buf[out%N]; mutex_in.P(); int item := buf[out%N]; buf[in%N] := item; out := out+1; buf[in%N] := item; out := out+1; in := in+1; mutex_out.V(); in := in+1; mutex_out.V(); mutex_in.V(); return(item); mutex_in.V(); return(item); } } } }
85 86
Step 1: Coordinate Actions Step 1: Coordinate Actions*
*with Semaphores Shared: Shared: int buf[N]; int buf[N]; Need a full buffer entry to Use two counting semaphores: int in := 0, out := 0; int in := 0, out := 0; remove an item; and an empty one to count empty entries, Semaphore mutex_in(1), mutex_out(1); Semaphore mutex_in(1), mutex_out(1); one to add an item one to count full Condition empty, full; Condition empty, full;
// remove item from buffer // remove item from buffer // add item to buffer int consume() { // add item to buffer int consume() { void produce(int item) { wait(full); void produce(int item) { wait(full); wait(empty); mutex_out.P(); wait(empty); mutex_out.P(); mutex_in.P(); int item := buf[out%N]; mutex_in.P(); int item := buf[out%N]; buf[in%N] := item; out := out+1; buf[in%N] := item; out := out+1; in := in+1; mutex_out.V(); in := in+1; mutex_out.V(); mutex_in.V(); signal(empty); mutex_in.V(); signal(empty); signal(full); return(item); signal(full); return(item); } } 87 } 88 } Step 1: Coordinate Actions* Step 1: Coordinate Actions*
*with Semaphores *with Semaphores Shared: Shared: int buf[N]; int buf[N]; Use two counting semaphores: Use two counting semaphores: int in := 0, out := 0; int in := 0, out := 0; one to count empty entries, one to count empty entries, Semaphore mutex_in(1), mutex_out(1); Semaphore mutex_in(1), mutex_out(1); one to count full one to count full Semaphore empty(N), full(0); Semaphore empty(N), full(0);
// remove item from buffer // remove item from buffer // add item to buffer int consume() { // add item to buffer int consume() { void produce(int item) { wait(full); void produce(int item) { wait(full) wait(empty); mutex_out.P(); empty.P(); mutex_out.P(); mutex_in.P(); int item := buf[out%N]; mutex_in.P(); int item := buf[out%N]; buf[in%N] := item; out := out+1; buf[in%N] := item; out := out+1; in := in+1; mutex_out.V(); in := in+1; mutex_out.V(); mutex_in.V(); signal(empty); mutex_in.V(); signal(empty); signal(full); return(item); signal(full); return(item); } } 89 } 90 }
Step 1: Coordinate Actions* Step 1: Coordinate Actions*
*with Semaphores *with Semaphores Shared: Shared: int buf[N]; int buf[N]; Use two counting semaphores: Use two counting semaphores: int in := 0, out := 0; int in := 0, out := 0; one to count empty entries, one to count empty entries, Semaphore mutex_in(1), mutex_out(1); Semaphore mutex_in(1), mutex_out(1); one to count full one to count full Semaphore empty(N), full(0); Semaphore empty(N), full(0);
// remove item from buffer // remove item from buffer // add item to buffer int consume() { // add item to buffer int consume() { void produce(int item) { wait(full) void produce(int item) { full.P(); empty.P(); mutex_out.P(); empty.P(); mutex_out.P(); mutex_in.P(); int item := buf[out%N]; mutex_in.P(); int item := buf[out%N]; buf[in%N] := item; out := out+1; buf[in%N] := item; out := out+1; in := in+1; mutex_out.V(); in := in+1; mutex_out.V(); mutex_in.V(); signal(empty); mutex_in.V(); empty.V(); full.V(); return(item); full.V(); return(item); } } 91 } 92 } Musings on Step 1: Coordinate Actions* Producer/Consumer *with Semaphores Shared: We used two semaphores because Isint buf[N];there a V for every P? we used two different variables (in int in := 0, out := 0; & out) accessed solely by producers Shared: Semaphore mutex_in(1), mutex_out(1); and consumers respectively int buf[N]; Semaphore empty(N), full(0); int in := 0, out := 0; if we used variables changed by both Semaphore mutex_in(1), mutex_out(1); Semaphore empty(N), full(0); Are mutexes initialized// remove to item 1? from buffer producers and consumers, we would // add item to buffer int consume() { have have had to use a single // remove item from buffer void produce(int item) { full.P(); semaphore // add item to buffer int consume() { void produce(int item) { empty.P(); mutex_out.P(); full.P(); sacrificing concurrency empty.P(); mutex_in.P(); mutex_out.P(); item := buf[out]; mutex_in.P(); int item := buf[out%N]; Do mutexes buf[in] := item; P&V in the out same := (out+1)%N; thread? Extracting more concurrency buf[in%N] := item; out := out+1; in := (in+1)%N; in := in+1; mutex_out.V(); increases complexity mutex_out.V(); mutex_in.V(); mutex_in.V(); empty.V(); empty.V(); full.V(); only do so if the return in return(item); full.V(); return(item); } performance is worth it! } } 93 94 }
Readers-Writers Fairness questions
Models access to an object (e.g., a database), shared among several threads Suppose a writer is active, and a combination of readers and writers arrive some threads only read the object Who should get in next?
others only write it Suppose that a writer is waiting, and an Safety endless stream of readers arrives Who should get in next? (#r 0) (0 #w 1) (#r>0) (#w =0)) ^ ^ )
95 96 Readers-Writers Musings on Solution Readers/Writers int read() { Shared: Semaphore rOw provides mutex rcount_mutex.P(); int rcount = 0; between readers and writers Semaphore rcount_mutex (1); rcount := rcount+1; if (rcount = 1) then writers always rOw.P() / rOw.V() int read() { Semaphore rOw_lock(1); rcount_mutex.P(); rOw_lock.P(); if I am the void write() { first reader, readers do so only when rcount rcount := rcount+1; rOw_lock.P(); rcount_mutex.V(); P() to enforce if (rcount == 1) then invariant transitions from 0 to 1 or from 1 to 0 … rOw_lock.P(); void write() { … /* Perform write */ rcount_mutex.V(); … rOw_lock.P(); /* Perform read */ If a writer is writing, where are … rOw_lock.V(); … … readers waiting? /* Perform read */ } /* Perform write */ rcount_mutex.P(); … … rcount := rcount-1; Once a writer exits, all readers rcount_mutex.P(); rcount := rcount-1; rOw_lock.V(); if (rcount = 0) then can fall through if (rcount == 0) then if I am the rOw.lock.V(); } rOw.lock.V(); last reader, Which reader gets to go first? Shared: rcount_mutex.V(); V() to indicate rcount_mutex.V(); int rcount = 0; CS is empty Are all readers guaranteed to fall } } Semaphore rcount_mutex (1); 97 through? 98 Semaphore rOw_lock(1);
More Musings on Classic Mistakes
Readers/Writers with Semaphores N U J V
Ti P(S) Ti stuck on 2nd P(). Subsequent CS int read() { processes hopelessly pile on 1st P() rcount_mutex.P(); P(S) void write() { rcount := rcount+1; If readers and writers are waiting, rOw_lock.P(); if (rcount == 1) then and a writer exits, who goes first? … rOw_lock.P(); Undermines mutex: /* Perform write */ Tj rcount_mutex.V(); V(S) • Tj does not get permission via P() … Why do readers use a mutex? … CS rOw_lock.V(); • “extra” V() allows other processes into /* Perform read */ } V(S) CS inappropriately Why don’t writers use a mutex? … rcount_mutex.P(); rcount := rcount-1; Tl if (rcount == 0) then P(S) Conditional code can change code rOw.lock.V(); Shared: if (x) return; flow in the CS. Caused by code rcount_mutex.V(); int rcount = 0; CS updates (bug fixes, etc.) by someone } Semaphore rcount_mutex (1); V(S) other than original author of code. 99 Semaphore rOw_lock(1); 100