sc_cor_qt.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_cor_qt.cpp -- Coroutine implementation with QuickThreads.
00021 
00022   Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date:
00032   Description of Modification:
00033 
00034  *****************************************************************************/
00035 
00036 
00037 // $Log: sc_cor_qt.cpp,v $
00038 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00039 // SystemC 2.2
00040 //
00041 // Revision 1.3  2006/01/13 18:44:29  acg
00042 // Added $Log to record CVS changes into the source.
00043 //
00044 
00045 #if !defined(WIN32) && !defined(SC_USE_PTHREADS)
00046 
00047 #include <unistd.h>
00048 #include <sys/mman.h>
00049 
00050 #include "sysc/kernel/sc_cor_qt.h"
00051 #include "sysc/kernel/sc_simcontext.h"
00052 
00053 namespace sc_core {
00054 
00055 // ----------------------------------------------------------------------------
00056 //  File static variables.
00057 // ----------------------------------------------------------------------------
00058 
00059 // main coroutine
00060 
00061 static sc_cor_qt main_cor;
00062 
00063 // current coroutine
00064 
00065 static sc_cor_qt* curr_cor = 0;
00066 
00067 
00068 // ----------------------------------------------------------------------------
00069 //  CLASS : sc_cor_qt
00070 //
00071 //  Coroutine class implemented with QuickThreads.
00072 // ----------------------------------------------------------------------------
00073 
00074 // switch stack protection on/off
00075 
00076 void
00077 sc_cor_qt::stack_protect( bool enable )
00078 {
00079     // Code needs to be tested on HP-UX and disabled if it doesn't work there
00080     // Code still needs to be ported to WIN32
00081 
00082     static std::size_t pagesize;
00083     
00084     if( pagesize == 0 ) {
00085 #       if defined(__ppc__)
00086         pagesize = getpagesize();
00087 #       else
00088         pagesize = sysconf( _SC_PAGESIZE );
00089 #       endif 
00090     }
00091 
00092     assert( pagesize != 0 );
00093     assert( m_stack_size > ( 2 * pagesize ) );
00094 
00095 #ifdef QUICKTHREADS_GROW_DOWN
00096     // Stacks grow from high address down to low address
00097     caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + pagesize - 1 ) /
00098                  pagesize ) * pagesize );
00099 #else
00100     // Stacks grow from low address up to high address
00101     caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) +
00102                    m_stack_size - pagesize ) /
00103                  pagesize ) * pagesize );
00104 #endif
00105 
00106     int ret;
00107 
00108     if( enable ) {
00109     ret = mprotect( redzone, pagesize - 1, PROT_NONE );
00110     } else {
00111     ret = mprotect( redzone, pagesize - 1, PROT_READ | PROT_WRITE );
00112     }
00113 
00114     assert( ret == 0 );
00115 }
00116 
00117 
00118 // ----------------------------------------------------------------------------
00119 //  CLASS : sc_cor_pkg_qt
00120 //
00121 //  Coroutine package class implemented with QuickThreads.
00122 // ----------------------------------------------------------------------------
00123 
00124 int sc_cor_pkg_qt::instance_count = 0;
00125 
00126 
00127 // support function
00128 
00129 inline
00130 void*
00131 stack_align( void* sp, int alignment, std::size_t* stack_size )
00132 {
00133     int round_up_mask = alignment - 1;
00134     *stack_size = (*stack_size + round_up_mask) & ~round_up_mask;
00135     return ( (void*)(((qt_word_t) sp + round_up_mask) & ~round_up_mask) );
00136 }
00137 
00138 
00139 // constructor
00140 
00141 sc_cor_pkg_qt::sc_cor_pkg_qt( sc_simcontext* simc )
00142 : sc_cor_pkg( simc )
00143 {
00144     if( ++ instance_count == 1 ) {
00145     // initialize the current coroutine
00146     assert( curr_cor == 0 );
00147     curr_cor = &main_cor;
00148     }
00149 }
00150 
00151 
00152 // destructor
00153 
00154 sc_cor_pkg_qt::~sc_cor_pkg_qt()
00155 {
00156     if( -- instance_count == 0 ) {
00157     // cleanup the current coroutine
00158     curr_cor = 0;
00159     }
00160 }
00161 
00162 
00163 // create a new coroutine
00164 
00165 extern "C"
00166 void
00167 sc_cor_qt_wrapper( void* arg, void* cor, qt_userf_t* fn )
00168 {
00169     curr_cor = RCAST<sc_cor_qt*>( cor );
00170     // invoke the user function
00171     (*(sc_cor_fn*) fn)( arg );
00172     // not reached
00173 }
00174 
00175 sc_cor*
00176 sc_cor_pkg_qt::create( std::size_t stack_size, sc_cor_fn* fn, void* arg )
00177 {
00178     sc_cor_qt* cor = new sc_cor_qt();
00179     cor->m_pkg = this;
00180     cor->m_stack_size = stack_size;
00181     cor->m_stack = new char[cor->m_stack_size];
00182     void* sto = stack_align( cor->m_stack, QUICKTHREADS_STKALIGN, 
00183         &cor->m_stack_size );
00184     cor->m_sp = QUICKTHREADS_SP(sto, cor->m_stack_size - QUICKTHREADS_STKALIGN);
00185     cor->m_sp = QUICKTHREADS_ARGS( cor->m_sp, arg, cor, (qt_userf_t*) fn,
00186              sc_cor_qt_wrapper );
00187     return cor;
00188 }
00189 
00190 
00191 // yield to the next coroutine
00192 
00193 extern "C"
00194 void*
00195 sc_cor_qt_yieldhelp( qt_t* sp, void* old_cor, void* )
00196 {
00197     RCAST<sc_cor_qt*>( old_cor )->m_sp = sp;
00198     return 0;
00199 }
00200 
00201 void
00202 sc_cor_pkg_qt::yield( sc_cor* next_cor )
00203 {
00204     sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor );
00205     sc_cor_qt* old_cor = curr_cor;
00206     curr_cor = new_cor;
00207     QUICKTHREADS_BLOCK( sc_cor_qt_yieldhelp, old_cor, 0, new_cor->m_sp );
00208 }
00209 
00210 
00211 // abort the current coroutine (and resume the next coroutine)
00212 
00213 extern "C"
00214 void*
00215 sc_cor_qt_aborthelp( qt_t*, void*, void* )
00216 {
00217     return 0;
00218 }
00219 
00220 void
00221 sc_cor_pkg_qt::abort( sc_cor* next_cor )
00222 {
00223     sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor );
00224     sc_cor_qt* old_cor = curr_cor;
00225     curr_cor = new_cor;
00226     QUICKTHREADS_ABORT( sc_cor_qt_aborthelp, old_cor, 0, new_cor->m_sp );
00227 }
00228 
00229 
00230 // get the main coroutine
00231 
00232 sc_cor*
00233 sc_cor_pkg_qt::get_main()
00234 {
00235     return &main_cor;
00236 }
00237 
00238 } // namespace sc_core
00239 
00240 #endif
00241 
00242 
00243 // Taf!

Generated on Wed Jan 21 15:32:09 2009 for SystemC by  doxygen 1.5.5