Example #1
0
 inline uint64_t
 elapsed_usec() const
 {
   compiler_barrier();
   const uint64_t t0 = start_;
   const uint64_t t1 = cur_usec(m_);
   compiler_barrier();
   return t1 - t0;
 }
Example #2
0
 inline uint64_t
 lap()
 {
   compiler_barrier();
   const uint64_t t0 = start_;
   const uint64_t t1 = cur_usec(m_);
   start_ = t1;
   compiler_barrier();
   return t1 - t0;
 }
Example #3
0
/**
 * Converts a key to a gni memory handle
 *
 * @param key   gnix memory registration key
 * @param mhdl  gni memory handle
 */
void _gnix_convert_key_to_mhdl(
		gnix_mr_key_t *key,
		gni_mem_handle_t *mhdl)
{
	_gnix_convert_key_to_mhdl_no_crc(key, mhdl);
	compiler_barrier();
	GNI_MEMHNDL_SET_CRC((*mhdl));
}
Example #4
0
int NOINLINE b(int x)
{
  int r;

  compiler_barrier();
  
  if (x)
    r = a();
  else
    r = c(1);
  return r + 1;
}
Example #5
0
u32_t _get_elapsed_program_time(void)
{
	u32_t rtc_elapsed, rtc_past_copy;

	if (!expected_sys_ticks) {
		return 0;
	}

	/* Read rtc_past before RTC_COUNTER */
	rtc_past_copy = rtc_past;

	/* Make sure that compiler will not reverse access to RTC and
	 * rtc_past.
	 */
	compiler_barrier();

	rtc_elapsed = (RTC_COUNTER - rtc_past_copy) & RTC_MASK;

	/* Convert number of Machine cycles to SYS_TICKS */
	return (rtc_elapsed / sys_clock_hw_cycles_per_tick);
}
Example #6
0
u64_t _get_elapsed_clock_time(void)
{
	u64_t elapsed;
	u32_t rtc_elapsed, rtc_past_copy;

	/* Read _sys_clock_tick_count and rtc_past before RTC_COUNTER */
	elapsed = _sys_clock_tick_count;
	rtc_past_copy = rtc_past;

	/* Make sure that compiler will not reverse access to RTC and
	 * variables above.
	 */
	compiler_barrier();

	rtc_elapsed = (RTC_COUNTER - rtc_past_copy) & RTC_MASK;
	if (rtc_elapsed >= sys_clock_hw_cycles_per_tick) {
		/* Update total number of SYS_TICKS passed */
		elapsed += (rtc_elapsed / sys_clock_hw_cycles_per_tick);
	}

	return elapsed;
}
Example #7
0
u32_t _timer_cycle_get_32(void)
{
	u32_t ticked_cycles;
	u32_t elapsed_cycles;

	/* Number of timer cycles announced as ticks so far. */
	ticked_cycles = _sys_clock_tick_count * sys_clock_hw_cycles_per_tick;

	/* Make sure that compiler will not reverse access to RTC and
	 * _sys_clock_tick_count.
	 */
	compiler_barrier();

	/* Number of timer cycles since last announced tick we know about.
	 *
	 * The value of RTC_COUNTER is not reset on tick, so it will
	 * compensate potentialy missed update of _sys_clock_tick_count
	 * which could have happen between the ticked_cycles calculation
	 * and the code below.
	 */
	elapsed_cycles = (RTC_COUNTER - ticked_cycles) & RTC_MASK;

	return ticked_cycles + elapsed_cycles;
}
Example #8
0
unsigned long plthook_entry(unsigned long *ret_addr, unsigned long child_idx,
			    unsigned long module_id, struct mcount_regs *regs)
{
	struct sym *sym;
	unsigned long child_ip;
	struct mcount_thread_data *mtdp;
	struct mcount_ret_stack *rstack;
	struct ftrace_trigger tr = {
		.flags = 0,
	};
	bool skip = false;
	enum filter_result filtered;

	if (unlikely(mcount_should_stop()))
		return 0;

	mtd.recursion_guard = true;

	mtdp = get_thread_data();
	if (unlikely(check_thread_data(mtdp))) {
		mcount_prepare();

		mtdp = get_thread_data();
		assert(mtdp);
	}

	/*
	 * There was a recursion like below:
	 *
	 * plthook_entry -> mcount_entry -> mcount_prepare -> xmalloc
	 *   -> plthook_entry
	 */
	if (mtdp->plthook_guard)
		goto out;

	if (check_dynsym_idxlist(&skip_idxlist, child_idx))
		goto out;

	sym = find_dynsym(&symtabs, child_idx);
	pr_dbg3("[%d] enter %lx: %s\n", child_idx, sym->addr, sym->name);

	child_ip = sym ? sym->addr : 0;
	if (child_ip == 0) {
		pr_err_ns("invalid function idx found! (idx: %d, %#lx)\n",
			  (int) child_idx, child_idx);
	}

	filtered = mcount_entry_filter_check(mtdp, sym->addr, &tr);
	if (filtered != FILTER_IN) {
		/*
		 * Skip recording but still hook the return address,
		 * otherwise it cannot trace further invocations due to
		 * the overwritten PLT entry by the resolver function.
		 */
		skip = true;

		/* but if we don't have rstack, just bail out */
		if (filtered == FILTER_RSTACK)
			goto out;
	}

	mtdp->plthook_guard = true;

	rstack = &mtdp->rstack[mtdp->idx++];

	rstack->depth      = mtdp->record_idx;
	rstack->dyn_idx    = child_idx;
	rstack->parent_loc = ret_addr;
	rstack->parent_ip  = *ret_addr;
	rstack->child_ip   = child_ip;
	rstack->start_time = skip ? 0 : mcount_gettime();
	rstack->end_time   = 0;
	rstack->flags      = skip ? MCOUNT_FL_NORECORD : 0;

	mcount_entry_filter_record(mtdp, rstack, &tr, regs);

	*ret_addr = (unsigned long)plthook_return;

	if (check_dynsym_idxlist(&setjmp_idxlist, child_idx))
		setup_jmpbuf_rstack(mtdp, mtdp->idx - 1);
	else if (check_dynsym_idxlist(&longjmp_idxlist, child_idx))
		rstack->flags |= MCOUNT_FL_LONGJMP;
	else if (check_dynsym_idxlist(&vfork_idxlist, child_idx)) {
		rstack->flags |= MCOUNT_FL_VFORK;
		prepare_vfork(mtdp, rstack);
	}

	/* force flush rstack on some special functions */
	if (check_dynsym_idxlist(&flush_idxlist, child_idx)) {
		record_trace_data(mtdp, rstack, NULL);
	}

	if (plthook_dynsym_resolved[child_idx]) {
		volatile unsigned long *resolved_addr = plthook_dynsym_addr + child_idx;

		/* ensure resolved address was set */
		while (!*resolved_addr)
			cpu_relax();

		mtdp->recursion_guard = false;
		return *resolved_addr;
	}

	mtdp->plthook_addr = plthook_got_ptr[3 + child_idx];

out:
	mtdp->recursion_guard = false;
	return 0;
}

