OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libitm/] [method-serial.cc] - Blame information for rev 737

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 737 jeremybenn
/* Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
2
   Contributed by Richard Henderson <rth@redhat.com>.
3
 
4
   This file is part of the GNU Transactional Memory Library (libitm).
5
 
6
   Libitm is free software; you can redistribute it and/or modify it
7
   under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
 
11
   Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
12
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
   more details.
15
 
16
   Under Section 7 of GPL version 3, you are granted additional
17
   permissions described in the GCC Runtime Library Exception, version
18
   3.1, as published by the Free Software Foundation.
19
 
20
   You should have received a copy of the GNU General Public License and
21
   a copy of the GCC Runtime Library Exception along with this program;
22
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
   <http://www.gnu.org/licenses/>.  */
24
 
25
#include "libitm_i.h"
26
 
27
// Avoid a dependency on libstdc++ for the pure virtuals in abi_dispatch.
28
extern "C" void HIDDEN
29
__cxa_pure_virtual ()
30
{
31
  abort ();
32
}
33
 
34
using namespace GTM;
35
 
36
namespace {
37
 
38
// This group consists of the serial, serialirr, and serialirr_onwrite
39
// methods, which all need no global state (except what is already provided
40
// by the serial mode implementation).
41
struct serial_mg : public method_group
42
{
43
  virtual void init() { }
44
  virtual void fini() { }
45
};
46
 
47
static serial_mg o_serial_mg;
48
 
49
 
50
class serialirr_dispatch : public abi_dispatch
51
{
52
 public:
53
  serialirr_dispatch() : abi_dispatch(false, true, true, false, &o_serial_mg)
54
  { }
55
 
56
 protected:
57
  serialirr_dispatch(bool ro, bool wt, bool uninstrumented,
58
      bool closed_nesting, method_group* mg) :
59
    abi_dispatch(ro, wt, uninstrumented, closed_nesting, mg) { }
60
 
61
  // Transactional loads and stores simply access memory directly.
62
  // These methods are static to avoid indirect calls, and will be used by the
63
  // virtual ABI dispatch methods or by static direct-access methods created
64
  // below.
65
  template <typename V> static V load(const V* addr, ls_modifier mod)
66
  {
67
    return *addr;
68
  }
69
  template <typename V> static void store(V* addr, const V value,
70
      ls_modifier mod)
71
  {
72
    *addr = value;
73
  }
74
 
75
 public:
76
  static void memtransfer_static(void *dst, const void* src, size_t size,
77
      bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
78
  {
79
    if (!may_overlap)
80
      ::memcpy(dst, src, size);
81
    else
82
      ::memmove(dst, src, size);
83
  }
84
 
85
  static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
86
  {
87
    ::memset(dst, c, size);
88
  }
89
 
90
  CREATE_DISPATCH_METHODS(virtual, )
91
  CREATE_DISPATCH_METHODS_MEM()
92
 
93
  virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; }
94
  virtual bool trycommit(gtm_word& priv_time) { return true; }
95
  virtual void rollback(gtm_transaction_cp *cp) { abort(); }
96
 
97
  virtual abi_dispatch* closed_nesting_alternative()
98
  {
99
    // For nested transactions with an instrumented code path, we can do
100
    // undo logging.
101
    return GTM::dispatch_serial();
102
  }
103
};
104
 
105
class serial_dispatch : public abi_dispatch
106
{
107
protected:
108
  static void log(const void *addr, size_t len)
109
  {
110
    gtm_thread *tx = gtm_thr();
111
    tx->undolog.log(addr, len);
112
  }
113
 
114
  template <typename V> static V load(const V* addr, ls_modifier mod)
115
  {
116
    return *addr;
117
  }
118
  template <typename V> static void store(V* addr, const V value,
119
      ls_modifier mod)
120
  {
121
    if (mod != WaW)
122
      log(addr, sizeof(V));
123
    *addr = value;
124
  }
125
 
126
public:
127
  static void memtransfer_static(void *dst, const void* src, size_t size,
128
      bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
129
  {
130
    if (dst_mod != WaW && dst_mod != NONTXNAL)
131
      log(dst, size);
132
    if (!may_overlap)
133
      ::memcpy(dst, src, size);
134
    else
135
      ::memmove(dst, src, size);
136
  }
137
 
138
  static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
139
  {
140
    if (mod != WaW)
141
      log(dst, size);
142
    ::memset(dst, c, size);
143
  }
144
 
145
  virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; }
146
  virtual bool trycommit(gtm_word& priv_time) { return true; }
147
  // Local undo will handle this.
148
  // trydropreference() need not be changed either.
149
  virtual void rollback(gtm_transaction_cp *cp) { }
150
 
151
  CREATE_DISPATCH_METHODS(virtual, )
152
  CREATE_DISPATCH_METHODS_MEM()
153
 
154
  serial_dispatch() : abi_dispatch(false, true, false, true, &o_serial_mg) { }
155
};
156
 
157
 
158
// Like serialirr_dispatch but does not requests serial-irrevocable mode until
159
// the first write in the transaction. Can be useful for read-mostly workloads
160
// and testing, but is likely too simple to be of general purpose.
161
class serialirr_onwrite_dispatch : public serialirr_dispatch
162
{
163
 public:
164
  serialirr_onwrite_dispatch() :
165
    serialirr_dispatch(false, true, false, false, &o_serial_mg) { }
166
 
167
 protected:
168
  static void pre_write()
169
  {
170
    gtm_thread *tx = gtm_thr();
171
    if (!(tx->state & (gtm_thread::STATE_SERIAL
172
        | gtm_thread::STATE_IRREVOCABLE)))
173
      tx->serialirr_mode();
174
  }
175
 
176
  // Transactional loads access memory directly.
177
  // Transactional stores switch to serial mode first.
178
  template <typename V> static void store(V* addr, const V value,
179
      ls_modifier mod)
180
  {
181
    pre_write();
182
    serialirr_dispatch::store(addr, value, mod);
183
  }
184
 
185
 public:
186
  static void memtransfer_static(void *dst, const void* src, size_t size,
187
      bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
188
  {
189
    pre_write();
190
    serialirr_dispatch::memtransfer_static(dst, src, size, may_overlap,
191
        dst_mod, src_mod);
192
  }
193
 
194
  static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
195
  {
196
    pre_write();
197
    serialirr_dispatch::memset_static(dst, c, size, mod);
198
  }
199
 
200
  CREATE_DISPATCH_METHODS(virtual, )
201
  CREATE_DISPATCH_METHODS_MEM()
202
 
203
  virtual void rollback(gtm_transaction_cp *cp)
204
  {
205
    gtm_thread *tx = gtm_thr();
206
    if (tx->state & gtm_thread::STATE_IRREVOCABLE)
207
      abort();
208
  }
209
};
210
 
211
} // anon namespace
212
 
213
static const serialirr_dispatch o_serialirr_dispatch;
214
static const serial_dispatch o_serial_dispatch;
215
static const serialirr_onwrite_dispatch o_serialirr_onwrite_dispatch;
216
 
217
abi_dispatch *
218
GTM::dispatch_serialirr ()
219
{
220
  return const_cast<serialirr_dispatch *>(&o_serialirr_dispatch);
221
}
222
 
223
abi_dispatch *
224
GTM::dispatch_serial ()
225
{
226
  return const_cast<serial_dispatch *>(&o_serial_dispatch);
227
}
228
 
229
abi_dispatch *
230
GTM::dispatch_serialirr_onwrite ()
231
{
232
  return
233
      const_cast<serialirr_onwrite_dispatch *>(&o_serialirr_onwrite_dispatch);
234
}
235
 
236
// Put the transaction into serial-irrevocable mode.
237
 
238
void
239
GTM::gtm_thread::serialirr_mode ()
240
{
241
  struct abi_dispatch *disp = abi_disp ();
242
 
243
  if (this->state & STATE_SERIAL)
244
    {
245
      if (this->state & STATE_IRREVOCABLE)
246
        return;
247
 
248
      // Try to commit the dispatch-specific part of the transaction, as we
249
      // would do for an outermost commit.
250
      // We're already serial, so we don't need to ensure privatization safety
251
      // for other transactions here.
252
      gtm_word priv_time = 0;
253
      bool ok = disp->trycommit (priv_time);
254
      // Given that we're already serial, the trycommit better work.
255
      assert (ok);
256
    }
257
  else if (serial_lock.write_upgrade (this))
258
    {
259
      this->state |= STATE_SERIAL;
260
      // Try to commit the dispatch-specific part of the transaction, as we
261
      // would do for an outermost commit.
262
      // We have successfully upgraded to serial mode, so we don't need to
263
      // ensure privatization safety for other transactions here.
264
      // However, we are still a reader (wrt. privatization safety) until we
265
      // have either committed or restarted, so finish the upgrade after that.
266
      gtm_word priv_time = 0;
267
      if (!disp->trycommit (priv_time))
268
        restart (RESTART_SERIAL_IRR, true);
269
      gtm_thread::serial_lock.write_upgrade_finish(this);
270
    }
271
  else
272
    restart (RESTART_SERIAL_IRR, false);
273
 
274
  this->state |= (STATE_SERIAL | STATE_IRREVOCABLE);
275
  set_abi_disp (dispatch_serialirr ());
276
}
277
 
278
void ITM_REGPARM
279
_ITM_changeTransactionMode (_ITM_transactionState state)
280
{
281
  assert (state == modeSerialIrrevocable);
282
  gtm_thr()->serialirr_mode ();
283
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.