Example #1
0
  TransactionalScope::TransactionalScope(spinlock_t &fallback_mutex, bool writeAccess) : 
    // initializaer list
    spinlock(fallback_mutex) 
  {
  unsigned int xact_status;
  threadstate_t &ts = tstate;
  
  ts.txCount++;

  // we are already executing transactionally, continue.
  if (_xtest()) return;

  do {
    xact_status = _xbegin();

    if (xact_status == _XBEGIN_STARTED) {
      
      if ( *(reinterpret_cast<int*>(&fallback_mutex)) == 0 ) { 
	return;
      } else { 
	_xabort(0xFF); 
      }
    
    } else { 
      /** We have aborted. */
      ++ts.totalAborts;
      ++ts.successiveAborts;

      // if we xaborted because the lock was held, acquire the lock
      if ((xact_status & _XABORT_EXPLICIT) && _XABORT_CODE(xact_status) == 0xFF) {
	ts.maxAborts = 1;
	ts.maxTxLen = 1;
	break;
      }

      //if xabort:retry or xabort:conflict is set retry
      if (xact_status & (_XABORT_RETRY | _XABORT_CONFLICT)) {
	ts.maxTxLen = 1;
      }

      // // if we used too much buffer space inside the transaction half the max transaction length
      if ((xact_status & _XABORT_CAPACITY)) {
	ts.maxTxLen = 1;
      }
      _mm_pause();
    }
  } while (ts.successiveAborts < ts.maxAborts);

  ts.fallbackTaken++;

  // Fallback to lock
  if (writeAccess) { 
    spinlock.lock(); 
  } else { 
    spinlock.lock_read();
  }
}
Example #2
0
int main()
{
  unsigned status;
  if ((status = _xbegin()) == _XBEGIN_STARTED) {
    _xend();
  } else {
    _xabort(_XABORT_CONFLICT);
  }
}
Example #3
0
int
__lll_trylock_elision (int *futex, short *adapt_count)
{
    /* Implement POSIX semantics by forbiding nesting
       trylock.  Sorry.  After the abort the code is re-executed
       non transactional and if the lock was already locked
       return an error.  */
    _xabort (_ABORT_NESTED_TRYLOCK);

    /* Only try a transaction if it's worth it.  */
    if (*adapt_count <= 0)
    {
        unsigned status;

        if ((status = _xbegin()) == _XBEGIN_STARTED)
        {
            if (*futex == 0)
                return 0;

            /* Lock was busy.  Fall back to normal locking.
               Could also _xend here but xabort with 0xff code
               is more visible in the profiler.  */
            _xabort (_ABORT_LOCK_BUSY);
        }

        if (!(status & _XABORT_RETRY))
        {
            /* Internal abort.  No chance for retry.  For future
               locks don't try speculation for some time.  */
            if (*adapt_count != aconf.skip_trylock_internal_abort)
                *adapt_count = aconf.skip_trylock_internal_abort;
        }
        /* Could do some retries here.  */
    }
    else
    {
        /* Lost updates are possible, but harmless.  */
        (*adapt_count)--;
    }

    return lll_trylock (*futex);
}
Example #4
0
JNIEXPORT void JNICALL Java_javartm_Transaction_abort__(JNIEnv *env, jclass cls) {
	if (_xtest()) {
		_xabort(0);
	} else {
		// Tried to abort without active transaction
		// Throw an exception so that user code after the abort doesn't continue running
		jclass excClass = (*env)->FindClass(env, "java/lang/IllegalStateException");
		if (!excClass) return;
		(*env)->ThrowNew(env, excClass, "No active transaction to be aborted");
	}
}
Example #5
0
int main(void)
{
	int status;
	if ((status = _xbegin()) == _XBEGIN_STARTED) {
		if (_xtest())
			_xabort(1);
		_xend();
	} else
		printf("aborted %x, %d", status, _XABORT_CODE(status));
	return 0;
}
Example #6
0
/*
 * [lyj] Disable the interpretation of "deleted" field.
 */
