PR 50016 Slow I/O on MingW due to _commit
[official-gcc.git] / libitm / stmlock.h
blobf115a417da20e94188536eb56dec7c3fee62030c
1 /* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Transactional Memory Library (libitm).
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.
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.
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.
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/>. */
25 #ifndef LIBITM_STMLOCK_H
26 #define LIBITM_STMLOCK_H 1
28 namespace GTM HIDDEN {
30 /* A versioned write lock on a cacheline. This must be wide enough to
31 store a pointer, and preferably wide enough to avoid overflowing the
32 version counter. Thus we use a "word", which should be 64-bits on
33 64-bit systems even when their pointer size is forced smaller. */
34 typedef gtm_word gtm_stmlock;
36 /* This has to be the same size as gtm_stmlock, we just use this name
37 for documentation purposes. */
38 typedef gtm_word gtm_version;
40 /* The maximum value a version number can have. This is a consequence
41 of having the low bit of gtm_stmlock reserved for the owned bit. */
42 #define GTM_VERSION_MAX (~(gtm_version)0 >> 1)
44 /* A value that may be used to indicate "uninitialized" for a version. */
45 #define GTM_VERSION_INVALID (~(gtm_version)0)
47 /* This bit is set when the write lock is held. When set, the balance of
48 the bits in the lock is a pointer that references STM backend specific
49 data; it is up to the STM backend to determine if this thread holds the
50 lock. If this bit is clear, the balance of the bits are the last
51 version number committed to the cacheline. */
52 static inline bool
53 gtm_stmlock_owned_p (gtm_stmlock lock)
55 return lock & 1;
58 static inline gtm_stmlock
59 gtm_stmlock_set_owned (void *data)
61 return (gtm_stmlock)(uintptr_t)data | 1;
64 static inline void *
65 gtm_stmlock_get_addr (gtm_stmlock lock)
67 return (void *)((uintptr_t)lock & ~(uintptr_t)1);
70 static inline gtm_version
71 gtm_stmlock_get_version (gtm_stmlock lock)
73 return lock >> 1;
76 static inline gtm_stmlock
77 gtm_stmlock_set_version (gtm_version ver)
79 return ver << 1;
82 /* We use a fixed set of locks for all memory, hashed into the
83 following table. */
84 #define LOCK_ARRAY_SIZE (1024 * 1024)
85 extern gtm_stmlock gtm_stmlock_array[LOCK_ARRAY_SIZE];
87 static inline gtm_stmlock *
88 gtm_get_stmlock (const gtm_cacheline *addr)
90 size_t idx = ((uintptr_t) addr / CACHELINE_SIZE) % LOCK_ARRAY_SIZE;
91 return gtm_stmlock_array + idx;
94 /* The current global version number. */
95 extern gtm_version gtm_clock;
97 static inline gtm_version
98 gtm_get_clock (void)
100 gtm_version r;
102 __sync_synchronize ();
103 r = gtm_clock;
104 atomic_read_barrier ();
106 return r;
109 static inline gtm_version
110 gtm_inc_clock (void)
112 gtm_version r = __sync_add_and_fetch (&gtm_clock, 1);
114 /* ??? Ought to handle wraparound for 32-bit. */
115 if (sizeof(r) < 8 && r > GTM_VERSION_MAX)
116 abort ();
118 return r;
121 } // namespace GTM
123 #endif // LIBITM_STMLOCK_H