112027Sjungma@eit.uni-kl.de/*****************************************************************************
212027Sjungma@eit.uni-kl.de
312027Sjungma@eit.uni-kl.de  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412027Sjungma@eit.uni-kl.de  more contributor license agreements.  See the NOTICE file distributed
512027Sjungma@eit.uni-kl.de  with this work for additional information regarding copyright ownership.
612027Sjungma@eit.uni-kl.de  Accellera licenses this file to you under the Apache License, Version 2.0
712027Sjungma@eit.uni-kl.de  (the "License"); you may not use this file except in compliance with the
812027Sjungma@eit.uni-kl.de  License.  You may obtain a copy of the License at
912027Sjungma@eit.uni-kl.de
1012027Sjungma@eit.uni-kl.de    http://www.apache.org/licenses/LICENSE-2.0
1112027Sjungma@eit.uni-kl.de
1212027Sjungma@eit.uni-kl.de  Unless required by applicable law or agreed to in writing, software
1312027Sjungma@eit.uni-kl.de  distributed under the License is distributed on an "AS IS" BASIS,
1412027Sjungma@eit.uni-kl.de  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512027Sjungma@eit.uni-kl.de  implied.  See the License for the specific language governing
1612027Sjungma@eit.uni-kl.de  permissions and limitations under the License.
1712027Sjungma@eit.uni-kl.de
1812027Sjungma@eit.uni-kl.de *****************************************************************************/
1912027Sjungma@eit.uni-kl.de
2012027Sjungma@eit.uni-kl.de/*****************************************************************************
2112027Sjungma@eit.uni-kl.de
2212027Sjungma@eit.uni-kl.de  sc_cor_qt.cpp -- Coroutine implementation with QuickThreads.
2312027Sjungma@eit.uni-kl.de
2412027Sjungma@eit.uni-kl.de  Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18
2512027Sjungma@eit.uni-kl.de
2612027Sjungma@eit.uni-kl.de CHANGE LOG APPEARS AT THE END OF THE FILE
2712027Sjungma@eit.uni-kl.de *****************************************************************************/
2812027Sjungma@eit.uni-kl.de
2912027Sjungma@eit.uni-kl.de#if !defined(_WIN32) && !defined(WIN32) && !defined(SC_USE_PTHREADS)
3012027Sjungma@eit.uni-kl.de
3112027Sjungma@eit.uni-kl.de#include <unistd.h>
3212027Sjungma@eit.uni-kl.de#include <sys/mman.h>
3312027Sjungma@eit.uni-kl.de#include <sys/types.h>
3412027Sjungma@eit.uni-kl.de
3512027Sjungma@eit.uni-kl.de#include "sysc/kernel/sc_cor_qt.h"
3612027Sjungma@eit.uni-kl.de#include "sysc/kernel/sc_simcontext.h"
3712027Sjungma@eit.uni-kl.de
3812027Sjungma@eit.uni-kl.denamespace sc_core {
3912027Sjungma@eit.uni-kl.de
4012027Sjungma@eit.uni-kl.de// ----------------------------------------------------------------------------
4112027Sjungma@eit.uni-kl.de//  File static variables.
4212027Sjungma@eit.uni-kl.de// ----------------------------------------------------------------------------
4312027Sjungma@eit.uni-kl.de
4412027Sjungma@eit.uni-kl.de// main coroutine
4512027Sjungma@eit.uni-kl.de
4612027Sjungma@eit.uni-kl.destatic sc_cor_qt main_cor;
4712027Sjungma@eit.uni-kl.de
4812027Sjungma@eit.uni-kl.de// current coroutine
4912027Sjungma@eit.uni-kl.de
5012027Sjungma@eit.uni-kl.destatic sc_cor_qt* curr_cor = 0;
5112027Sjungma@eit.uni-kl.de
5212027Sjungma@eit.uni-kl.de
5312027Sjungma@eit.uni-kl.de// ----------------------------------------------------------------------------
5412027Sjungma@eit.uni-kl.de//  CLASS : sc_cor_qt
5512027Sjungma@eit.uni-kl.de//
5612027Sjungma@eit.uni-kl.de//  Coroutine class implemented with QuickThreads.
5712027Sjungma@eit.uni-kl.de// ----------------------------------------------------------------------------
5812027Sjungma@eit.uni-kl.de
5912027Sjungma@eit.uni-kl.de// switch stack protection on/off
6012027Sjungma@eit.uni-kl.de
6112027Sjungma@eit.uni-kl.devoid
6212027Sjungma@eit.uni-kl.desc_cor_qt::stack_protect( bool enable )
6312027Sjungma@eit.uni-kl.de{
6412027Sjungma@eit.uni-kl.de    // Code needs to be tested on HP-UX and disabled if it doesn't work there
6512027Sjungma@eit.uni-kl.de    // Code still needs to be ported to WIN32
6612027Sjungma@eit.uni-kl.de
6712027Sjungma@eit.uni-kl.de    static std::size_t pagesize;
6812027Sjungma@eit.uni-kl.de
6912027Sjungma@eit.uni-kl.de    if( pagesize == 0 ) {
7012027Sjungma@eit.uni-kl.de#       if defined(__ppc__)
7112027Sjungma@eit.uni-kl.de	    pagesize = getpagesize();
7212027Sjungma@eit.uni-kl.de#       else
7312027Sjungma@eit.uni-kl.de	    pagesize = sysconf( _SC_PAGESIZE );
7412027Sjungma@eit.uni-kl.de#       endif
7512027Sjungma@eit.uni-kl.de    }
7612027Sjungma@eit.uni-kl.de
7712027Sjungma@eit.uni-kl.de    assert( pagesize != 0 );
7812027Sjungma@eit.uni-kl.de    assert( m_stack_size > ( 2 * pagesize ) );
7912027Sjungma@eit.uni-kl.de
8012027Sjungma@eit.uni-kl.de#ifdef QUICKTHREADS_GROW_DOWN
8112027Sjungma@eit.uni-kl.de    // Stacks grow from high address down to low address
8212027Sjungma@eit.uni-kl.de    caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + pagesize - 1 ) /
8312027Sjungma@eit.uni-kl.de				 pagesize ) * pagesize );
8412027Sjungma@eit.uni-kl.de#else
8512027Sjungma@eit.uni-kl.de    // Stacks grow from low address up to high address
8612027Sjungma@eit.uni-kl.de    caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) +
8712027Sjungma@eit.uni-kl.de				   m_stack_size - pagesize ) /
8812027Sjungma@eit.uni-kl.de				 pagesize ) * pagesize );
8912027Sjungma@eit.uni-kl.de#endif
9012027Sjungma@eit.uni-kl.de
9112027Sjungma@eit.uni-kl.de    int ret;
9212027Sjungma@eit.uni-kl.de
9312027Sjungma@eit.uni-kl.de    // Enable the red zone at the end of the stack so that references within
9412027Sjungma@eit.uni-kl.de    // it will cause an interrupt.
9512027Sjungma@eit.uni-kl.de
9612027Sjungma@eit.uni-kl.de    if( enable ) {
9712027Sjungma@eit.uni-kl.de        ret = mprotect( redzone, pagesize - 1, PROT_NONE );
9812027Sjungma@eit.uni-kl.de    }
9912027Sjungma@eit.uni-kl.de
10012027Sjungma@eit.uni-kl.de    // Revert the red zone to normal memory usage. Try to make it read - write -
10112027Sjungma@eit.uni-kl.de    // execute. If that does not work then settle for read - write
10212027Sjungma@eit.uni-kl.de
10312027Sjungma@eit.uni-kl.de    else {
10412027Sjungma@eit.uni-kl.de        ret = mprotect( redzone, pagesize - 1, PROT_READ|PROT_WRITE|PROT_EXEC);
10512027Sjungma@eit.uni-kl.de        if ( ret != 0 )
10612027Sjungma@eit.uni-kl.de            ret = mprotect( redzone, pagesize - 1, PROT_READ | PROT_WRITE );
10712027Sjungma@eit.uni-kl.de    }
10812027Sjungma@eit.uni-kl.de
10912027Sjungma@eit.uni-kl.de    assert( ret == 0 );
11012027Sjungma@eit.uni-kl.de}
11112027Sjungma@eit.uni-kl.de
11212027Sjungma@eit.uni-kl.de
11312027Sjungma@eit.uni-kl.de// ----------------------------------------------------------------------------
11412027Sjungma@eit.uni-kl.de//  CLASS : sc_cor_pkg_qt
11512027Sjungma@eit.uni-kl.de//
11612027Sjungma@eit.uni-kl.de//  Coroutine package class implemented with QuickThreads.
11712027Sjungma@eit.uni-kl.de// ----------------------------------------------------------------------------
11812027Sjungma@eit.uni-kl.de
11912027Sjungma@eit.uni-kl.deint sc_cor_pkg_qt::instance_count = 0;
12012027Sjungma@eit.uni-kl.de
12112027Sjungma@eit.uni-kl.de
12212027Sjungma@eit.uni-kl.de// support function
12312027Sjungma@eit.uni-kl.de
12412027Sjungma@eit.uni-kl.deinline
12512027Sjungma@eit.uni-kl.devoid*
12612027Sjungma@eit.uni-kl.destack_align( void* sp, int alignment, std::size_t* stack_size )
12712027Sjungma@eit.uni-kl.de{
12812027Sjungma@eit.uni-kl.de    int round_up_mask = alignment - 1;
12912027Sjungma@eit.uni-kl.de    *stack_size = (*stack_size + round_up_mask) & ~round_up_mask;
13012027Sjungma@eit.uni-kl.de    return ( (void*)(((qt_word_t) sp + round_up_mask) & ~round_up_mask) );
13112027Sjungma@eit.uni-kl.de}
13212027Sjungma@eit.uni-kl.de
13312027Sjungma@eit.uni-kl.de
13412027Sjungma@eit.uni-kl.de// constructor
13512027Sjungma@eit.uni-kl.de
13612027Sjungma@eit.uni-kl.desc_cor_pkg_qt::sc_cor_pkg_qt( sc_simcontext* simc )
13712027Sjungma@eit.uni-kl.de: sc_cor_pkg( simc )
13812027Sjungma@eit.uni-kl.de{
13912027Sjungma@eit.uni-kl.de    if( ++ instance_count == 1 ) {
14012027Sjungma@eit.uni-kl.de	// initialize the current coroutine
14112027Sjungma@eit.uni-kl.de	assert( curr_cor == 0 );
14212027Sjungma@eit.uni-kl.de	curr_cor = &main_cor;
14312027Sjungma@eit.uni-kl.de    }
14412027Sjungma@eit.uni-kl.de}
14512027Sjungma@eit.uni-kl.de
14612027Sjungma@eit.uni-kl.de
14712027Sjungma@eit.uni-kl.de// destructor
14812027Sjungma@eit.uni-kl.de
14912027Sjungma@eit.uni-kl.desc_cor_pkg_qt::~sc_cor_pkg_qt()
15012027Sjungma@eit.uni-kl.de{
15112027Sjungma@eit.uni-kl.de    if( -- instance_count == 0 ) {
15212027Sjungma@eit.uni-kl.de	// cleanup the current coroutine
15312027Sjungma@eit.uni-kl.de	curr_cor = 0;
15412027Sjungma@eit.uni-kl.de    }
15512027Sjungma@eit.uni-kl.de}
15612027Sjungma@eit.uni-kl.de
15712027Sjungma@eit.uni-kl.de
15812027Sjungma@eit.uni-kl.de// create a new coroutine
15912027Sjungma@eit.uni-kl.de
16012027Sjungma@eit.uni-kl.deextern "C"
16112027Sjungma@eit.uni-kl.devoid
16212027Sjungma@eit.uni-kl.desc_cor_qt_wrapper( void* arg, void* cor, qt_userf_t* fn )
16312027Sjungma@eit.uni-kl.de{
16412027Sjungma@eit.uni-kl.de    curr_cor = RCAST<sc_cor_qt*>( cor );
16512027Sjungma@eit.uni-kl.de    // invoke the user function
16612027Sjungma@eit.uni-kl.de    (*(sc_cor_fn*) fn)( arg );
16712027Sjungma@eit.uni-kl.de    // not reached
16812027Sjungma@eit.uni-kl.de}
16912027Sjungma@eit.uni-kl.de
17012027Sjungma@eit.uni-kl.desc_cor*
17112027Sjungma@eit.uni-kl.desc_cor_pkg_qt::create( std::size_t stack_size, sc_cor_fn* fn, void* arg )
17212027Sjungma@eit.uni-kl.de{
17312027Sjungma@eit.uni-kl.de    sc_cor_qt* cor = new sc_cor_qt();
17412027Sjungma@eit.uni-kl.de    cor->m_pkg = this;
17512027Sjungma@eit.uni-kl.de    cor->m_stack_size = stack_size;
17612027Sjungma@eit.uni-kl.de    cor->m_stack = new char[cor->m_stack_size];
17712027Sjungma@eit.uni-kl.de    void* sto = stack_align( cor->m_stack, QUICKTHREADS_STKALIGN,
17812027Sjungma@eit.uni-kl.de                             &cor->m_stack_size );
17912027Sjungma@eit.uni-kl.de    cor->m_sp = QUICKTHREADS_SP(sto, cor->m_stack_size - QUICKTHREADS_STKALIGN);
18012027Sjungma@eit.uni-kl.de    cor->m_sp = QUICKTHREADS_ARGS( cor->m_sp, arg, cor, (qt_userf_t*) fn,
18112027Sjungma@eit.uni-kl.de			           sc_cor_qt_wrapper );
18212027Sjungma@eit.uni-kl.de    return cor;
18312027Sjungma@eit.uni-kl.de}
18412027Sjungma@eit.uni-kl.de
18512027Sjungma@eit.uni-kl.de
18612027Sjungma@eit.uni-kl.de// yield to the next coroutine
18712027Sjungma@eit.uni-kl.de
18812027Sjungma@eit.uni-kl.deextern "C"
18912027Sjungma@eit.uni-kl.devoid*
19012027Sjungma@eit.uni-kl.desc_cor_qt_yieldhelp( qt_t* sp, void* old_cor, void* )
19112027Sjungma@eit.uni-kl.de{
19212027Sjungma@eit.uni-kl.de    RCAST<sc_cor_qt*>( old_cor )->m_sp = sp;
19312027Sjungma@eit.uni-kl.de    return 0;
19412027Sjungma@eit.uni-kl.de}
19512027Sjungma@eit.uni-kl.de
19612027Sjungma@eit.uni-kl.devoid
19712027Sjungma@eit.uni-kl.desc_cor_pkg_qt::yield( sc_cor* next_cor )
19812027Sjungma@eit.uni-kl.de{
19912027Sjungma@eit.uni-kl.de    sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor );
20012027Sjungma@eit.uni-kl.de    sc_cor_qt* old_cor = curr_cor;
20112027Sjungma@eit.uni-kl.de    curr_cor = new_cor;
20212027Sjungma@eit.uni-kl.de    QUICKTHREADS_BLOCK( sc_cor_qt_yieldhelp, old_cor, 0, new_cor->m_sp );
20312027Sjungma@eit.uni-kl.de}
20412027Sjungma@eit.uni-kl.de
20512027Sjungma@eit.uni-kl.de
20612027Sjungma@eit.uni-kl.de// abort the current coroutine (and resume the next coroutine)
20712027Sjungma@eit.uni-kl.de
20812027Sjungma@eit.uni-kl.deextern "C"
20912027Sjungma@eit.uni-kl.devoid*
21012027Sjungma@eit.uni-kl.desc_cor_qt_aborthelp( qt_t*, void*, void* )
21112027Sjungma@eit.uni-kl.de{
21212027Sjungma@eit.uni-kl.de    return 0;
21312027Sjungma@eit.uni-kl.de}
21412027Sjungma@eit.uni-kl.de
21512027Sjungma@eit.uni-kl.devoid
21612027Sjungma@eit.uni-kl.desc_cor_pkg_qt::abort( sc_cor* next_cor )
21712027Sjungma@eit.uni-kl.de{
21812027Sjungma@eit.uni-kl.de    sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor );
21912027Sjungma@eit.uni-kl.de    sc_cor_qt* old_cor = curr_cor;
22012027Sjungma@eit.uni-kl.de    curr_cor = new_cor;
22112027Sjungma@eit.uni-kl.de    QUICKTHREADS_ABORT( sc_cor_qt_aborthelp, old_cor, 0, new_cor->m_sp );
22212027Sjungma@eit.uni-kl.de}
22312027Sjungma@eit.uni-kl.de
22412027Sjungma@eit.uni-kl.de
22512027Sjungma@eit.uni-kl.de// get the main coroutine
22612027Sjungma@eit.uni-kl.de
22712027Sjungma@eit.uni-kl.desc_cor*
22812027Sjungma@eit.uni-kl.desc_cor_pkg_qt::get_main()
22912027Sjungma@eit.uni-kl.de{
23012027Sjungma@eit.uni-kl.de    return &main_cor;
23112027Sjungma@eit.uni-kl.de}
23212027Sjungma@eit.uni-kl.de
23312027Sjungma@eit.uni-kl.de} // namespace sc_core
23412027Sjungma@eit.uni-kl.de
23512027Sjungma@eit.uni-kl.de#endif
23612027Sjungma@eit.uni-kl.de
23712027Sjungma@eit.uni-kl.de// $Log: sc_cor_qt.cpp,v $
23812027Sjungma@eit.uni-kl.de// Revision 1.9  2011/08/29 18:04:32  acg
23912027Sjungma@eit.uni-kl.de//  Philipp A. Hartmann: miscellaneous clean ups.
24012027Sjungma@eit.uni-kl.de//
24112027Sjungma@eit.uni-kl.de// Revision 1.8  2011/08/26 20:46:09  acg
24212027Sjungma@eit.uni-kl.de//  Andy Goodrich: moved the modification log to the end of the file to
24312027Sjungma@eit.uni-kl.de//  eliminate source line number skew when check-ins are done.
24412027Sjungma@eit.uni-kl.de//
24512027Sjungma@eit.uni-kl.de// Revision 1.7  2011/02/18 20:27:14  acg
24612027Sjungma@eit.uni-kl.de//  Andy Goodrich: Updated Copyrights.
24712027Sjungma@eit.uni-kl.de//
24812027Sjungma@eit.uni-kl.de// Revision 1.6  2011/02/13 21:47:37  acg
24912027Sjungma@eit.uni-kl.de//  Andy Goodrich: update copyright notice.
25012027Sjungma@eit.uni-kl.de//
25112027Sjungma@eit.uni-kl.de// Revision 1.5  2010/08/03 16:52:14  acg
25212027Sjungma@eit.uni-kl.de//  Andy Goodrich: line formatting.
25312027Sjungma@eit.uni-kl.de//
25412027Sjungma@eit.uni-kl.de// Revision 1.4  2008/11/11 14:03:07  acg
25512027Sjungma@eit.uni-kl.de//  Andy Goodrich: added execute access to the release of red zone storage
25612027Sjungma@eit.uni-kl.de//  per Ulli's suggestion.
25712027Sjungma@eit.uni-kl.de//
25812027Sjungma@eit.uni-kl.de// Revision 1.3  2008/05/22 17:06:25  acg
25912027Sjungma@eit.uni-kl.de//  Andy Goodrich: updated copyright notice to include 2008.
26012027Sjungma@eit.uni-kl.de//
26112027Sjungma@eit.uni-kl.de// Revision 1.2  2008/03/24 18:32:36  acg
26212027Sjungma@eit.uni-kl.de//  Andy Goodrich: added include of sys/types.h to pick up the declaration
26312027Sjungma@eit.uni-kl.de//  of caddr_t.
26412027Sjungma@eit.uni-kl.de//
26512027Sjungma@eit.uni-kl.de// Revision 1.1.1.1  2006/12/15 20:20:05  acg
26612027Sjungma@eit.uni-kl.de// SystemC 2.3
26712027Sjungma@eit.uni-kl.de//
26812027Sjungma@eit.uni-kl.de// Revision 1.3  2006/01/13 18:44:29  acg
26912027Sjungma@eit.uni-kl.de// Added $Log to record CVS changes into the source.
27012027Sjungma@eit.uni-kl.de
27112027Sjungma@eit.uni-kl.de// Taf!
272