Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // |reftest| skip |
michael@0 | 2 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | //----------------------------------------------------------------------- |
michael@0 | 8 | |
michael@0 | 9 | var summary = "Lamport Bakery's algorithm for mutual exclusion"; |
michael@0 | 10 | // Adapted from pseudocode in Wikipedia: |
michael@0 | 11 | // http://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm |
michael@0 | 12 | |
michael@0 | 13 | printStatus(summary); |
michael@0 | 14 | |
michael@0 | 15 | var N = 15; // Number of threads. |
michael@0 | 16 | var LOOP_COUNT = 10; // Number of times each thread should loop |
michael@0 | 17 | |
michael@0 | 18 | function range(n) { |
michael@0 | 19 | for (let i = 0; i < n; i++) |
michael@0 | 20 | yield i; |
michael@0 | 21 | } |
michael@0 | 22 | |
michael@0 | 23 | function max(a) { |
michael@0 | 24 | let x = Number.NEGATIVE_INFINITY; |
michael@0 | 25 | for each (let i in a) |
michael@0 | 26 | if (i > x) |
michael@0 | 27 | x = i; |
michael@0 | 28 | return x; |
michael@0 | 29 | } |
michael@0 | 30 | |
michael@0 | 31 | // the mutex mechanism |
michael@0 | 32 | var entering = [false for (i in range(N))]; |
michael@0 | 33 | var ticket = [0 for (i in range(N))]; |
michael@0 | 34 | |
michael@0 | 35 | // the object being protected |
michael@0 | 36 | var counter = 0; |
michael@0 | 37 | |
michael@0 | 38 | function lock(i) |
michael@0 | 39 | { |
michael@0 | 40 | entering[i] = true; |
michael@0 | 41 | ticket[i] = 1 + max(ticket); |
michael@0 | 42 | entering[i] = false; |
michael@0 | 43 | |
michael@0 | 44 | for (let j = 0; j < N; j++) { |
michael@0 | 45 | // If thread j is in the middle of getting a ticket, wait for that to |
michael@0 | 46 | // finish. |
michael@0 | 47 | while (entering[j]) |
michael@0 | 48 | ; |
michael@0 | 49 | |
michael@0 | 50 | // Wait until all threads with smaller ticket numbers or with the same |
michael@0 | 51 | // ticket number, but with higher priority, finish their work. |
michael@0 | 52 | while ((ticket[j] != 0) && ((ticket[j] < ticket[i]) || |
michael@0 | 53 | ((ticket[j] == ticket[i]) && (i < j)))) |
michael@0 | 54 | ; |
michael@0 | 55 | } |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | function unlock(i) { |
michael@0 | 59 | ticket[i] = 0; |
michael@0 | 60 | } |
michael@0 | 61 | |
michael@0 | 62 | function worker(i) { |
michael@0 | 63 | for (let k = 0; k < LOOP_COUNT; k++) { |
michael@0 | 64 | lock(i); |
michael@0 | 65 | |
michael@0 | 66 | // The critical section |
michael@0 | 67 | let x = counter; |
michael@0 | 68 | sleep(0.003); |
michael@0 | 69 | counter = x + 1; |
michael@0 | 70 | |
michael@0 | 71 | unlock(i); |
michael@0 | 72 | } |
michael@0 | 73 | return 'ok'; |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | function makeWorker(id) { |
michael@0 | 77 | return function () { return worker(id); }; |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | var expect; |
michael@0 | 81 | var actual; |
michael@0 | 82 | |
michael@0 | 83 | if (typeof scatter == 'undefined' || typeof sleep == 'undefined') { |
michael@0 | 84 | print('Test skipped. scatter or sleep not defined.'); |
michael@0 | 85 | expect = actual = 'Test skipped.'; |
michael@0 | 86 | } else { |
michael@0 | 87 | scatter([makeWorker(i) for (i in range(N))]); |
michael@0 | 88 | |
michael@0 | 89 | expect = "counter: " + (N * LOOP_COUNT); |
michael@0 | 90 | actual = "counter: " + counter; |
michael@0 | 91 | } |
michael@0 | 92 | |
michael@0 | 93 | reportCompare(expect, actual, summary); |