10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Copyright 2006-2008 the V8 project authors. All rights reserved. 2563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// Redistribution and use in source and binary forms, with or without 3563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// modification, are permitted provided that the following conditions are 4563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// met: 5563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// 6563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// * Redistributions of source code must retain the above copyright 7563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// notice, this list of conditions and the following disclaimer. 8563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// * Redistributions in binary form must reproduce the above 9563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// copyright notice, this list of conditions and the following 10563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// disclaimer in the documentation and/or other materials provided 11563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// with the distribution. 12563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// * Neither the name of Google Inc. nor the names of its 13563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// contributors may be used to endorse or promote products derived 14563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// from this software without specific prior written permission. 15563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// 16563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 28563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 29563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// This is a JavaScript implementation of the Richards 30563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// benchmark from: 31563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// 32563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// http://www.cl.cam.ac.uk/~mr10/Bench.html 330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// 34563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// The benchmark was originally implemented in BCPL by 35563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark// Martin Richards. 36563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 38563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 39563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * The Richards benchmark simulates the task dispatcher of an 40563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * operating system. 41563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark **/ 42563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction runRichards() { 43563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var scheduler = new Scheduler(); 44563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.addIdleTask(ID_IDLE, 0, null, COUNT); 45563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 46563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var queue = new Packet(null, ID_WORKER, KIND_WORK); 47563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(queue, ID_WORKER, KIND_WORK); 48563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.addWorkerTask(ID_WORKER, 1000, queue); 49563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 50563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE); 51563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE); 52563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE); 53563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue); 54563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 55563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE); 56563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE); 57563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE); 58563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue); 59563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 60563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.addDeviceTask(ID_DEVICE_A, 4000, null); 61563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 62563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.addDeviceTask(ID_DEVICE_B, 5000, null); 63563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 64563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.schedule(); 65563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 66563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (scheduler.queueCount != EXPECTED_QUEUE_COUNT || 67563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark scheduler.holdCount != EXPECTED_HOLD_COUNT) { 68563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var msg = 69563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark "Error during execution: queueCount = " + scheduler.queueCount + 70563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark ", holdCount = " + scheduler.holdCount + "."; 710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch throw new Error(msg); 72563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 73563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 74563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 75563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar COUNT = 1000; 76563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 77563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 78563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * These two constants specify how many times a packet is queued and 79563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * how many times a task is put on hold in a correct run of richards. 80563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * They don't have any meaning a such but are characteristic of a 81563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * correct run so if the actual queue or hold count is different from 82563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * the expected there must be a bug in the implementation. 83563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark **/ 84563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar EXPECTED_QUEUE_COUNT = 2322; 85563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar EXPECTED_HOLD_COUNT = 928; 86563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 87563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 88563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 89563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * A scheduler can be used to schedule a set of tasks based on their relative 90563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * priorities. Scheduling is done by maintaining a list of task control blocks 91563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * which holds tasks and the data queue they are processing. 92563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 93563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 94563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction Scheduler() { 95563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.queueCount = 0; 96563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.holdCount = 0; 97563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.blocks = new Array(NUMBER_OF_IDS); 98563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.list = null; 99563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb = null; 100563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentId = null; 101563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 102563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 103563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar ID_IDLE = 0; 104563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar ID_WORKER = 1; 105563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar ID_HANDLER_A = 2; 106563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar ID_HANDLER_B = 3; 107563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar ID_DEVICE_A = 4; 108563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar ID_DEVICE_B = 5; 109563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar NUMBER_OF_IDS = 6; 110563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 111563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar KIND_DEVICE = 0; 112563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar KIND_WORK = 1; 113563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 114563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 115563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add an idle task to this scheduler. 116563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the identity of the task 117563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the task's priority 118563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of work to be processed by the task 119563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} count the number of times to schedule the task 120563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 121563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.addIdleTask = function (id, priority, queue, count) { 122563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.addRunningTask(id, priority, queue, new IdleTask(this, 1, count)); 123563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 124563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 125563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 126563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add a work task to this scheduler. 127563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the identity of the task 128563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the task's priority 129563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of work to be processed by the task 130563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 131563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.addWorkerTask = function (id, priority, queue) { 132563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.addTask(id, priority, queue, new WorkerTask(this, ID_HANDLER_A, 0)); 133563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 134563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 135563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 136563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add a handler task to this scheduler. 137563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the identity of the task 138563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the task's priority 139563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of work to be processed by the task 140563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 141563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.addHandlerTask = function (id, priority, queue) { 142563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.addTask(id, priority, queue, new HandlerTask(this)); 143563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 144563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 145563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 146563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add a handler task to this scheduler. 147563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the identity of the task 148563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the task's priority 149563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of work to be processed by the task 150563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 151563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.addDeviceTask = function (id, priority, queue) { 152563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.addTask(id, priority, queue, new DeviceTask(this)) 153563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 154563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 155563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 156563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add the specified task and mark it as running. 157563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the identity of the task 158563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the task's priority 159563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of work to be processed by the task 160563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Task} task the task to add 161563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 162563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.addRunningTask = function (id, priority, queue, task) { 163563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.addTask(id, priority, queue, task); 164563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb.setRunning(); 165563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 166563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 167563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 168563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add the specified task to this scheduler. 169563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the identity of the task 170563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the task's priority 171563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of work to be processed by the task 172563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Task} task the task to add 173563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 174563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.addTask = function (id, priority, queue, task) { 175563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task); 176563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.list = this.currentTcb; 177563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.blocks[id] = this.currentTcb; 178563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 179563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 180563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 181563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Execute the tasks managed by this scheduler. 182563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 183563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.schedule = function () { 184563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb = this.list; 185563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark while (this.currentTcb != null) { 186563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.currentTcb.isHeldOrSuspended()) { 187563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb = this.currentTcb.link; 188563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 189563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentId = this.currentTcb.id; 190563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb = this.currentTcb.run(); 191563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 192563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 193563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 194563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 195563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 196563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Release a task that is currently blocked and return the next block to run. 197563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the id of the task to suspend 198563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 199563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.release = function (id) { 200563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var tcb = this.blocks[id]; 201563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (tcb == null) return tcb; 202563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark tcb.markAsNotHeld(); 203563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (tcb.priority > this.currentTcb.priority) { 204563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return tcb; 205563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 206563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.currentTcb; 207563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 208563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 209563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 210563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 211563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Block the currently executing task and return the next task control block 212563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * to run. The blocked task will not be made runnable until it is explicitly 213563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * released, even if new work is added to it. 214563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 215563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.holdCurrent = function () { 216563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.holdCount++; 217563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb.markAsHeld(); 218563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.currentTcb.link; 219563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 220563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 221563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 222563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Suspend the currently executing task and return the next task control block 223563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * to run. If new work is added to the suspended task it will be made runnable. 224563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 225563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.suspendCurrent = function () { 226563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.currentTcb.markAsSuspended(); 227563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.currentTcb; 228563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 229563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 230563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 231563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add the specified packet to the end of the worklist used by the task 232563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * associated with the packet and make the task runnable if it is currently 233563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * suspended. 234563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} packet the packet to add 235563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 236563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkScheduler.prototype.queue = function (packet) { 237563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var t = this.blocks[packet.id]; 238563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (t == null) return t; 239563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.queueCount++; 240563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet.link = null; 241563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet.id = this.currentId; 242563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return t.checkPriorityAdd(this.currentTcb, packet); 243563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 244563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 245563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 246563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * A task control block manages a task and the queue of work packages associated 247563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * with it. 248563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {TaskControlBlock} link the preceding block in the linked block list 249563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id the id of this block 250563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} priority the priority of this block 251563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the queue of packages to be processed by the task 252563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Task} task the task 253563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 254563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 255563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction TaskControlBlock(link, id, priority, queue, task) { 256563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.link = link; 257563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.id = id; 258563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.priority = priority; 259563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.queue = queue; 260563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.task = task; 261563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (queue == null) { 262563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = STATE_SUSPENDED; 263563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 264563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = STATE_SUSPENDED_RUNNABLE; 265563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 266563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 267563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 268563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 269563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * The task is running and is currently scheduled. 270563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 271563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar STATE_RUNNING = 0; 272563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 273563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 274563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * The task has packets left to process. 275563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 276563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar STATE_RUNNABLE = 1; 277563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 278563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 279563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * The task is not currently running. The task is not blocked as such and may 280563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark* be started by the scheduler. 281563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 282563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar STATE_SUSPENDED = 2; 283563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 284563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 285563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * The task is blocked and cannot be run until it is explicitly released. 286563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 287563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar STATE_HELD = 4; 288563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 289563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE; 290563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar STATE_NOT_HELD = ~STATE_HELD; 291563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 292563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.setRunning = function () { 293563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = STATE_RUNNING; 294563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 295563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 296563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.markAsNotHeld = function () { 297563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = this.state & STATE_NOT_HELD; 298563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 299563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 300563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.markAsHeld = function () { 301563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = this.state | STATE_HELD; 302563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 303563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 304563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.isHeldOrSuspended = function () { 305563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return (this.state & STATE_HELD) != 0 || (this.state == STATE_SUSPENDED); 306563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 307563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 308563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.markAsSuspended = function () { 309563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = this.state | STATE_SUSPENDED; 310563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 311563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 312563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.markAsRunnable = function () { 313563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = this.state | STATE_RUNNABLE; 314563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 315563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 316563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 317563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Runs this task, if it is ready to be run, and returns the next task to run. 318563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 319563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.run = function () { 320563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var packet; 321563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.state == STATE_SUSPENDED_RUNNABLE) { 322563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet = this.queue; 323563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.queue = packet.link; 324563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.queue == null) { 325563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = STATE_RUNNING; 326563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 327563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.state = STATE_RUNNABLE; 328563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 329563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 330563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet = null; 331563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 332563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.task.run(packet); 333563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 334563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 335563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 336563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Adds a packet to the worklist of this block's task, marks this as runnable if 337563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * necessary, and returns the next runnable object to run (the one 338563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * with the highest priority). 339563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 340563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.checkPriorityAdd = function (task, packet) { 341563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.queue == null) { 342563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.queue = packet; 343563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.markAsRunnable(); 344563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.priority > task.priority) return this; 345563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 346563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.queue = packet.addTo(this.queue); 347563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 348563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return task; 349563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 350563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 351563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkTaskControlBlock.prototype.toString = function () { 352563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return "tcb { " + this.task + "@" + this.state + " }"; 353563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 354563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 355563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 356563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * An idle task doesn't do any work itself but cycles control between the two 357563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * device tasks. 358563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Scheduler} scheduler the scheduler that manages this task 359563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} v1 a seed value that controls how the device tasks are scheduled 360563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} count the number of times this task should be scheduled 361563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 362563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 363563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction IdleTask(scheduler, v1, count) { 364563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.scheduler = scheduler; 365563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = v1; 366563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.count = count; 367563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 368563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 369563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkIdleTask.prototype.run = function (packet) { 370563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.count--; 371563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.count == 0) return this.scheduler.holdCurrent(); 372563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if ((this.v1 & 1) == 0) { 373563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = this.v1 >> 1; 374563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.release(ID_DEVICE_A); 375563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 376563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = (this.v1 >> 1) ^ 0xD008; 377563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.release(ID_DEVICE_B); 378563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 379563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 380563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 381563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkIdleTask.prototype.toString = function () { 382563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return "IdleTask" 383563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 384563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 385563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 386563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * A task that suspends itself after each time it has been run to simulate 387563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * waiting for data from an external device. 388563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Scheduler} scheduler the scheduler that manages this task 389563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 390563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 391563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction DeviceTask(scheduler) { 392563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.scheduler = scheduler; 393563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = null; 394563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 395563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 396563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDeviceTask.prototype.run = function (packet) { 397563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (packet == null) { 398563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.v1 == null) return this.scheduler.suspendCurrent(); 399563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var v = this.v1; 400563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = null; 401563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.queue(v); 402563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 403563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = packet; 404563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.holdCurrent(); 405563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 406563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 407563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 408563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDeviceTask.prototype.toString = function () { 409563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return "DeviceTask"; 410563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 411563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 412563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 413563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * A task that manipulates work packets. 414563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Scheduler} scheduler the scheduler that manages this task 415563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} v1 a seed used to specify how work packets are manipulated 416563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} v2 another seed used to specify how work packets are manipulated 417563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 418563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 419563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction WorkerTask(scheduler, v1, v2) { 420563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.scheduler = scheduler; 421563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = v1; 422563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v2 = v2; 423563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 424563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 425563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkWorkerTask.prototype.run = function (packet) { 426563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (packet == null) { 427563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.suspendCurrent(); 428563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 429563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.v1 == ID_HANDLER_A) { 430563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = ID_HANDLER_B; 431563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 432563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = ID_HANDLER_A; 433563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 434563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet.id = this.v1; 435563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet.a1 = 0; 436563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark for (var i = 0; i < DATA_SIZE; i++) { 437563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v2++; 438563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.v2 > 26) this.v2 = 1; 439563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark packet.a2[i] = this.v2; 440563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 441563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.queue(packet); 442563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 443563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 444563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 445563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkWorkerTask.prototype.toString = function () { 446563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return "WorkerTask"; 447563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 448563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 449563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 450563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * A task that manipulates work packets and then suspends itself. 451563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Scheduler} scheduler the scheduler that manages this task 452563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 453563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 454563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction HandlerTask(scheduler) { 455563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.scheduler = scheduler; 456563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = null; 457563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v2 = null; 458563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 459563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 460563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkHandlerTask.prototype.run = function (packet) { 461563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (packet != null) { 462563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (packet.kind == KIND_WORK) { 463563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = packet.addTo(this.v1); 464563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 465563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v2 = packet.addTo(this.v2); 466563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 467563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 468563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.v1 != null) { 469563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var count = this.v1.a1; 470563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var v; 471563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (count < DATA_SIZE) { 472563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (this.v2 != null) { 473563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark v = this.v2; 474563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v2 = this.v2.link; 475563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark v.a1 = this.v1.a2[count]; 476563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1.a1 = count + 1; 477563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.queue(v); 478563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 479563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } else { 480563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark v = this.v1; 481563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.v1 = this.v1.link; 482563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.queue(v); 483563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 484563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 485563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return this.scheduler.suspendCurrent(); 486563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 487563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 488563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkHandlerTask.prototype.toString = function () { 489563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return "HandlerTask"; 490563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 491563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 492563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/* --- * 493563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * P a c k e t 494563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * --- */ 495563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 496563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar DATA_SIZE = 4; 497563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 498563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 499563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * A simple package of data that is manipulated by the tasks. The exact layout 500563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * of the payload data carried by a packet is not importaint, and neither is the 501563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * nature of the work performed on packets by the tasks. 502563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 503563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Besides carrying data, packets form linked lists and are hence used both as 504563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * data and worklists. 505563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} link the tail of the linked list of packets 506563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} id an ID for this packet 507563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {int} kind the type of this packet 508563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @constructor 509563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 510563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfunction Packet(link, id, kind) { 511563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.link = link; 512563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.id = id; 513563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.kind = kind; 514563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.a1 = 0; 515563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.a2 = new Array(DATA_SIZE); 516563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 517563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 518563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/** 519563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Add this packet to the end of a worklist, and return the worklist. 520563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * @param {Packet} queue the worklist to add this packet to 521563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 522563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkPacket.prototype.addTo = function (queue) { 523563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark this.link = null; 524563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (queue == null) return this; 525563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark var peek, next = queue; 526563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark while ((peek = next.link) != null) 527563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark next = peek; 528563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark next.link = this; 529563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return queue; 530563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 531563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 532563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkPacket.prototype.toString = function () { 533563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return "Packet"; 534563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}; 535563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 536563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfor (var i = 0; i < 350; ++i) 537563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark runRichards(); 538