1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_cor_fiber.cpp -- Coroutine implementation with fibers. 23 24 Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 25 26 CHANGE LOG APPEARS AT THE END OF THE FILE 27 *****************************************************************************/ 28 29#if defined(_WIN32) || defined(WIN32) || defined(WIN64) 30 31#ifndef SC_INCLUDE_WINDOWS_H 32# define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed 33#endif 34 35#include "sysc/kernel/sc_cor_fiber.h" 36#include "sysc/kernel/sc_simcontext.h" 37#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ 38# if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 2)) 39# include <unwind.h> 40# else 41 extern "C" void _Unwind_SjLj_Register (struct SjLj_Function_Context *); 42 extern "C" void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); 43# endif 44#endif 45 46namespace sc_core { 47 48// ---------------------------------------------------------------------------- 49// File static variables. 50// ---------------------------------------------------------------------------- 51 52// main coroutine 53 54static sc_cor_fiber main_cor; 55#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ 56// current coroutine 57static sc_cor_fiber* curr_cor; 58#endif 59 60 61// ---------------------------------------------------------------------------- 62// CLASS : sc_cor_fiber 63// 64// Coroutine class implemented with Windows fibers. 65// ---------------------------------------------------------------------------- 66 67// destructor 68 69sc_cor_fiber::~sc_cor_fiber() 70{ 71 if( m_fiber != 0 ) { 72 PVOID cur_fiber = GetCurrentFiber(); 73 if (m_fiber != cur_fiber) 74 DeleteFiber( m_fiber ); 75 } 76} 77 78 79// ---------------------------------------------------------------------------- 80// CLASS : sc_cor_pkg_fiber 81// 82// Coroutine package class implemented with QuickThreads. 83// ---------------------------------------------------------------------------- 84 85int sc_cor_pkg_fiber::instance_count = 0; 86 87 88// constructor 89 90sc_cor_pkg_fiber::sc_cor_pkg_fiber( sc_simcontext* simc ) 91: sc_cor_pkg( simc ) 92{ 93 if( ++ instance_count == 1 ) { 94 // initialize the main coroutine 95 assert( main_cor.m_fiber == 0 ); 96 main_cor.m_fiber = ConvertThreadToFiber( 0 ); 97 98 if( !main_cor.m_fiber && GetLastError() == ERROR_ALREADY_FIBER ) { 99 // conversion of current thread to fiber has failed, because 100 // someone else already converted the main thread to a fiber 101 // -> store current fiber 102 main_cor.m_fiber = GetCurrentFiber(); 103 } 104 assert( main_cor.m_fiber != 0 ); 105 106# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ 107 // initialize the current coroutine 108 assert( curr_cor == 0 ); 109 curr_cor = &main_cor; 110# endif 111 } 112} 113 114 115// destructor 116 117sc_cor_pkg_fiber::~sc_cor_pkg_fiber() 118{ 119 if( -- instance_count == 0 ) { 120 // cleanup the main coroutine 121 main_cor.m_fiber = 0; 122# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ 123 // cleanup the current coroutine 124 curr_cor = 0; 125# endif 126 } 127} 128 129 130// create a new coroutine 131 132sc_cor* 133sc_cor_pkg_fiber::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) 134{ 135 sc_cor_fiber* cor = new sc_cor_fiber; 136 cor->m_pkg = this; 137 cor->m_stack_size = stack_size; 138 cor->m_fiber = CreateFiberEx( cor->m_stack_size / 2, cor->m_stack_size, 0, 139 (LPFIBER_START_ROUTINE) fn, arg ); 140 return cor; 141} 142 143 144// yield to the next coroutine 145 146void 147sc_cor_pkg_fiber::yield( sc_cor* next_cor ) 148{ 149 sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); 150# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ 151 // Switch SJLJ exception handling function contexts 152 _Unwind_SjLj_Register(&curr_cor->m_eh); 153 _Unwind_SjLj_Unregister(&new_cor->m_eh); 154 curr_cor = new_cor; 155# endif 156 SwitchToFiber( new_cor->m_fiber ); 157} 158 159 160// abort the current coroutine (and resume the next coroutine) 161 162void 163sc_cor_pkg_fiber::abort( sc_cor* next_cor ) 164{ 165 sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); 166# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ 167 // Switch SJLJ exception handling function contexts 168 _Unwind_SjLj_Register(&curr_cor->m_eh); 169 _Unwind_SjLj_Unregister(&new_cor->m_eh); 170 curr_cor = new_cor; 171# endif 172 SwitchToFiber( new_cor->m_fiber ); 173} 174 175 176// get the main coroutine 177 178sc_cor* 179sc_cor_pkg_fiber::get_main() 180{ 181 return &main_cor; 182} 183 184} // namespace sc_core 185 186 187// $Log: sc_cor_fiber.cpp,v $ 188// Revision 1.9 2011/09/08 16:12:45 acg 189// Philipp A. Hartmann: make sure we don't try to make a thread a fiber if 190// its already a fiber. 191// 192// Revision 1.8 2011/08/26 20:46:09 acg 193// Andy Goodrich: moved the modification log to the end of the file to 194// eliminate source line number skew when check-ins are done. 195// 196// Revision 1.7 2011/06/25 17:08:39 acg 197// Andy Goodrich: Jerome Cornet's changes to use libtool to build the 198// library. 199// 200// Revision 1.6 2011/02/18 20:27:14 acg 201// Andy Goodrich: Updated Copyrights. 202// 203// Revision 1.5 2011/02/13 21:47:37 acg 204// Andy Goodrich: update copyright notice. 205// 206// Revision 1.4 2011/01/19 23:21:50 acg 207// Andy Goodrich: changes for IEEE 1666 2011 208// 209// Revision 1.3 2009/05/22 16:06:29 acg 210// Andy Goodrich: process control updates. 211// 212// Revision 1.2 2008/05/22 17:06:25 acg 213// Andy Goodrich: updated copyright notice to include 2008. 214// 215// Revision 1.1.1.1 2006/12/15 20:20:05 acg 216// SystemC 2.3 217// 218// Revision 1.3 2006/01/13 18:44:29 acg 219// Added $Log to record CVS changes into the source. 220// 221 222#endif 223 224// Taf! 225