19258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org// Copyright 2006-2008 the V8 project authors. All rights reserved.
2727e995b7bba3c57fb1e5c156d386ca11894f781v// Redistribution and use in source and binary forms, with or without
3727e995b7bba3c57fb1e5c156d386ca11894f781v// modification, are permitted provided that the following conditions are
4727e995b7bba3c57fb1e5c156d386ca11894f781v// met:
5727e995b7bba3c57fb1e5c156d386ca11894f781v//
6727e995b7bba3c57fb1e5c156d386ca11894f781v//     * Redistributions of source code must retain the above copyright
7727e995b7bba3c57fb1e5c156d386ca11894f781v//       notice, this list of conditions and the following disclaimer.
8727e995b7bba3c57fb1e5c156d386ca11894f781v//     * Redistributions in binary form must reproduce the above
9727e995b7bba3c57fb1e5c156d386ca11894f781v//       copyright notice, this list of conditions and the following
10727e995b7bba3c57fb1e5c156d386ca11894f781v//       disclaimer in the documentation and/or other materials provided
11727e995b7bba3c57fb1e5c156d386ca11894f781v//       with the distribution.
12727e995b7bba3c57fb1e5c156d386ca11894f781v//     * Neither the name of Google Inc. nor the names of its
13727e995b7bba3c57fb1e5c156d386ca11894f781v//       contributors may be used to endorse or promote products derived
14727e995b7bba3c57fb1e5c156d386ca11894f781v//       from this software without specific prior written permission.
15727e995b7bba3c57fb1e5c156d386ca11894f781v//
16727e995b7bba3c57fb1e5c156d386ca11894f781v// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17727e995b7bba3c57fb1e5c156d386ca11894f781v// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18727e995b7bba3c57fb1e5c156d386ca11894f781v// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19727e995b7bba3c57fb1e5c156d386ca11894f781v// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20727e995b7bba3c57fb1e5c156d386ca11894f781v// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21727e995b7bba3c57fb1e5c156d386ca11894f781v// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22727e995b7bba3c57fb1e5c156d386ca11894f781v// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23727e995b7bba3c57fb1e5c156d386ca11894f781v// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24727e995b7bba3c57fb1e5c156d386ca11894f781v// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25727e995b7bba3c57fb1e5c156d386ca11894f781v// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26727e995b7bba3c57fb1e5c156d386ca11894f781v// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27727e995b7bba3c57fb1e5c156d386ca11894f781v
28727e995b7bba3c57fb1e5c156d386ca11894f781v
29727e995b7bba3c57fb1e5c156d386ca11894f781v// This is a JavaScript implementation of the Richards
30727e995b7bba3c57fb1e5c156d386ca11894f781v// benchmark from:
31727e995b7bba3c57fb1e5c156d386ca11894f781v//
32727e995b7bba3c57fb1e5c156d386ca11894f781v//    http://www.cl.cam.ac.uk/~mr10/Bench.html
33b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org//
34727e995b7bba3c57fb1e5c156d386ca11894f781v// The benchmark was originally implemented in BCPL by
35727e995b7bba3c57fb1e5c156d386ca11894f781v// Martin Richards.
36727e995b7bba3c57fb1e5c156d386ca11894f781v
37727e995b7bba3c57fb1e5c156d386ca11894f781v
38d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.comvar Richards = new BenchmarkSuite('Richards', 35302, [
39727e995b7bba3c57fb1e5c156d386ca11894f781v  new Benchmark("Richards", runRichards)
40727e995b7bba3c57fb1e5c156d386ca11894f781v]);
41727e995b7bba3c57fb1e5c156d386ca11894f781v
42727e995b7bba3c57fb1e5c156d386ca11894f781v
43727e995b7bba3c57fb1e5c156d386ca11894f781v/**
44727e995b7bba3c57fb1e5c156d386ca11894f781v * The Richards benchmark simulates the task dispatcher of an
45727e995b7bba3c57fb1e5c156d386ca11894f781v * operating system.
46727e995b7bba3c57fb1e5c156d386ca11894f781v **/
47727e995b7bba3c57fb1e5c156d386ca11894f781vfunction runRichards() {
48727e995b7bba3c57fb1e5c156d386ca11894f781v  var scheduler = new Scheduler();
49727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);
50727e995b7bba3c57fb1e5c156d386ca11894f781v
51727e995b7bba3c57fb1e5c156d386ca11894f781v  var queue = new Packet(null, ID_WORKER, KIND_WORK);
52727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(queue,  ID_WORKER, KIND_WORK);
53727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.addWorkerTask(ID_WORKER, 1000, queue);
54727e995b7bba3c57fb1e5c156d386ca11894f781v
55727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE);
56727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(queue,  ID_DEVICE_A, KIND_DEVICE);
57727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(queue,  ID_DEVICE_A, KIND_DEVICE);
58727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);
59727e995b7bba3c57fb1e5c156d386ca11894f781v
60727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE);
61727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(queue,  ID_DEVICE_B, KIND_DEVICE);
62727e995b7bba3c57fb1e5c156d386ca11894f781v  queue = new Packet(queue,  ID_DEVICE_B, KIND_DEVICE);
63727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);
64727e995b7bba3c57fb1e5c156d386ca11894f781v
65727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);
66727e995b7bba3c57fb1e5c156d386ca11894f781v
67727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);
68727e995b7bba3c57fb1e5c156d386ca11894f781v
69727e995b7bba3c57fb1e5c156d386ca11894f781v  scheduler.schedule();
70727e995b7bba3c57fb1e5c156d386ca11894f781v
71727e995b7bba3c57fb1e5c156d386ca11894f781v  if (scheduler.queueCount != EXPECTED_QUEUE_COUNT ||
72727e995b7bba3c57fb1e5c156d386ca11894f781v      scheduler.holdCount != EXPECTED_HOLD_COUNT) {
73727e995b7bba3c57fb1e5c156d386ca11894f781v    var msg =
74727e995b7bba3c57fb1e5c156d386ca11894f781v        "Error during execution: queueCount = " + scheduler.queueCount +
75727e995b7bba3c57fb1e5c156d386ca11894f781v        ", holdCount = " + scheduler.holdCount + ".";
7641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    throw new Error(msg);
77727e995b7bba3c57fb1e5c156d386ca11894f781v  }
78727e995b7bba3c57fb1e5c156d386ca11894f781v}
79727e995b7bba3c57fb1e5c156d386ca11894f781v
80727e995b7bba3c57fb1e5c156d386ca11894f781vvar COUNT = 1000;
81727e995b7bba3c57fb1e5c156d386ca11894f781v
82727e995b7bba3c57fb1e5c156d386ca11894f781v/**
83727e995b7bba3c57fb1e5c156d386ca11894f781v * These two constants specify how many times a packet is queued and
84727e995b7bba3c57fb1e5c156d386ca11894f781v * how many times a task is put on hold in a correct run of richards.
85727e995b7bba3c57fb1e5c156d386ca11894f781v * They don't have any meaning a such but are characteristic of a
86727e995b7bba3c57fb1e5c156d386ca11894f781v * correct run so if the actual queue or hold count is different from
87727e995b7bba3c57fb1e5c156d386ca11894f781v * the expected there must be a bug in the implementation.
88727e995b7bba3c57fb1e5c156d386ca11894f781v **/
89727e995b7bba3c57fb1e5c156d386ca11894f781vvar EXPECTED_QUEUE_COUNT = 2322;
90727e995b7bba3c57fb1e5c156d386ca11894f781vvar EXPECTED_HOLD_COUNT = 928;
91727e995b7bba3c57fb1e5c156d386ca11894f781v
92727e995b7bba3c57fb1e5c156d386ca11894f781v
93727e995b7bba3c57fb1e5c156d386ca11894f781v/**
94727e995b7bba3c57fb1e5c156d386ca11894f781v * A scheduler can be used to schedule a set of tasks based on their relative
95727e995b7bba3c57fb1e5c156d386ca11894f781v * priorities.  Scheduling is done by maintaining a list of task control blocks
96727e995b7bba3c57fb1e5c156d386ca11894f781v * which holds tasks and the data queue they are processing.
97727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
98727e995b7bba3c57fb1e5c156d386ca11894f781v */
99727e995b7bba3c57fb1e5c156d386ca11894f781vfunction Scheduler() {
100727e995b7bba3c57fb1e5c156d386ca11894f781v  this.queueCount = 0;
101727e995b7bba3c57fb1e5c156d386ca11894f781v  this.holdCount = 0;
102727e995b7bba3c57fb1e5c156d386ca11894f781v  this.blocks = new Array(NUMBER_OF_IDS);
103727e995b7bba3c57fb1e5c156d386ca11894f781v  this.list = null;
104727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentTcb = null;
105727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentId = null;
106727e995b7bba3c57fb1e5c156d386ca11894f781v}
107727e995b7bba3c57fb1e5c156d386ca11894f781v
108727e995b7bba3c57fb1e5c156d386ca11894f781vvar ID_IDLE       = 0;
109727e995b7bba3c57fb1e5c156d386ca11894f781vvar ID_WORKER     = 1;
110727e995b7bba3c57fb1e5c156d386ca11894f781vvar ID_HANDLER_A  = 2;
111727e995b7bba3c57fb1e5c156d386ca11894f781vvar ID_HANDLER_B  = 3;
112727e995b7bba3c57fb1e5c156d386ca11894f781vvar ID_DEVICE_A   = 4;
113727e995b7bba3c57fb1e5c156d386ca11894f781vvar ID_DEVICE_B   = 5;
114727e995b7bba3c57fb1e5c156d386ca11894f781vvar NUMBER_OF_IDS = 6;
115727e995b7bba3c57fb1e5c156d386ca11894f781v
116727e995b7bba3c57fb1e5c156d386ca11894f781vvar KIND_DEVICE   = 0;
117727e995b7bba3c57fb1e5c156d386ca11894f781vvar KIND_WORK     = 1;
118727e995b7bba3c57fb1e5c156d386ca11894f781v
119727e995b7bba3c57fb1e5c156d386ca11894f781v/**
120727e995b7bba3c57fb1e5c156d386ca11894f781v * Add an idle task to this scheduler.
121727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the identity of the task
122727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the task's priority
123727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of work to be processed by the task
124727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} count the number of times to schedule the task
125727e995b7bba3c57fb1e5c156d386ca11894f781v */
126727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.addIdleTask = function (id, priority, queue, count) {
127727e995b7bba3c57fb1e5c156d386ca11894f781v  this.addRunningTask(id, priority, queue, new IdleTask(this, 1, count));
128727e995b7bba3c57fb1e5c156d386ca11894f781v};
129727e995b7bba3c57fb1e5c156d386ca11894f781v
130727e995b7bba3c57fb1e5c156d386ca11894f781v/**
131727e995b7bba3c57fb1e5c156d386ca11894f781v * Add a work task to this scheduler.
132727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the identity of the task
133727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the task's priority
134727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of work to be processed by the task
135727e995b7bba3c57fb1e5c156d386ca11894f781v */
136727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.addWorkerTask = function (id, priority, queue) {
137727e995b7bba3c57fb1e5c156d386ca11894f781v  this.addTask(id, priority, queue, new WorkerTask(this, ID_HANDLER_A, 0));
138727e995b7bba3c57fb1e5c156d386ca11894f781v};
139727e995b7bba3c57fb1e5c156d386ca11894f781v
140727e995b7bba3c57fb1e5c156d386ca11894f781v/**
141727e995b7bba3c57fb1e5c156d386ca11894f781v * Add a handler task to this scheduler.
142727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the identity of the task
143727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the task's priority
144727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of work to be processed by the task
145727e995b7bba3c57fb1e5c156d386ca11894f781v */
146727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.addHandlerTask = function (id, priority, queue) {
147727e995b7bba3c57fb1e5c156d386ca11894f781v  this.addTask(id, priority, queue, new HandlerTask(this));
148727e995b7bba3c57fb1e5c156d386ca11894f781v};
149727e995b7bba3c57fb1e5c156d386ca11894f781v
150727e995b7bba3c57fb1e5c156d386ca11894f781v/**
151727e995b7bba3c57fb1e5c156d386ca11894f781v * Add a handler task to this scheduler.
152727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the identity of the task
153727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the task's priority
154727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of work to be processed by the task
155727e995b7bba3c57fb1e5c156d386ca11894f781v */
156727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.addDeviceTask = function (id, priority, queue) {
157727e995b7bba3c57fb1e5c156d386ca11894f781v  this.addTask(id, priority, queue, new DeviceTask(this))
158727e995b7bba3c57fb1e5c156d386ca11894f781v};
159727e995b7bba3c57fb1e5c156d386ca11894f781v
160727e995b7bba3c57fb1e5c156d386ca11894f781v/**
161727e995b7bba3c57fb1e5c156d386ca11894f781v * Add the specified task and mark it as running.
162727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the identity of the task
163727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the task's priority
164727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of work to be processed by the task
165727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Task} task the task to add
166727e995b7bba3c57fb1e5c156d386ca11894f781v */
167727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.addRunningTask = function (id, priority, queue, task) {
168727e995b7bba3c57fb1e5c156d386ca11894f781v  this.addTask(id, priority, queue, task);
169727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentTcb.setRunning();
170727e995b7bba3c57fb1e5c156d386ca11894f781v};
171727e995b7bba3c57fb1e5c156d386ca11894f781v
172727e995b7bba3c57fb1e5c156d386ca11894f781v/**
173727e995b7bba3c57fb1e5c156d386ca11894f781v * Add the specified task to this scheduler.
174727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the identity of the task
175727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the task's priority
176727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of work to be processed by the task
177727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Task} task the task to add
178727e995b7bba3c57fb1e5c156d386ca11894f781v */
179727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.addTask = function (id, priority, queue, task) {
180727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task);
181727e995b7bba3c57fb1e5c156d386ca11894f781v  this.list = this.currentTcb;
182727e995b7bba3c57fb1e5c156d386ca11894f781v  this.blocks[id] = this.currentTcb;
183727e995b7bba3c57fb1e5c156d386ca11894f781v};
184727e995b7bba3c57fb1e5c156d386ca11894f781v
185727e995b7bba3c57fb1e5c156d386ca11894f781v/**
186727e995b7bba3c57fb1e5c156d386ca11894f781v * Execute the tasks managed by this scheduler.
187727e995b7bba3c57fb1e5c156d386ca11894f781v */
188727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.schedule = function () {
189727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentTcb = this.list;
190727e995b7bba3c57fb1e5c156d386ca11894f781v  while (this.currentTcb != null) {
191727e995b7bba3c57fb1e5c156d386ca11894f781v    if (this.currentTcb.isHeldOrSuspended()) {
192727e995b7bba3c57fb1e5c156d386ca11894f781v      this.currentTcb = this.currentTcb.link;
193727e995b7bba3c57fb1e5c156d386ca11894f781v    } else {
194727e995b7bba3c57fb1e5c156d386ca11894f781v      this.currentId = this.currentTcb.id;
195727e995b7bba3c57fb1e5c156d386ca11894f781v      this.currentTcb = this.currentTcb.run();
196727e995b7bba3c57fb1e5c156d386ca11894f781v    }
197727e995b7bba3c57fb1e5c156d386ca11894f781v  }
198727e995b7bba3c57fb1e5c156d386ca11894f781v};
199727e995b7bba3c57fb1e5c156d386ca11894f781v
200727e995b7bba3c57fb1e5c156d386ca11894f781v/**
201727e995b7bba3c57fb1e5c156d386ca11894f781v * Release a task that is currently blocked and return the next block to run.
202727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the id of the task to suspend
203727e995b7bba3c57fb1e5c156d386ca11894f781v */
204727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.release = function (id) {
205727e995b7bba3c57fb1e5c156d386ca11894f781v  var tcb = this.blocks[id];
206727e995b7bba3c57fb1e5c156d386ca11894f781v  if (tcb == null) return tcb;
207727e995b7bba3c57fb1e5c156d386ca11894f781v  tcb.markAsNotHeld();
208727e995b7bba3c57fb1e5c156d386ca11894f781v  if (tcb.priority > this.currentTcb.priority) {
209727e995b7bba3c57fb1e5c156d386ca11894f781v    return tcb;
210727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
211727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.currentTcb;
212727e995b7bba3c57fb1e5c156d386ca11894f781v  }
213727e995b7bba3c57fb1e5c156d386ca11894f781v};
214727e995b7bba3c57fb1e5c156d386ca11894f781v
215727e995b7bba3c57fb1e5c156d386ca11894f781v/**
216727e995b7bba3c57fb1e5c156d386ca11894f781v * Block the currently executing task and return the next task control block
217727e995b7bba3c57fb1e5c156d386ca11894f781v * to run.  The blocked task will not be made runnable until it is explicitly
218727e995b7bba3c57fb1e5c156d386ca11894f781v * released, even if new work is added to it.
219727e995b7bba3c57fb1e5c156d386ca11894f781v */
220727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.holdCurrent = function () {
221727e995b7bba3c57fb1e5c156d386ca11894f781v  this.holdCount++;
222727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentTcb.markAsHeld();
223727e995b7bba3c57fb1e5c156d386ca11894f781v  return this.currentTcb.link;
224727e995b7bba3c57fb1e5c156d386ca11894f781v};
225727e995b7bba3c57fb1e5c156d386ca11894f781v
226727e995b7bba3c57fb1e5c156d386ca11894f781v/**
227727e995b7bba3c57fb1e5c156d386ca11894f781v * Suspend the currently executing task and return the next task control block
228727e995b7bba3c57fb1e5c156d386ca11894f781v * to run.  If new work is added to the suspended task it will be made runnable.
229727e995b7bba3c57fb1e5c156d386ca11894f781v */
230727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.suspendCurrent = function () {
231727e995b7bba3c57fb1e5c156d386ca11894f781v  this.currentTcb.markAsSuspended();
232727e995b7bba3c57fb1e5c156d386ca11894f781v  return this.currentTcb;
233727e995b7bba3c57fb1e5c156d386ca11894f781v};
234727e995b7bba3c57fb1e5c156d386ca11894f781v
235727e995b7bba3c57fb1e5c156d386ca11894f781v/**
236727e995b7bba3c57fb1e5c156d386ca11894f781v * Add the specified packet to the end of the worklist used by the task
237727e995b7bba3c57fb1e5c156d386ca11894f781v * associated with the packet and make the task runnable if it is currently
238727e995b7bba3c57fb1e5c156d386ca11894f781v * suspended.
239727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} packet the packet to add
240727e995b7bba3c57fb1e5c156d386ca11894f781v */
241727e995b7bba3c57fb1e5c156d386ca11894f781vScheduler.prototype.queue = function (packet) {
242727e995b7bba3c57fb1e5c156d386ca11894f781v  var t = this.blocks[packet.id];
243727e995b7bba3c57fb1e5c156d386ca11894f781v  if (t == null) return t;
244727e995b7bba3c57fb1e5c156d386ca11894f781v  this.queueCount++;
245727e995b7bba3c57fb1e5c156d386ca11894f781v  packet.link = null;
246727e995b7bba3c57fb1e5c156d386ca11894f781v  packet.id = this.currentId;
247727e995b7bba3c57fb1e5c156d386ca11894f781v  return t.checkPriorityAdd(this.currentTcb, packet);
248727e995b7bba3c57fb1e5c156d386ca11894f781v};
249727e995b7bba3c57fb1e5c156d386ca11894f781v
250727e995b7bba3c57fb1e5c156d386ca11894f781v/**
251727e995b7bba3c57fb1e5c156d386ca11894f781v * A task control block manages a task and the queue of work packages associated
252727e995b7bba3c57fb1e5c156d386ca11894f781v * with it.
253727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {TaskControlBlock} link the preceding block in the linked block list
254727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id the id of this block
255727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} priority the priority of this block
256727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the queue of packages to be processed by the task
257727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Task} task the task
258727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
259727e995b7bba3c57fb1e5c156d386ca11894f781v */
260727e995b7bba3c57fb1e5c156d386ca11894f781vfunction TaskControlBlock(link, id, priority, queue, task) {
261727e995b7bba3c57fb1e5c156d386ca11894f781v  this.link = link;
262727e995b7bba3c57fb1e5c156d386ca11894f781v  this.id = id;
263727e995b7bba3c57fb1e5c156d386ca11894f781v  this.priority = priority;
264727e995b7bba3c57fb1e5c156d386ca11894f781v  this.queue = queue;
265727e995b7bba3c57fb1e5c156d386ca11894f781v  this.task = task;
266727e995b7bba3c57fb1e5c156d386ca11894f781v  if (queue == null) {
267727e995b7bba3c57fb1e5c156d386ca11894f781v    this.state = STATE_SUSPENDED;
268727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
269727e995b7bba3c57fb1e5c156d386ca11894f781v    this.state = STATE_SUSPENDED_RUNNABLE;
270727e995b7bba3c57fb1e5c156d386ca11894f781v  }
271727e995b7bba3c57fb1e5c156d386ca11894f781v}
272727e995b7bba3c57fb1e5c156d386ca11894f781v
273727e995b7bba3c57fb1e5c156d386ca11894f781v/**
274727e995b7bba3c57fb1e5c156d386ca11894f781v * The task is running and is currently scheduled.
275727e995b7bba3c57fb1e5c156d386ca11894f781v */
276727e995b7bba3c57fb1e5c156d386ca11894f781vvar STATE_RUNNING = 0;
277727e995b7bba3c57fb1e5c156d386ca11894f781v
278727e995b7bba3c57fb1e5c156d386ca11894f781v/**
279727e995b7bba3c57fb1e5c156d386ca11894f781v * The task has packets left to process.
280727e995b7bba3c57fb1e5c156d386ca11894f781v */
281727e995b7bba3c57fb1e5c156d386ca11894f781vvar STATE_RUNNABLE = 1;
282727e995b7bba3c57fb1e5c156d386ca11894f781v
283727e995b7bba3c57fb1e5c156d386ca11894f781v/**
284727e995b7bba3c57fb1e5c156d386ca11894f781v * The task is not currently running.  The task is not blocked as such and may
285727e995b7bba3c57fb1e5c156d386ca11894f781v* be started by the scheduler.
286727e995b7bba3c57fb1e5c156d386ca11894f781v */
287727e995b7bba3c57fb1e5c156d386ca11894f781vvar STATE_SUSPENDED = 2;
288727e995b7bba3c57fb1e5c156d386ca11894f781v
289727e995b7bba3c57fb1e5c156d386ca11894f781v/**
290727e995b7bba3c57fb1e5c156d386ca11894f781v * The task is blocked and cannot be run until it is explicitly released.
291727e995b7bba3c57fb1e5c156d386ca11894f781v */
292727e995b7bba3c57fb1e5c156d386ca11894f781vvar STATE_HELD = 4;
293727e995b7bba3c57fb1e5c156d386ca11894f781v
294727e995b7bba3c57fb1e5c156d386ca11894f781vvar STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
295727e995b7bba3c57fb1e5c156d386ca11894f781vvar STATE_NOT_HELD = ~STATE_HELD;
296727e995b7bba3c57fb1e5c156d386ca11894f781v
297727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.setRunning = function () {
298727e995b7bba3c57fb1e5c156d386ca11894f781v  this.state = STATE_RUNNING;
299727e995b7bba3c57fb1e5c156d386ca11894f781v};
300727e995b7bba3c57fb1e5c156d386ca11894f781v
301727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.markAsNotHeld = function () {
302727e995b7bba3c57fb1e5c156d386ca11894f781v  this.state = this.state & STATE_NOT_HELD;
303727e995b7bba3c57fb1e5c156d386ca11894f781v};
304727e995b7bba3c57fb1e5c156d386ca11894f781v
305727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.markAsHeld = function () {
306727e995b7bba3c57fb1e5c156d386ca11894f781v  this.state = this.state | STATE_HELD;
307727e995b7bba3c57fb1e5c156d386ca11894f781v};
308727e995b7bba3c57fb1e5c156d386ca11894f781v
309727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.isHeldOrSuspended = function () {
310727e995b7bba3c57fb1e5c156d386ca11894f781v  return (this.state & STATE_HELD) != 0 || (this.state == STATE_SUSPENDED);
311727e995b7bba3c57fb1e5c156d386ca11894f781v};
312727e995b7bba3c57fb1e5c156d386ca11894f781v
313727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.markAsSuspended = function () {
314727e995b7bba3c57fb1e5c156d386ca11894f781v  this.state = this.state | STATE_SUSPENDED;
315727e995b7bba3c57fb1e5c156d386ca11894f781v};
316727e995b7bba3c57fb1e5c156d386ca11894f781v
317727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.markAsRunnable = function () {
318727e995b7bba3c57fb1e5c156d386ca11894f781v  this.state = this.state | STATE_RUNNABLE;
319727e995b7bba3c57fb1e5c156d386ca11894f781v};
320727e995b7bba3c57fb1e5c156d386ca11894f781v
321727e995b7bba3c57fb1e5c156d386ca11894f781v/**
322727e995b7bba3c57fb1e5c156d386ca11894f781v * Runs this task, if it is ready to be run, and returns the next task to run.
323727e995b7bba3c57fb1e5c156d386ca11894f781v */
324727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.run = function () {
325727e995b7bba3c57fb1e5c156d386ca11894f781v  var packet;
326727e995b7bba3c57fb1e5c156d386ca11894f781v  if (this.state == STATE_SUSPENDED_RUNNABLE) {
327727e995b7bba3c57fb1e5c156d386ca11894f781v    packet = this.queue;
328727e995b7bba3c57fb1e5c156d386ca11894f781v    this.queue = packet.link;
329727e995b7bba3c57fb1e5c156d386ca11894f781v    if (this.queue == null) {
330727e995b7bba3c57fb1e5c156d386ca11894f781v      this.state = STATE_RUNNING;
331727e995b7bba3c57fb1e5c156d386ca11894f781v    } else {
332727e995b7bba3c57fb1e5c156d386ca11894f781v      this.state = STATE_RUNNABLE;
333727e995b7bba3c57fb1e5c156d386ca11894f781v    }
334727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
335727e995b7bba3c57fb1e5c156d386ca11894f781v    packet = null;
336727e995b7bba3c57fb1e5c156d386ca11894f781v  }
337727e995b7bba3c57fb1e5c156d386ca11894f781v  return this.task.run(packet);
338727e995b7bba3c57fb1e5c156d386ca11894f781v};
339727e995b7bba3c57fb1e5c156d386ca11894f781v
340727e995b7bba3c57fb1e5c156d386ca11894f781v/**
341727e995b7bba3c57fb1e5c156d386ca11894f781v * Adds a packet to the worklist of this block's task, marks this as runnable if
342727e995b7bba3c57fb1e5c156d386ca11894f781v * necessary, and returns the next runnable object to run (the one
343727e995b7bba3c57fb1e5c156d386ca11894f781v * with the highest priority).
344727e995b7bba3c57fb1e5c156d386ca11894f781v */
345727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.checkPriorityAdd = function (task, packet) {
346727e995b7bba3c57fb1e5c156d386ca11894f781v  if (this.queue == null) {
347727e995b7bba3c57fb1e5c156d386ca11894f781v    this.queue = packet;
348727e995b7bba3c57fb1e5c156d386ca11894f781v    this.markAsRunnable();
349727e995b7bba3c57fb1e5c156d386ca11894f781v    if (this.priority > task.priority) return this;
350727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
351727e995b7bba3c57fb1e5c156d386ca11894f781v    this.queue = packet.addTo(this.queue);
352727e995b7bba3c57fb1e5c156d386ca11894f781v  }
353727e995b7bba3c57fb1e5c156d386ca11894f781v  return task;
354727e995b7bba3c57fb1e5c156d386ca11894f781v};
355727e995b7bba3c57fb1e5c156d386ca11894f781v
356727e995b7bba3c57fb1e5c156d386ca11894f781vTaskControlBlock.prototype.toString = function () {
357727e995b7bba3c57fb1e5c156d386ca11894f781v  return "tcb { " + this.task + "@" + this.state + " }";
358727e995b7bba3c57fb1e5c156d386ca11894f781v};
359727e995b7bba3c57fb1e5c156d386ca11894f781v
360727e995b7bba3c57fb1e5c156d386ca11894f781v/**
361727e995b7bba3c57fb1e5c156d386ca11894f781v * An idle task doesn't do any work itself but cycles control between the two
362727e995b7bba3c57fb1e5c156d386ca11894f781v * device tasks.
363727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Scheduler} scheduler the scheduler that manages this task
364727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} v1 a seed value that controls how the device tasks are scheduled
365727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} count the number of times this task should be scheduled
366727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
367727e995b7bba3c57fb1e5c156d386ca11894f781v */
368727e995b7bba3c57fb1e5c156d386ca11894f781vfunction IdleTask(scheduler, v1, count) {
369727e995b7bba3c57fb1e5c156d386ca11894f781v  this.scheduler = scheduler;
370727e995b7bba3c57fb1e5c156d386ca11894f781v  this.v1 = v1;
371727e995b7bba3c57fb1e5c156d386ca11894f781v  this.count = count;
372727e995b7bba3c57fb1e5c156d386ca11894f781v}
373727e995b7bba3c57fb1e5c156d386ca11894f781v
374727e995b7bba3c57fb1e5c156d386ca11894f781vIdleTask.prototype.run = function (packet) {
375727e995b7bba3c57fb1e5c156d386ca11894f781v  this.count--;
376727e995b7bba3c57fb1e5c156d386ca11894f781v  if (this.count == 0) return this.scheduler.holdCurrent();
377727e995b7bba3c57fb1e5c156d386ca11894f781v  if ((this.v1 & 1) == 0) {
378727e995b7bba3c57fb1e5c156d386ca11894f781v    this.v1 = this.v1 >> 1;
379727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.scheduler.release(ID_DEVICE_A);
380727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
381727e995b7bba3c57fb1e5c156d386ca11894f781v    this.v1 = (this.v1 >> 1) ^ 0xD008;
382727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.scheduler.release(ID_DEVICE_B);
383727e995b7bba3c57fb1e5c156d386ca11894f781v  }
384727e995b7bba3c57fb1e5c156d386ca11894f781v};
385727e995b7bba3c57fb1e5c156d386ca11894f781v
386727e995b7bba3c57fb1e5c156d386ca11894f781vIdleTask.prototype.toString = function () {
387727e995b7bba3c57fb1e5c156d386ca11894f781v  return "IdleTask"
388727e995b7bba3c57fb1e5c156d386ca11894f781v};
389727e995b7bba3c57fb1e5c156d386ca11894f781v
390727e995b7bba3c57fb1e5c156d386ca11894f781v/**
391727e995b7bba3c57fb1e5c156d386ca11894f781v * A task that suspends itself after each time it has been run to simulate
392727e995b7bba3c57fb1e5c156d386ca11894f781v * waiting for data from an external device.
393727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Scheduler} scheduler the scheduler that manages this task
394727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
395727e995b7bba3c57fb1e5c156d386ca11894f781v */
396727e995b7bba3c57fb1e5c156d386ca11894f781vfunction DeviceTask(scheduler) {
397727e995b7bba3c57fb1e5c156d386ca11894f781v  this.scheduler = scheduler;
398727e995b7bba3c57fb1e5c156d386ca11894f781v  this.v1 = null;
399727e995b7bba3c57fb1e5c156d386ca11894f781v}
400727e995b7bba3c57fb1e5c156d386ca11894f781v
401727e995b7bba3c57fb1e5c156d386ca11894f781vDeviceTask.prototype.run = function (packet) {
402727e995b7bba3c57fb1e5c156d386ca11894f781v  if (packet == null) {
403727e995b7bba3c57fb1e5c156d386ca11894f781v    if (this.v1 == null) return this.scheduler.suspendCurrent();
404727e995b7bba3c57fb1e5c156d386ca11894f781v    var v = this.v1;
405727e995b7bba3c57fb1e5c156d386ca11894f781v    this.v1 = null;
406727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.scheduler.queue(v);
407727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
408727e995b7bba3c57fb1e5c156d386ca11894f781v    this.v1 = packet;
409727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.scheduler.holdCurrent();
410727e995b7bba3c57fb1e5c156d386ca11894f781v  }
411727e995b7bba3c57fb1e5c156d386ca11894f781v};
412727e995b7bba3c57fb1e5c156d386ca11894f781v
413727e995b7bba3c57fb1e5c156d386ca11894f781vDeviceTask.prototype.toString = function () {
414727e995b7bba3c57fb1e5c156d386ca11894f781v  return "DeviceTask";
415727e995b7bba3c57fb1e5c156d386ca11894f781v};
416727e995b7bba3c57fb1e5c156d386ca11894f781v
417727e995b7bba3c57fb1e5c156d386ca11894f781v/**
418727e995b7bba3c57fb1e5c156d386ca11894f781v * A task that manipulates work packets.
419727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Scheduler} scheduler the scheduler that manages this task
420727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} v1 a seed used to specify how work packets are manipulated
421727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} v2 another seed used to specify how work packets are manipulated
422727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
423727e995b7bba3c57fb1e5c156d386ca11894f781v */
424727e995b7bba3c57fb1e5c156d386ca11894f781vfunction WorkerTask(scheduler, v1, v2) {
425727e995b7bba3c57fb1e5c156d386ca11894f781v  this.scheduler = scheduler;
426727e995b7bba3c57fb1e5c156d386ca11894f781v  this.v1 = v1;
427727e995b7bba3c57fb1e5c156d386ca11894f781v  this.v2 = v2;
428727e995b7bba3c57fb1e5c156d386ca11894f781v}
429727e995b7bba3c57fb1e5c156d386ca11894f781v
430727e995b7bba3c57fb1e5c156d386ca11894f781vWorkerTask.prototype.run = function (packet) {
431727e995b7bba3c57fb1e5c156d386ca11894f781v  if (packet == null) {
432727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.scheduler.suspendCurrent();
433727e995b7bba3c57fb1e5c156d386ca11894f781v  } else {
434727e995b7bba3c57fb1e5c156d386ca11894f781v    if (this.v1 == ID_HANDLER_A) {
435727e995b7bba3c57fb1e5c156d386ca11894f781v      this.v1 = ID_HANDLER_B;
436727e995b7bba3c57fb1e5c156d386ca11894f781v    } else {
437727e995b7bba3c57fb1e5c156d386ca11894f781v      this.v1 = ID_HANDLER_A;
438727e995b7bba3c57fb1e5c156d386ca11894f781v    }
439727e995b7bba3c57fb1e5c156d386ca11894f781v    packet.id = this.v1;
440727e995b7bba3c57fb1e5c156d386ca11894f781v    packet.a1 = 0;
441727e995b7bba3c57fb1e5c156d386ca11894f781v    for (var i = 0; i < DATA_SIZE; i++) {
442727e995b7bba3c57fb1e5c156d386ca11894f781v      this.v2++;
443727e995b7bba3c57fb1e5c156d386ca11894f781v      if (this.v2 > 26) this.v2 = 1;
444727e995b7bba3c57fb1e5c156d386ca11894f781v      packet.a2[i] = this.v2;
445727e995b7bba3c57fb1e5c156d386ca11894f781v    }
446727e995b7bba3c57fb1e5c156d386ca11894f781v    return this.scheduler.queue(packet);
447727e995b7bba3c57fb1e5c156d386ca11894f781v  }
448727e995b7bba3c57fb1e5c156d386ca11894f781v};
449727e995b7bba3c57fb1e5c156d386ca11894f781v
450727e995b7bba3c57fb1e5c156d386ca11894f781vWorkerTask.prototype.toString = function () {
451727e995b7bba3c57fb1e5c156d386ca11894f781v  return "WorkerTask";
452727e995b7bba3c57fb1e5c156d386ca11894f781v};
453727e995b7bba3c57fb1e5c156d386ca11894f781v
454727e995b7bba3c57fb1e5c156d386ca11894f781v/**
455727e995b7bba3c57fb1e5c156d386ca11894f781v * A task that manipulates work packets and then suspends itself.
456727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Scheduler} scheduler the scheduler that manages this task
457727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
458727e995b7bba3c57fb1e5c156d386ca11894f781v */
459727e995b7bba3c57fb1e5c156d386ca11894f781vfunction HandlerTask(scheduler) {
460727e995b7bba3c57fb1e5c156d386ca11894f781v  this.scheduler = scheduler;
461727e995b7bba3c57fb1e5c156d386ca11894f781v  this.v1 = null;
462727e995b7bba3c57fb1e5c156d386ca11894f781v  this.v2 = null;
463727e995b7bba3c57fb1e5c156d386ca11894f781v}
464727e995b7bba3c57fb1e5c156d386ca11894f781v
465727e995b7bba3c57fb1e5c156d386ca11894f781vHandlerTask.prototype.run = function (packet) {
466727e995b7bba3c57fb1e5c156d386ca11894f781v  if (packet != null) {
467727e995b7bba3c57fb1e5c156d386ca11894f781v    if (packet.kind == KIND_WORK) {
468727e995b7bba3c57fb1e5c156d386ca11894f781v      this.v1 = packet.addTo(this.v1);
469727e995b7bba3c57fb1e5c156d386ca11894f781v    } else {
470727e995b7bba3c57fb1e5c156d386ca11894f781v      this.v2 = packet.addTo(this.v2);
471727e995b7bba3c57fb1e5c156d386ca11894f781v    }
472727e995b7bba3c57fb1e5c156d386ca11894f781v  }
473727e995b7bba3c57fb1e5c156d386ca11894f781v  if (this.v1 != null) {
474727e995b7bba3c57fb1e5c156d386ca11894f781v    var count = this.v1.a1;
475727e995b7bba3c57fb1e5c156d386ca11894f781v    var v;
476727e995b7bba3c57fb1e5c156d386ca11894f781v    if (count < DATA_SIZE) {
477727e995b7bba3c57fb1e5c156d386ca11894f781v      if (this.v2 != null) {
478727e995b7bba3c57fb1e5c156d386ca11894f781v        v = this.v2;
479727e995b7bba3c57fb1e5c156d386ca11894f781v        this.v2 = this.v2.link;
480727e995b7bba3c57fb1e5c156d386ca11894f781v        v.a1 = this.v1.a2[count];
481727e995b7bba3c57fb1e5c156d386ca11894f781v        this.v1.a1 = count + 1;
482727e995b7bba3c57fb1e5c156d386ca11894f781v        return this.scheduler.queue(v);
483727e995b7bba3c57fb1e5c156d386ca11894f781v      }
484727e995b7bba3c57fb1e5c156d386ca11894f781v    } else {
485727e995b7bba3c57fb1e5c156d386ca11894f781v      v = this.v1;
486727e995b7bba3c57fb1e5c156d386ca11894f781v      this.v1 = this.v1.link;
487727e995b7bba3c57fb1e5c156d386ca11894f781v      return this.scheduler.queue(v);
488727e995b7bba3c57fb1e5c156d386ca11894f781v    }
489727e995b7bba3c57fb1e5c156d386ca11894f781v  }
490727e995b7bba3c57fb1e5c156d386ca11894f781v  return this.scheduler.suspendCurrent();
491727e995b7bba3c57fb1e5c156d386ca11894f781v};
492727e995b7bba3c57fb1e5c156d386ca11894f781v
493727e995b7bba3c57fb1e5c156d386ca11894f781vHandlerTask.prototype.toString = function () {
494727e995b7bba3c57fb1e5c156d386ca11894f781v  return "HandlerTask";
495727e995b7bba3c57fb1e5c156d386ca11894f781v};
496727e995b7bba3c57fb1e5c156d386ca11894f781v
497727e995b7bba3c57fb1e5c156d386ca11894f781v/* --- *
498727e995b7bba3c57fb1e5c156d386ca11894f781v * P a c k e t
499727e995b7bba3c57fb1e5c156d386ca11894f781v * --- */
500727e995b7bba3c57fb1e5c156d386ca11894f781v
501727e995b7bba3c57fb1e5c156d386ca11894f781vvar DATA_SIZE = 4;
502727e995b7bba3c57fb1e5c156d386ca11894f781v
503727e995b7bba3c57fb1e5c156d386ca11894f781v/**
504727e995b7bba3c57fb1e5c156d386ca11894f781v * A simple package of data that is manipulated by the tasks.  The exact layout
505727e995b7bba3c57fb1e5c156d386ca11894f781v * of the payload data carried by a packet is not importaint, and neither is the
506727e995b7bba3c57fb1e5c156d386ca11894f781v * nature of the work performed on packets by the tasks.
507727e995b7bba3c57fb1e5c156d386ca11894f781v *
508727e995b7bba3c57fb1e5c156d386ca11894f781v * Besides carrying data, packets form linked lists and are hence used both as
509727e995b7bba3c57fb1e5c156d386ca11894f781v * data and worklists.
510727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} link the tail of the linked list of packets
511727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} id an ID for this packet
512727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {int} kind the type of this packet
513727e995b7bba3c57fb1e5c156d386ca11894f781v * @constructor
514727e995b7bba3c57fb1e5c156d386ca11894f781v */
515727e995b7bba3c57fb1e5c156d386ca11894f781vfunction Packet(link, id, kind) {
516727e995b7bba3c57fb1e5c156d386ca11894f781v  this.link = link;
517727e995b7bba3c57fb1e5c156d386ca11894f781v  this.id = id;
518727e995b7bba3c57fb1e5c156d386ca11894f781v  this.kind = kind;
519727e995b7bba3c57fb1e5c156d386ca11894f781v  this.a1 = 0;
520727e995b7bba3c57fb1e5c156d386ca11894f781v  this.a2 = new Array(DATA_SIZE);
521727e995b7bba3c57fb1e5c156d386ca11894f781v}
522727e995b7bba3c57fb1e5c156d386ca11894f781v
523727e995b7bba3c57fb1e5c156d386ca11894f781v/**
524727e995b7bba3c57fb1e5c156d386ca11894f781v * Add this packet to the end of a worklist, and return the worklist.
525727e995b7bba3c57fb1e5c156d386ca11894f781v * @param {Packet} queue the worklist to add this packet to
526727e995b7bba3c57fb1e5c156d386ca11894f781v */
527727e995b7bba3c57fb1e5c156d386ca11894f781vPacket.prototype.addTo = function (queue) {
528727e995b7bba3c57fb1e5c156d386ca11894f781v  this.link = null;
529727e995b7bba3c57fb1e5c156d386ca11894f781v  if (queue == null) return this;
530727e995b7bba3c57fb1e5c156d386ca11894f781v  var peek, next = queue;
531727e995b7bba3c57fb1e5c156d386ca11894f781v  while ((peek = next.link) != null)
532727e995b7bba3c57fb1e5c156d386ca11894f781v    next = peek;
533727e995b7bba3c57fb1e5c156d386ca11894f781v  next.link = this;
534727e995b7bba3c57fb1e5c156d386ca11894f781v  return queue;
535727e995b7bba3c57fb1e5c156d386ca11894f781v};
536727e995b7bba3c57fb1e5c156d386ca11894f781v
537727e995b7bba3c57fb1e5c156d386ca11894f781vPacket.prototype.toString = function () {
538727e995b7bba3c57fb1e5c156d386ca11894f781v  return "Packet";
539727e995b7bba3c57fb1e5c156d386ca11894f781v};
540