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