void fraser_insert(sl_intset_t *set, uint32_t v, bool lin)
{
    sl_node_t *NEW, *new_next, *pred, *succ, *succs[LEVELMAX], *preds[LEVELMAX];
    uint32_t i;
    uint32_t status;
   // uint32_t attempts = 0;
    NEW = sl_new_simple_node(v, get_rand_level(), lin);
retry:
    fraser_search(set, v, preds, succs);
    for (i = 0; i < NEW->toplevel; i++)
        NEW->nexts[i] = succs[i];
    /* Node is visible once inserted at lowest level */
    if (!ATOMIC_CAS_MB(&preds[0]->nexts[0], succs[0], NEW))
        goto retry;
    
//retry_HTM:
    status = _xbegin();
    if(status == _XBEGIN_STARTED)
    {
        for (i = 1; i < NEW->toplevel; i++) {
            if(preds[i]->nexts[i] == succs[i])
                preds[i]->nexts[i] = NEW;
            else
                _xabort(66);
        }
        _xend();
        return;
    }/*else
    {
        if ((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 66) {
        }
        else if (++attempts < MAX_ATTEMPT_NUM) {
            goto retry_HTM;
        }
    }*/
    
    for (i = 1; i < NEW->toplevel; i++) {
        while (1) {
            pred = preds[i];
            succ = succs[i];
            /* Update the forward pointer if it is stale */
            new_next = NEW->nexts[i];
            if ((new_next != succ) &&
                (!ATOMIC_CAS_MB(&NEW->nexts[i], unset_mark((uint32_t)new_next), succ)))
                break;
            /* Give up if pointer is marked */
            /* We retry the search if the CAS fails */
            if (ATOMIC_CAS_MB(&pred->nexts[i], succ, NEW))
                break;
            fraser_search(set, v, preds, succs);
        }
    }
}
Example #7
0
int BST::addRTM(Node *node) {
    int state = TRANSACTION;
    int attempt = 1;
    int nabort = 0;
    int res;

    while (1) {
        UINT status = _XBEGIN_STARTED;
        if (state == TRANSACTION) {
            status = _xbegin();
        }
        else {
            tatas_lock.acquireOptimistic();
        }

        if (status == _XBEGIN_STARTED) {
            if (state == TRANSACTION && tatas_lock.getValue()) {
                _xabort(0xA0);
                nabort++;
            }

            res = add(node);

            if (state == TRANSACTION) {
                _xend();
            }
            else {
                tatas_lock.release();
            }
            break;
        }
        else {
            if (tatas_lock.getValue()) {
                do {
                    _mm_pause();
                } while (tatas_lock.getValue());
            }
            else {
                volatile UINT64 wait = attempt;
                while (wait--);
            }
            if (++attempt >= MAXATTEMPT) {
                state = LOCK;
            }
        }
    }
    return res;
}
Example #8
0
void spin_lock_rtm(int *lock)
{
	int i;
	unsigned status;
	unsigned retry = RETRY_OTHER;

	for (i = 0; i < retry; i++) {
		if ((status = _xbegin()) == _XBEGIN_STARTED) {
			if (lock_is_free(lock))
				return;
			_xabort(0xff);
		}
		trace_abort(status);
		if ((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 0xff) {
			while (!lock_is_free(lock))
				pause();
		} else if (!(status & _XABORT_RETRY) && !(status & _XABORT_CAPACITY))
			break;

		if (status & _XABORT_CONFLICT) {
			retry = RETRY_CON;
			while (!lock_is_free(lock))
				pause();
			/* Could do various kinds of backoff here. */
		} else if (status & _XABORT_CAPACITY) {
			retry = RETRY_CAP;
		} else {
			retry = RETRY_OTHER;
		}
	}
	/* Could do adaptation here */

	while (__sync_sub_and_fetch(lock, 1) < 0) {
		do
			pause();
		while (!lock_is_free(lock));
		/* Could do respeculation here */
	}
}
Example #9
0
JNIEXPORT void JNICALL Java_javartm_Transaction_abort__J(JNIEnv *env, jclass cls, jlong reason) {
	// I don't know why (register clobbering? bug?), but if reason is 32bits, then the returned
	// result after _xabort is always 0. Having reason as a long seems to work, don't know why.
	if (_xtest()) {
		// Supposedly the argument to _xabort must be encoded into the instruction.
		// To allow the user to specify his reason we must have an xabort for each value.
		// Welcome to low-level programming :)
		switch (reason) {
			case   0: _xabort(0);
			case   1: _xabort(1);
			case   2: _xabort(2);
			case   3: _xabort(3);
			case   4: _xabort(4);
			case   5: _xabort(5);
			case   6: _xabort(6);
			case   7: _xabort(7);
			case   8: _xabort(8);
			case   9: _xabort(9);
			case  10: _xabort(10);
			case  11: _xabort(11);
			case  12: _xabort(12);
			case  13: _xabort(13);
			case  14: _xabort(14);
			case  15: _xabort(15);
			case  16: _xabort(16);
			case  17: _xabort(17);
			case  18: _xabort(18);
			case  19: _xabort(19);
			case  20: _xabort(20);
			case  21: _xabort(21);
			case  22: _xabort(22);
			case  23: _xabort(23);
			case  24: _xabort(24);
			case  25: _xabort(25);
			case  26: _xabort(26);
			case  27: _xabort(27);
			case  28: _xabort(28);
			case  29: _xabort(29);
			case  30: _xabort(30);
			case  31: _xabort(31);
			case  32: _xabort(32);
			case  33: _xabort(33);
			case  34: _xabort(34);
			case  35: _xabort(35);
			case  36: _xabort(36);
			case  37: _xabort(37);
			case  38: _xabort(38);
			case  39: _xabort(39);
			case  40: _xabort(40);
			case  41: _xabort(41);
			case  42: _xabort(42);
			case  43: _xabort(43);
			case  44: _xabort(44);
			case  45: _xabort(45);
			case  46: _xabort(46);
			case  47: _xabort(47);
			case  48: _xabort(48);
			case  49: _xabort(49);
			case  50: _xabort(50);
			case  51: _xabort(51);
			case  52: _xabort(52);
			case  53: _xabort(53);
			case  54: _xabort(54);
			case  55: _xabort(55);
			case  56: _xabort(56);
			case  57: _xabort(57);
			case  58: _xabort(58);
			case  59: _xabort(59);
			case  60: _xabort(60);
			case  61: _xabort(61);
			case  62: _xabort(62);
			case  63: _xabort(63);
			case  64: _xabort(64);
			case  65: _xabort(65);
			case  66: _xabort(66);
			case  67: _xabort(67);
			case  68: _xabort(68);
			case  69: _xabort(69);
			case  70: _xabort(70);
			case  71: _xabort(71);
			case  72: _xabort(72);
			case  73: _xabort(73);
			case  74: _xabort(74);
			case  75: _xabort(75);
			case  76: _xabort(76);
			case  77: _xabort(77);
			case  78: _xabort(78);
			case  79: _xabort(79);
			case  80: _xabort(80);
			case  81: _xabort(81);
			case  82: _xabort(82);
			case  83: _xabort(83);
			case  84: _xabort(84);
			case  85: _xabort(85);
			case  86: _xabort(86);
			case  87: _xabort(87);
			case  88: _xabort(88);
			case  89: _xabort(89);
			case  90: _xabort(90);
			case  91: _xabort(91);
			case  92: _xabort(92);
			case  93: _xabort(93);
			case  94: _xabort(94);
			case  95: _xabort(95);
			case  96: _xabort(96);
			case  97: _xabort(97);
			case  98: _xabort(98);
			case  99: _xabort(99);
			case 100: _xabort(100);
			case 101: _xabort(101);
			case 102: _xabort(102);
			case 103: _xabort(103);
			case 104: _xabort(104);
			case 105: _xabort(105);
			case 106: _xabort(106);
			case 107: _xabort(107);
			case 108: _xabort(108);
			case 109: _xabort(109);
			case 110: _xabort(110);
			case 111: _xabort(111);
			case 112: _xabort(112);
			case 113: _xabort(113);
			case 114: _xabort(114);
			case 115: _xabort(115);
			case 116: _xabort(116);
			case 117: _xabort(117);
			case 118: _xabort(118);
			case 119: _xabort(119);
			case 120: _xabort(120);
			case 121: _xabort(121);
			case 122: _xabort(122);
			case 123: _xabort(123);
			case 124: _xabort(124);
			case 125: _xabort(125);
			case 126: _xabort(126);
			case 127: _xabort(127);
			case 128: _xabort(128);
			case 129: _xabort(129);
			case 130: _xabort(130);
			case 131: _xabort(131);
			case 132: _xabort(132);
			case 133: _xabort(133);
			case 134: _xabort(134);
			case 135: _xabort(135);
			case 136: _xabort(136);
			case 137: _xabort(137);
			case 138: _xabort(138);
			case 139: _xabort(139);
			case 140: _xabort(140);
			case 141: _xabort(141);
			case 142: _xabort(142);
			case 143: _xabort(143);
			case 144: _xabort(144);
			case 145: _xabort(145);
			case 146: _xabort(146);
			case 147: _xabort(147);
			case 148: _xabort(148);
			case 149: _xabort(149);
			case 150: _xabort(150);
			case 151: _xabort(151);
			case 152: _xabort(152);
			case 153: _xabort(153);
			case 154: _xabort(154);
			case 155: _xabort(155);
			case 156: _xabort(156);
			case 157: _xabort(157);
			case 158: _xabort(158);
			case 159: _xabort(159);
			case 160: _xabort(160);
			case 161: _xabort(161);
			case 162: _xabort(162);
			case 163: _xabort(163);
			case 164: _xabort(164);
			case 165: _xabort(165);
			case 166: _xabort(166);
			case 167: _xabort(167);
			case 168: _xabort(168);
			case 169: _xabort(169);
			case 170: _xabort(170);
			case 171: _xabort(171);
			case 172: _xabort(172);
			case 173: _xabort(173);
			case 174: _xabort(174);
			case 175: _xabort(175);
			case 176: _xabort(176);
			case 177: _xabort(177);
			case 178: _xabort(178);
			case 179: _xabort(179);
			case 180: _xabort(180);
			case 181: _xabort(181);
			case 182: _xabort(182);
			case 183: _xabort(183);
			case 184: _xabort(184);
			case 185: _xabort(185);
			case 186: _xabort(186);
			case 187: _xabort(187);
			case 188: _xabort(188);
			case 189: _xabort(189);
			case 190: _xabort(190);
			case 191: _xabort(191);
			case 192: _xabort(192);
			case 193: _xabort(193);
			case 194: _xabort(194);
			case 195: _xabort(195);
			case 196: _xabort(196);
			case 197: _xabort(197);
			case 198: _xabort(198);
			case 199: _xabort(199);
			case 200: _xabort(200);
			case 201: _xabort(201);
			case 202: _xabort(202);
			case 203: _xabort(203);
			case 204: _xabort(204);
			case 205: _xabort(205);
			case 206: _xabort(206);
			case 207: _xabort(207);
			case 208: _xabort(208);
			case 209: _xabort(209);
			case 210: _xabort(210);
			case 211: _xabort(211);
			case 212: _xabort(212);
			case 213: _xabort(213);
			case 214: _xabort(214);
			case 215: _xabort(215);
			case 216: _xabort(216);
			case 217: _xabort(217);
			case 218: _xabort(218);
			case 219: _xabort(219);
			case 220: _xabort(220);
			case 221: _xabort(221);
			case 222: _xabort(222);
			case 223: _xabort(223);
			case 224: _xabort(224);
			case 225: _xabort(225);
			case 226: _xabort(226);
			case 227: _xabort(227);
			case 228: _xabort(228);
			case 229: _xabort(229);
			case 230: _xabort(230);
			case 231: _xabort(231);
			case 232: _xabort(232);
			case 233: _xabort(233);
			case 234: _xabort(234);
			case 235: _xabort(235);
			case 236: _xabort(236);
			case 237: _xabort(237);
			case 238: _xabort(238);
			case 239: _xabort(239);
			case 240: _xabort(240);
			case 241: _xabort(241);
			case 242: _xabort(242);
			case 243: _xabort(243);
			case 244: _xabort(244);
			case 245: _xabort(245);
			case 246: _xabort(246);
			case 247: _xabort(247);
			case 248: _xabort(248);
			case 249: _xabort(249);
			case 250: _xabort(250);
			case 251: _xabort(251);
			case 252: _xabort(252);
			case 253: _xabort(253);
			case 254: _xabort(254);
			case 255: _xabort(255);
			 default: _xabort(0);
		}
	} else {
		// Tried to abort without active transaction
		// Throw an exception so that user code after the abort doesn't continue running
		jclass excClass = (*env)->FindClass(env, "java/lang/IllegalStateException");
		if (!excClass) return;
		(*env)->ThrowNew(env, excClass, "No active transaction to be aborted");
	}
}
Example #10
0
void
test_xabort(void) {
  // CHECK: void @llvm.x86.xabort(i8 2)
  _xabort(2);
}
uint32_t mem_read(tid_t tid, uint32_t *addr) {
    version_t version;
    uint32_t val;
    objid_t objid = calc_objid(addr);
    struct objinfo *info = &g_objinfo[objid];

    if ((g_sim_bbcnt % RTM_BATCH_N) == 0) { // Simulate basic block begin.
        assert(!_xtest());
        int ret = _xbegin();
        (void)ret;
#ifdef RTM_STAT
        if (ret != _XBEGIN_STARTED) {
            fprintf(stderr, "T%d R%ld aborted %x, %d\n", g_tid, memop, ret,
                    _XABORT_CODE(ret));
            g_rtm_abort_cnt++;
        }
#endif
    }

    int in_rtm = _xtest();
    if (in_rtm) {
        version = info->version;
        // XXX It's possible the transaction commits while another write is in
        // fallback handler and has increased version by 1, thus we would get an
        // odd version here. Also refer to read tx in rtmseq.
        if (version & 1) {
            _xabort(1);
        }
        val = *addr;
    } else {
        do {
            version = info->version;
            while (unlikely(version & 1)) {
                cpu_relax();
                version = info->version;
            }
            barrier();
            val = *addr;
            barrier();
        } while (version != info->version);
    }

    if (in_rtm && (g_sim_bbcnt % RTM_BATCH_N == RTM_BATCH_N - 1)) { // Simulate basic block end.
        // XXX Update: since we have checked odd version in tx region, we
        // will abort for parallel execution of read tx and write fallback.
        // So no need to check for lock here.
        // XXX A transaction is accessing different shared objects. Here we only
        // check for a single object's write lock, it's not enough. That's why
        // we need the odd version check in the transaction region.
        /*
         *if (info->write_lock) {
         *    _xabort(2);
         *}
         */
        _xend();
        // Avoid taking log inside transaction.
        batch_read_log(objid, version);
        batch_process_log();
    } else {
        batch_read_log(objid, version);
    }

    g_sim_bbcnt++;
    return val;
}
void mem_write(tid_t tid, uint32_t *addr, uint32_t val) {
    version_t version;
    objid_t objid = calc_objid(addr);
    struct objinfo *info = &g_objinfo[objid];

    if ((g_sim_bbcnt % RTM_BATCH_N) == 0) {
        assert(!_xtest());
        int ret = _xbegin();
        (void)ret;
#ifdef RTM_STAT
        if (ret != _XBEGIN_STARTED) {
            fprintf(stderr, "T%d W%ld aborted %x, %d\n", g_tid, memop, ret,
                    _XABORT_CODE(ret));
            g_rtm_abort_cnt++;
        }
#endif
    }

    int in_rtm = _xtest();
    if (in_rtm) {
        version = info->version;
        // XXX To ensure exclusion of write tx and fallback. Same as in read
        // transaction.
        if (info->write_lock) {
            _xabort(3);
        }
        barrier();
        *addr = val;
        barrier();
        info->version += 2;
        // XXX The barrier is necessary, because there are reordering inside a
        // transaction.  The reason is the same as in seqlock implementation.
        __sync_synchronize();
    } else {
        spin_lock(&info->write_lock);

        version = info->version;
        barrier();

        // Odd version means that there's writer trying to update value.
        info->version++;
        barrier();
        *addr = val;
        // This barrier disallows read to happen before the write.
        // The explicit barrier here may also make the compiler unnecessary here.
        __sync_synchronize();
        info->version++;

        spin_unlock(&info->write_lock);
    }

    if (in_rtm && (g_sim_bbcnt % RTM_BATCH_N == RTM_BATCH_N - 1))  {
        // XXX Update: since we have checked lock in tx region, we
        // will abort for parallel execution of write tx and write fallback.
        // So no need to check for lock here.
        /*
         *if (info->write_lock) {
         *    _xabort(4);
         *}
         */
        _xend();
        // Avoid taking log inside transaction.
        batch_write_log(objid, version);
        batch_process_log();
    } else {
        batch_write_log(objid, version);
    }

    g_sim_bbcnt++;
}