// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: prioque.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
* Copyright (C) 2004 Sun Microsystems, Inc.
#pragma ident "@(#)1.2 04/08/13 prioque.cc"
extern long SYSTEM_get_time (int whence
= 0);
/*static*/ int EventQue::debug
= 0;
/*static*/ volatile int EventQue::event_id
= 1;
#define PQ_PARENT(x) ((x)>>1)
#define PQ_LEFT(x) ((x)<<1)
#define PQ_RIGHT(x) (((x)<<1)+1)
_heap
= (Event_t
*) malloc ((_limit
+1) * sizeof (Event_t
));
mutex_init (&_lock
, 0, 0); // other options include recursive locks, ...
_heap
= (Event_t
*) realloc (_heap
, (_limit
+1) * sizeof (Event_t
));
static int ulog2 (uint32_t x
) {int i
; for (i
=-1;x
>0;i
++) x
>>=1; return i
;}
static void indent (int x
) { for (int i
= 0; i
< x
; i
++) printf (" "); }
void EventQue::internaldebug (int x
) {
if (x
== 1) printf ("size=%d\n", _size
);
if (PQ_RIGHT(x
) <= _size
)
internaldebug (PQ_RIGHT(x
));
// identify violations of the heap-invariant (top down sorted property)
if (x
>1 && _heap
[x
].pq_priority
< _heap
[PQ_PARENT(x
)].pq_priority
)
indent (ulog2 (x
)); printf ("%d: %lld\n", x
, _heap
[x
].pq_priority
);
internaldebug (PQ_LEFT(x
));
EventQue::_topdown_update (int index
) // aka. MIN-HEAPIFY in "Intro to Algs",
// but should have been called MIN-INCREASE-KEY for symmetry!
// Top down restoration of the heap invariant starting at index,
// assuming that only the node at index has been modified and that
// only that node potentially fails the invariant. It might have to
// percolate downwards if its priority is too high (too far in the future).
uint64_t min
= _heap
[index
].pq_priority
;
/* see if a child has lower priority (earlier time) than index's */
if (PQ_LEFT(index
) <= _size
&& _heap
[PQ_LEFT(index
)].pq_priority
< min
) {
min
= _heap
[PQ_LEFT(index
)].pq_priority
;
if (PQ_RIGHT(index
) <= _size
&& _heap
[PQ_RIGHT(index
)].pq_priority
< min
) {
min
= _heap
[PQ_RIGHT(index
)].pq_priority
;
/* if so swap it up into index's place, then descend... */
Event_t temp
= _heap
[index
]; // copy semantics, ugh...
_heap
[index
] = _heap
[imin
]; // ugh...
_heap
[imin
] = temp
; // ugh...
// fix parameters and loop, instead of recursing
min
= _heap
[index
].pq_priority
; // loop invar, but comp wont figure it
EventQue::_bottomup_update (int index
) // aka. MIN-DECREASE-KEY in "Intro to Algs"
// Bottom up restoration of the heap invariant starting at index,
// assuming that only the node at index has been modified and that
// only that node potentially fails the invariant. If might have to
// percolate updwards if its priority is too low (too near in the future).
uint64_t min
= _heap
[index
].pq_priority
;
/* see if index has a lower priority (earlier time) than its parent */
if (index
> 1 && min
< _heap
[PQ_PARENT(index
)].pq_priority
) {
/* oops, dont do this!: min = _heap[imin].pq_priority; */
/* if so swap it up into its parent's place, then ascend... */
Event_t temp
= _heap
[index
]; // copy semantics, ugh...
_heap
[index
] = _heap
[imin
]; // ugh...
_heap
[imin
] = temp
; // ugh...
// fix parameters and loop, instead of recursing
EventQue::_insert (Event_t
* object
)
_heap
[_size
+1] = *object
; // copy semantics...
_bottomup_update (_size
+1);
EventQue::_delete (Event_t
* object
)
if (object
!= NULL
) *object
= _heap
[1]; // copy semantics...
/* Stateless random number generator, 31-bit integer result. */
/* See "Random Number Generators: Good Ones Are Hard To Find", */
/* Park & Miller, CACM 31#10 October 1988 pages 1192-1201. */
#define _A_MULTIPLIER 16807
#define _M_MODULUS 2147483647 /* (2**31)-1 */
#define _Q_QUOTIENT 127773 /* 2147483647 / 16807 */
#define _R_REMAINDER 2836 /* 2147483647 % 16807 */
next
= _A_MULTIPLIER
* lo
- _R_REMAINDER
* hi
;
return next
+ _M_MODULUS
;
int main (int argc
, char * argv
[])
if (argc
== 2 && strcmp (argv
[1], "-rand") == 0) {
printf ("%4d\n", RN
%1000);
printf ("\ta.out > prioque.out;\n");
printf ("\ta.out -rand | sort > sort.out;\n");
printf ("\tdiff prioque.out sort.out; # should be equal...\n");
for (i
=0; i
<100; i
++) { // insert 100 items
pq
.insert_mondo ((uint64_t)RN
%1000, (uint64_t)RN
%1000, &dummy_data
[0]);
/*printf ("--- after insert ---\n");pq.debug ();*/
printf ("1) size=%d, expecting 10\n", pq
.size ());
for (i
=0; i
<900; i
++) { // insert and delete 900
if (temp
.pq_kind
== EventQue::PQ_MONDO
) {
printf ("%4d\n", (int)temp
.pq_ctrl
);
printf ("2.a) kind=%d, expecting %d\n", temp
.pq_kind
, EventQue::PQ_MONDO
);
pq
.insert_mondo ((uint64_t)RN
%1000, (uint64_t)RN
%1000, &dummy_data
[0]);
printf ("2) size=%d, expecting 10\n", pq
.size ());
for (i
=0; i
<100; i
++) { // delete 100 items
if (temp
.pq_kind
== EventQue::PQ_MONDO
) {
printf ("%4d\n", (int)temp
.pq_ctrl
);
printf ("3.a) kind=%d, expecting %d\n", temp
.pq_kind
, EventQue::PQ_MONDO
);
/*printf ("--- after delete ---\n");pq.debug ();*/
if (!pq
.empty () || pq
.size () != 0)
printf ("3) size=%d, expecting 0\n", pq
.size ());