00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef _MTM_I_H_819AKI
00028 #define _MTM_I_H_819AKI
00029
00030 #include <stddef.h>
00031 #include <stdbool.h>
00032 #include <stdint.h>
00033
00034 #define ITM_NORETURN __attribute__((noreturn))
00035
00036 #include <xmmintrin.h>
00037
00038 typedef uint8_t _ITM_TYPE_U1;
00039 typedef uint16_t _ITM_TYPE_U2;
00040 typedef uint32_t _ITM_TYPE_U4;
00041 typedef uint64_t _ITM_TYPE_U8;
00042 typedef float _ITM_TYPE_F;
00043 typedef double _ITM_TYPE_D;
00044 typedef long double _ITM_TYPE_E;
00045 typedef __m64 _ITM_TYPE_M64;
00046 typedef __m128 _ITM_TYPE_M128;
00047 typedef float _Complex _ITM_TYPE_CF;
00048 typedef double _Complex _ITM_TYPE_CD;
00049 typedef long double _Complex _ITM_TYPE_CE;
00050
00051 typedef struct mtm_tx_s mtm_tx_t;
00052 typedef mtm_tx_t _ITM_transaction;
00053
00054 #include "itm.h"
00055
00056 # ifndef __cplusplus
00057 # define FOR_ALL_TYPES(ACTION,name) \
00058 ACTION (name,uint8_t,U1) \
00059 ACTION (name,uint16_t,U2) \
00060 ACTION (name,uint32_t,U4) \
00061 ACTION (name,uint64_t,U8) \
00062 ACTION (name,float,F) \
00063 ACTION (name,double,D) \
00064 ACTION (name,long double,E) \
00065 ACTION (name,__m64,M64) \
00066 ACTION (name,__m128,M128) \
00067 ACTION (name,float _Complex,CF) \
00068 ACTION (name,double _Complex,CD) \
00069 ACTION (name,long double _Complex,CE)
00070 # else
00071 # define FOR_ALL_TYPES(ACTION,name) \
00072 ACTION (name,uint8_t,U1) \
00073 ACTION (name,uint16_t,U2) \
00074 ACTION (name,uint32_t,U4) \
00075 ACTION (name,uint64_t,U8) \
00076 ACTION (name,float,F) \
00077 ACTION (name,double,D) \
00078 ACTION (name,long double,E) \
00079 ACTION (name,__m64,M64) \
00080 ACTION (name,__m128,M128)
00081 # endif
00082
00083 #include <result.h>
00084
00085
00086
00087 #define TMLOG_TYPE_BASE 0
00088 #define TMLOG_TYPE_TORNBIT 1
00089
00090 #if TMLOG_TYPE == TMLOG_TYPE_BASE
00091 # define M_TMLOG_WRITE m_tmlog_base_write
00092 # define M_TMLOG_TRUNCATE_SYNC m_tmlog_base_truncate_sync
00093 # define M_TMLOG_BEGIN m_tmlog_base_begin
00094 # define M_TMLOG_COMMIT m_tmlog_base_commit
00095 # define M_TMLOG_ABORT m_tmlog_base_abort
00096 # define M_TMLOG_T m_tmlog_base_t
00097 # define M_TMLOG_LF_TYPE LF_TYPE_TM_BASE
00098 # define M_TMLOG_OPS tmlog_base_ops
00099 #elif TMLOG_TYPE == TMLOG_TYPE_TORNBIT
00100 # define M_TMLOG_WRITE m_tmlog_tornbit_write
00101 # define M_TMLOG_TRUNCATE_SYNC m_tmlog_tornbit_truncate_sync
00102 # define M_TMLOG_BEGIN m_tmlog_tornbit_begin
00103 # define M_TMLOG_COMMIT m_tmlog_tornbit_commit
00104 # define M_TMLOG_ABORT m_tmlog_tornbit_abort
00105 # define M_TMLOG_T m_tmlog_tornbit_t
00106 # define M_TMLOG_LF_TYPE LF_TYPE_TM_TORNBIT
00107 # define M_TMLOG_OPS tmlog_tornbit_ops
00108 #else
00109 # error "Unknown persistent log type."
00110 #endif
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 #define EXPLICIT_TX_PARAMETER
00121
00122 # ifdef EXPLICIT_TX_PARAMETER
00123 # define TXTYPE mtm_tx_t *
00124 # define TXPARAM mtm_tx_t *tx
00125 # define TXPARAMS mtm_tx_t *tx,
00126 # define TXARG (mtm_tx_t *)tx
00127 # define TXARGS (mtm_tx_t *)tx,
00128 struct mtm_tx *mtm_current_tx();
00129 # else
00130 # define TXTYPE void
00131 # define TXPARAM
00132 # define TXPARAMS
00133 # define TXARG
00134 # define TXARGS
00135 #endif
00136
00137 #ifdef EXPLICIT_TX_PARAMETER
00138 # define TX_RETURN return tx
00139 # define TX_GET
00140 #else
00141 # define TX_RETURN return
00142 # define TX_GET mtm_tx_t *tx = mtm_get_tx()
00143 #endif
00144
00145 #define WRITE_BACK_ETL 0
00146 #define WRITE_THROUGH 1
00147
00148 #define CM_SUICIDE 0
00149 #define CM_DELAY 1
00150 #define CM_BACKOFF 2
00151 #define CM_PRIORITY 3
00152
00153 #include <assert.h>
00154 #include <stdio.h>
00155 #include <stdlib.h>
00156 #include <string.h>
00157
00158 #include <pthread.h>
00159
00160 #include <atomic.h>
00161
00162 #include <pcm.h>
00163
00164 #include "mode/dtable.h"
00165
00166 #if defined(CONFLICT_TRACKING) && ! defined(EPOCH_GC)
00167 # error "CONFLICT_TRACKING requires EPOCH_GC"
00168 #endif
00169
00170 #if defined(READ_LOCKED_DATA) && ! defined(EPOCH_GC)
00171 # error "READ_LOCKED_DATA requires EPOCH_GC"
00172 #endif
00173
00174 #define TLS
00175
00176 # define MTM_DEBUG_PRINT(...)
00177
00178
00179 #ifdef DEBUG
00180
00181 # define IO_FLUSH fflush(NULL)
00182 # define PRINT_DEBUG(...) printf(__VA_ARGS__); fflush(NULL)
00183 #else
00184 # define IO_FLUSH
00185 # define PRINT_DEBUG(...)
00186 #endif
00187
00188 #ifdef DEBUG2
00189 # define PRINT_DEBUG2(...) PRINT_DEBUG(__VA_ARGS__)
00190 #else
00191 # define PRINT_DEBUG2(...)
00192 #endif
00193
00194 #ifndef LOCK_SHIFT_EXTRA
00195 # define LOCK_SHIFT_EXTRA 2
00196 #endif
00197
00198 #if CM == CM_PRIORITY
00199 # define VR_THRESHOLD "VR_THRESHOLD"
00200 # define CM_THRESHOLD "CM_THRESHOLD"
00201 #endif
00202
00203 extern int vr_threshold;
00204 extern int cm_threshold;
00205
00206
00207
00208 #define STR2(str1, str2) str1##str2
00209 #define XSTR(s) STR(s)
00210 #define STR(s) #s
00211
00212 #define COMPILE_TIME_ASSERT(pred) switch (0) { case 0: case pred: ; }
00213
00214 #define UNUSED __attribute__((unused))
00215
00216 #ifdef HAVE_ATTRIBUTE_VISIBILITY
00217 # pragma GCC visibility push(hidden)
00218 #endif
00219
00220 #include "mode/mode.h"
00221 #include "sysdeps/x86/target.h"
00222 #include "rwlock.h"
00223 #include "useraction.h"
00224 #include "locks.h"
00225 #include "local.h"
00226 #include "stats.h"
00227
00232 typedef uintptr_t mtm_word_t;
00233
00234 enum {
00235 TX_IDLE = 0,
00236 TX_ACTIVE = 1,
00237 TX_COMMITTED = 2,
00238 TX_ABORTED = 3,
00239 TX_IRREVOCABLE = 4,
00240 TX_SERIAL = 8,
00241 };
00242
00243
00244
00245
00246
00247
00248
00249 typedef enum mtm_restart_reason
00250 {
00251 RESTART_REALLOCATE,
00252 RESTART_LOCKED_READ,
00253 RESTART_LOCKED_WRITE,
00254 RESTART_VALIDATE_READ,
00255 RESTART_VALIDATE_WRITE,
00256 RESTART_VALIDATE_COMMIT,
00257 RESTART_NOT_READONLY,
00258 RESTART_USER_RETRY,
00259 NUM_RESTARTS
00260 } mtm_restart_reason;
00261
00262
00263
00264 struct mtm_local_undo;
00265
00266
00267 struct mtm_tx_s {
00268 uintptr_t dummy1;
00269 uintptr_t dummy2;
00270 mtm_dtable_t *dtable;
00271
00272 mtm_jmpbuf_t *tmp_jb_ptr;
00273 mtm_jmpbuf_t tmp_jb;
00274 mtm_jmpbuf_t jb;
00275
00276 mtm_mode_data_t *modedata[MTM_NUM_MODES];
00277 mtm_mode_t mode;
00278 mtm_word_t status;
00279
00280 uint32_t prop;
00281 int nesting;
00282 int can_extend;
00283 _ITM_transactionId id;
00284 int thread_num;
00285 #ifdef CONFLICT_TRACKING
00286 pthread_t thread_id;
00287 #endif
00288 #if CM == CM_DELAY || CM == CM_PRIORITY
00289 volatile mtm_word_t *c_lock;
00290 #endif
00291 #if CM == CM_BACKOFF
00292 unsigned long backoff;
00293 unsigned long seed;
00294 #endif
00295 #if CM == CM_PRIORITY
00296 int priority;
00297 int visible_reads;
00298 #endif
00299 unsigned long retries;
00300
00301 uintptr_t stack_base;
00302 uintptr_t stack_size;
00303 mtm_local_undo_t local_undo;
00304 mtm_word_t *wb_table;
00305 pcm_storeset_t *pcm_storeset;
00306 m_stats_threadstat_t *threadstat;
00307 m_stats_statset_t *statset;
00308 mtm_user_action_list_t *commit_action_list;
00309 mtm_user_action_list_t *undo_action_list;
00310 };
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00372 extern volatile mtm_word_t locks[];
00373
00374 #ifdef CLOCK_IN_CACHE_LINE
00375 extern volatile mtm_word_t gclock[];
00376 # define CLOCK (gclock[512 / sizeof(mtm_word_t)])
00377 #else
00378 extern volatile mtm_word_t gclock;
00379 # define CLOCK (gclock)
00380 #endif
00381
00382 #ifdef _M_STATS_BUILD
00383 extern m_statsmgr_t *mtm_statsmgr;
00384 #endif
00385
00386
00387
00388
00389
00390 extern mtm_rwlock_t mtm_serial_lock;
00391
00392 extern uint32_t mtm_begin_transaction(uint32_t, const mtm_jmpbuf_t *);
00393 extern uint32_t mtm_longjmp (const mtm_jmpbuf_t *, uint32_t)
00394 ITM_NORETURN;
00395
00396 extern void mtm_commit_local (TXPARAM);
00397 extern void mtm_rollback_local (TXPARAM);
00398 extern void mtm_LB (mtm_tx_t *tx, const void *, size_t) _ITM_CALL_CONVENTION;
00399
00400 extern void mtm_serialmode (bool, bool);
00401 extern void mtm_restart_transaction (mtm_restart_reason) ITM_NORETURN;
00402
00403 extern void mtm_alloc_record_allocation (void *, size_t, void (*)(void *));
00404 extern void mtm_alloc_forget_allocation (void *, void (*)(void *));
00405 extern size_t mtm_alloc_get_allocation_size (void *);
00406 extern void mtm_alloc_commit_allocations (bool);
00407
00408 extern void mtm_revert_cpp_exceptions (void);
00409
00410
00411
00412
00413
00414
00415 extern void *mtm_null_read_lock (mtm_tx_t *td, uintptr_t);
00416 extern void *mtm_null_write_lock (mtm_tx_t *td, uintptr_t);
00417
00418
00419
00420
00421
00422
00423 #define GET_CLOCK (ATOMIC_LOAD_ACQ(&CLOCK))
00424 #define FETCH_INC_CLOCK (ATOMIC_FETCH_INC_FULL(&CLOCK))
00425
00426
00427
00428
00429
00430
00431
00432 #ifdef TLS
00433 extern __thread mtm_tx_t *_mtm_thread_tx;
00434 #else
00435 extern pthread_key_t _mtm_thread_tx;
00436 #endif
00437
00438
00439
00440
00441 static inline mtm_tx_t *mtm_get_tx()
00442 {
00443 #ifdef TLS
00444 return _mtm_thread_tx;
00445 #else
00446 return (mtm_tx_t *)pthread_getspecific(_mtm_thread_tx);
00447 #endif
00448 }
00449
00450 #ifdef LOCK_IDX_SWAP
00451
00452
00453
00454 static inline unsigned int lock_idx_swap(unsigned int idx) {
00455 return (idx & ~(unsigned int)0xFFFF) | ((idx & 0x00FF) << 8) | ((idx & 0xFF00) >> 8);
00456 }
00457 #endif
00458
00459 #ifdef ROLLOVER_CLOCK
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 pthread_mutex_t tx_count_mutex;
00478 pthread_cond_t tx_reset;
00479 int tx_count;
00480 int tx_overflow;
00481
00482
00483
00484
00485 static inline void mtm_rollover_enter(mtm_tx_t *tx)
00486 {
00487 PRINT_DEBUG("==> mtm_rollover_enter(%p)\n", tx);
00488
00489 pthread_mutex_lock(&tx_count_mutex);
00490 while (tx_overflow != 0)
00491 pthread_cond_wait(&tx_reset, &tx_count_mutex);
00492
00493 tx_count++;
00494 pthread_mutex_unlock(&tx_count_mutex);
00495 }
00496
00497
00498
00499
00500 static inline void mtm_rollover_exit(mtm_tx_t *tx)
00501 {
00502 PRINT_DEBUG("==> mtm_rollover_exit(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
00503
00504 pthread_mutex_lock(&tx_count_mutex);
00505
00506 tx_count--;
00507 assert(tx_count >= 0);
00508
00509 if (tx_overflow != 0 && tx_count == 0) {
00510
00511 memset((void *)locks, 0, LOCK_ARRAY_SIZE * sizeof(mtm_word_t));
00512 CLOCK = 0;
00513 tx_overflow = 0;
00514 # ifdef EPOCH_GC
00515
00516 gc_reset();
00517 # endif
00518
00519 pthread_cond_broadcast(&tx_reset);
00520 }
00521 pthread_mutex_unlock(&tx_count_mutex);
00522 }
00523
00532 static inline void mtm_overflow(mtm_tx_t *tx)
00533 {
00534 PRINT_DEBUG("==> mtm_overflow(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end);
00535
00536 pthread_mutex_lock(&tx_count_mutex);
00537
00538 tx_overflow = 1;
00539
00540 tx_count--;
00541 assert(tx_count >= 0);
00542
00543 if (tx_count == 0) {
00544
00545 memset((void *)locks, 0, LOCK_ARRAY_SIZE * sizeof(mtm_word_t));
00546 CLOCK = 0;
00547 tx_overflow = 0;
00548 # ifdef EPOCH_GC
00549
00550 gc_reset();
00551 # endif
00552
00553 pthread_cond_broadcast(&tx_reset);
00554 } else {
00555
00556 pthread_cond_wait(&tx_reset, &tx_count_mutex);
00557 }
00558
00559 tx_count++;
00560 pthread_mutex_unlock(&tx_count_mutex);
00561 }
00562 #endif
00563
00564
00565
00566
00567 static inline mtm_word_t mtm_get_clock()
00568 {
00569 return GET_CLOCK;
00570 }
00571
00572 #ifdef HAVE_ATTRIBUTE_VISIBILITY
00573 # pragma GCC visibility pop
00574 #endif
00575
00576 #endif