unsigned long plthook_exit(long *retval)
{
	int dyn_idx;
	unsigned long new_addr;
	struct mcount_thread_data *mtdp;
	struct mcount_ret_stack *rstack;

	mtdp = get_thread_data();
	assert(mtdp);

	mtdp->recursion_guard = true;

again:
	rstack = &mtdp->rstack[mtdp->idx - 1];

	if (unlikely(rstack->flags & (MCOUNT_FL_LONGJMP | MCOUNT_FL_VFORK))) {
		if (rstack->flags & MCOUNT_FL_LONGJMP) {
			restore_jmpbuf_rstack(mtdp, mtdp->idx + 1);
			rstack->flags &= ~MCOUNT_FL_LONGJMP;
			goto again;
		}

		if (rstack->flags & MCOUNT_FL_VFORK)
			setup_vfork(mtdp);
	}

	if (unlikely(vfork_parent))
		rstack = restore_vfork(mtdp, rstack);

	dyn_idx = rstack->dyn_idx;
	if (dyn_idx == MCOUNT_INVALID_DYNIDX)
		pr_err_ns("<%d> invalid dynsym idx: %d\n", mtdp->idx, dyn_idx);

	pr_dbg3("[%d] exit  %lx: %s\n", dyn_idx,
		plthook_dynsym_addr[dyn_idx],
		find_dynsym(&symtabs, dyn_idx)->name);

	if (!(rstack->flags & MCOUNT_FL_NORECORD))
		rstack->end_time = mcount_gettime();

	mcount_exit_filter_record(mtdp, rstack, retval);

	if (!plthook_dynsym_resolved[dyn_idx]) {
#ifndef SINGLE_THREAD
		static pthread_mutex_t resolver_mutex = PTHREAD_MUTEX_INITIALIZER;

		pthread_mutex_lock(&resolver_mutex);
#endif
		if (!plthook_dynsym_resolved[dyn_idx]) {
			new_addr = plthook_got_ptr[3 + dyn_idx];
			/* restore GOT so plt_hooker keep called */
			plthook_got_ptr[3 + dyn_idx] = mtdp->plthook_addr;

			plthook_dynsym_addr[dyn_idx] = new_addr;
			plthook_dynsym_resolved[dyn_idx] = true;
		}
#ifndef SINGLE_THREAD
		pthread_mutex_unlock(&resolver_mutex);
#endif
	}

	compiler_barrier();

	mtdp->idx--;
	mtdp->recursion_guard = false;
	mtdp->plthook_guard = false;

	return rstack->parent_ip;
}
Example #9
0
VOID_TASK_IMPL_2(sylvan_skiplist_assign_next, sylvan_skiplist_t, l, MTBDD, dd)
{
    if (dd == mtbdd_false || dd == mtbdd_true) return;

    uint32_t trace[SL_DEPTH];
    uint32_t loc = 0, loc_next = 0, k = SL_DEPTH-1;
    for (;;) {
        /* invariant: [loc].dd < dd */
        /* note: this is always true for loc==0 */
        sl_bucket *e = l->buckets + loc;
        loc_next = (*(volatile uint32_t*)&e->next[k]) & 0x7fffffff;
        if (loc_next != 0 && l->buckets[loc_next].dd == dd) {
            /* found */
            return;
        } else if (loc_next != 0 && l->buckets[loc_next].dd < dd) {
            /* go right */
            loc = loc_next;
        } else if (k > 0) {
            /* go down */
            trace[k] = loc;
            k--;
        } else if (!(e->next[0] & 0x80000000) && cas(&e->next[0], loc_next, loc_next|0x80000000)) {
            /* locked */
            break;
        }
    }

    /* claim next item */
    const uint64_t next = __sync_fetch_and_add(&l->next, 1);
    if (next >= l->size) {
        fprintf(stderr, "Out of cheese exception, no more blocks available\n");
        exit(1);
    }

    /* fill next item */
    sl_bucket *a = l->buckets + next;
    a->dd = dd;
    a->next[0] = loc_next;
    compiler_barrier();
    l->buckets[loc].next[0] = next;

    /* determine height */
    uint64_t h = 1 + __builtin_clz(LACE_TRNG) / 2;
    if (h > SL_DEPTH) h = SL_DEPTH;

    /* go up and create links */
    for (k=1;k<h;k++) {
        loc = trace[k];
        for (;;) {
            sl_bucket *e = l->buckets + loc;
            /* note, at k>0, no locks on edges */
            uint32_t loc_next = *(volatile uint32_t*)&e->next[k];
            if (loc_next != 0 && l->buckets[loc_next].dd < dd) {
                loc = loc_next;
            } else {
                a->next[k] = loc_next;
                if (cas(&e->next[k], loc_next, next)) break;
            }
        }
    }
}