* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: SS_Message.h
* 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 ============================================
// SS_Message is the container class that holds messages for
// a strand that need to be dealth with on the next step.
// The class is the crucial element in the run loop of the
// strand, and part of it's implementation directly impacts
// performance in a big way. The SS_Strand::get_signal is
// the only consumer of this class.
// is_pending() returns true if one or more messages have been
// send to the strand. This routines is the key test in the
// tight runloop of the strand and should not be changed.
// set_reenter_loop() is used to send a message to the strand
// that special state such as pstate and hpstate of the strand
// changed and w\it needs to get out of the loop to update things
// like global variables held in registers. Currently only
// SS_Strand::ss_sim_update calls this function.
void set_reenter_loop() { flag
.reenterloop
= 1; }
// clr_reenter_loop() is used to notify that the reenter loop
void clr_reenter_loop() { flag
.reenterloop
= 0; }
// set_handle_trap() is used to message othe strand that the
// next step should launch the trap handler. Only SS_Interrupt
// calls this method as it controls which trap is launched.
void set_handle_trap( SS_Trap::Type tt
)
assert(tt
< SS_Trap::TCC_INSTRUCTION
);
assert(SS_Trap::Type(flag
.trap_type
) == SS_Trap::RESERVED
);
// clr_handle_trap() is used to notify that the trap has been
// handled: the strand is now set to step into the trap code.
flag
.trap_type
= SS_Trap::RESERVED
;
// get_handle_trap() is used to find out if a trap is to be
// handled. A return value SS_Trap:RESERVED means no trap.
SS_Trap::Type
get_handle_trap()
return SS_Trap::Type(flag
.trap_type
);
// test_signal() returns true while there are SS_Signal type
// messages pending. get_signal() is used to consume those
bool test_signal() { return head
->next
!= 0; }
// post_signal() is used to send a SS_Signal based message
// to the strand. The routine is MP safe; it uses a mutex for enqueue.
void post_signal( SS_Signal
* node
)
tail
= tail
->next
= node
;
bl_atomic_add32((int32_t*)&flag
.signal
,1);
// get_signal() is used by the strand to consume a posted SS_Signal
// message. This routine can only be used when test_signal() returns
// true. Note each strand has one SS_Message instance so there is
// only one user of get_signal(), hence dequeue does not have to
// use MP safe constructs.
// There is always one SS_Signal on an empty queue. On a non empty queue
// the SS_Signal after the head is the one we are interested in.
SS_Signal
* help
= temp
->next
;
bl_atomic_add32((int32_t*)&flag
.signal
,-1);
temp
->type
= SS_Signal::FREE
;
if (free_count
>= free_count_max
)
SS_Signal
* h
= free_list
;
for (temp
= free_list
->next
;
free_count
> free_count_max
/2;
assert(free_list
->type
== SS_Signal::FREE
);
SS_Signal
* t
= free_list
;
SS_Signal::list_free(h
, t
);
// make_signal() creates a new signal that can be posted to a strand.
// This class maintains it's own pool of signals for MP scalability
SS_Signal
* make_signal( SS_Signal::Type type
)
SS_Signal
* help
= free_list
;
return SS_Signal::alloc(type
);
void snapshot( SS_SnapShot
& ss
, const char* prefix
);
// The Flags structure holds all fast but not MP safe flags. These
// can only be set by the strand itself. The signal flag is used
// for the MP safe SS_Signal based list.
uint8_t reenterloop
; // Get out of tight loop and reenter
uint8_t trap_type
; // Handle (disrupting) trap on th next step
uint8_t spare
[2]; // Reserved for future fast lock free flags
int32_t signal
; // Used to count number SS_Signals pending
uint64_t pending
; // One 8 byte load to test all the flags
Flags flag
; // The flags for fast messages
// The signal queue always has a valid head and tail pointer.
SS_Signal
* head
; // Head of the message queue
SS_Signal
* tail
; // Tail of the message queue
SS_Signal
* free_list
; // Free list of signals
uint_t free_count
; // Nr signals on free list
static const uint_t free_count_max
= 1024;