예제 #1
0
파일: lock.c 프로젝트: mytchel/bom
void
lock(struct lock *l)
{
  struct proc *p;
  
  if (up == nil) {
    return;
  }

 retry:

  if (!cas(&l->holder, nil, up)) {
    p = l->wlist;
    while (p != nil && p->next != nil)
      p = p->next;

    up->next = nil;

    if (p == nil) {
      if (!cas(&l->wlist, nil, up)) {
	goto retry;
      }
    } else if (!cas(&p->next, nil, up)) {
      goto retry;
    }

    procwait();
  }
}
예제 #2
0
// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
// Note that there can be spinning threads during all states - they do not
// affect mutex's state.
void
runtime·lock(Lock *l)
{
	uint32 i, v, wait, spin;

	if(m->locks++ < 0)
		runtime·throw("runtime·lock: lock count");

	// Speculative grab for lock.
	v = runtime·xchg(&l->key, MUTEX_LOCKED);
	if(v == MUTEX_UNLOCKED)
		return;

	// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
	// depending on whether there is a thread sleeping
	// on this mutex.  If we ever change l->key from
	// MUTEX_SLEEPING to some other value, we must be
	// careful to change it back to MUTEX_SLEEPING before
	// returning, to ensure that the sleeping thread gets
	// its wakeup call.
	wait = v;

	// On uniprocessor's, no point spinning.
	// On multiprocessors, spin for ACTIVE_SPIN attempts.
	spin = 0;
	if(runtime·ncpu > 1)
		spin = ACTIVE_SPIN;

	for(;;) {
		// Try for lock, spinning.
		for(i = 0; i < spin; i++) {
			while(l->key == MUTEX_UNLOCKED)
				if(runtime·cas(&l->key, MUTEX_UNLOCKED, wait))
					return;
			runtime·procyield(ACTIVE_SPIN_CNT);
		}

		// Try for lock, rescheduling.
		for(i=0; i < PASSIVE_SPIN; i++) {
			while(l->key == MUTEX_UNLOCKED)
				if(runtime·cas(&l->key, MUTEX_UNLOCKED, wait))
					return;
			runtime·osyield();
		}

		// Sleep.
		v = runtime·xchg(&l->key, MUTEX_SLEEPING);
		if(v == MUTEX_UNLOCKED)
			return;
		wait = MUTEX_SLEEPING;
		runtime·futexsleep(&l->key, MUTEX_SLEEPING, -1);
	}
}
//TTAS with exponential backoff
void lock(){
	while(1){
		while(__sync_add_and_fetch(&TTASLock, 0)){//lock is busy -- handle backoff
			__sync_add_and_fetch(&backoff, backoff * 2);//increase backoff time
			if(backoff >= MAX_SLEEP){
				cas(&backoff, backoff, 1);//reset backoff back to 1
			}
			usleep(backoff);
		}//reading to see if lock is busy
			if(cas(&TTASLock, 0, 1)){ //lock acheived
				return;
			}
	}
}
예제 #4
0
파일: mheap.c 프로젝트: tempbottle/golang
// Sweeps spans in list until reclaims at least npages into heap.
// Returns the actual number of pages reclaimed.
static uintptr
MHeap_ReclaimList(MHeap *h, MSpan *list, uintptr npages)
{
	MSpan *s;
	uintptr n;
	uint32 sg;

	n = 0;
	sg = runtime·mheap.sweepgen;
retry:
	for(s = list->next; s != list; s = s->next) {
		if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) {
			runtime·MSpanList_Remove(s);
			// swept spans are at the end of the list
			runtime·MSpanList_InsertBack(list, s);
			runtime·unlock(&h->lock);
			n += runtime·MSpan_Sweep(s);
			runtime·lock(&h->lock);
			if(n >= npages)
				return n;
			// the span could have been moved elsewhere
			goto retry;
		}
		if(s->sweepgen == sg-1) {
			// the span is being sweept by background sweeper, skip
			continue;
		}
		// already swept empty span,
		// all subsequent ones must also be either swept or in process of sweeping
		break;
	}
	return n;
}
예제 #5
0
파일: thread-support.c 프로젝트: AmkG/Orb
void Orb_cell_set(Orb_cell_t c, Orb_t val) {
	Orb_t curv, oldv;
	oldv = safe_read(&c->core);
	do {
		curv = oldv;
	} while(curv != (oldv = cas(&c->core, oldv, val)));
}
예제 #6
0
	void pull(global_queue<value_type> & gq)
	{
		this->clear();

		node * new_head = gq.m_head;
		do
		{
			m_head = new_head;
			new_head = cas(gq.m_head, (node *)0, new_head);
		}
		while (m_head != new_head);

		// Fix-up the pulled list
		if (m_head == 0)
			return;

		++m_size;
		node * cur = m_head;
		while (cur->m_next != 0)
		{
			cur->m_next->m_prev = cur;
			++m_size;
			cur = cur->m_next;
		}

		m_tail = cur;
	}
예제 #7
0
파일: unionfind.c 프로젝트: Meijuh/ltsmin
bool
uf_try_grab (const uf_t *uf, ref_t a)
{
    char x = atomic_read (&uf->array[a].uf_status);
    if (x == UF_LOCK) return false;
    return cas (&uf->array[a].uf_status, x, UF_LOCK);
}
예제 #8
0
stack_t* stack_push(stack_t* head, stack_t* newHead)
{
#if NON_BLOCKING == 0
    pthread_mutex_lock(&mutex);
    newHead->ptr=head;
    pthread_mutex_unlock(&mutex);

#elif NON_BLOCKING == 1
  // Implement a harware CAS-based stack

    if(head == NULL)
    {
        newHead->ptr = head;
    }
    else
    {
        stack_t* old;
        do
        {
            old = head;
            newHead->ptr = old;
        }while(cas(newHead->ptr, old, head) == old);
    }
#else

  // Implement a software CAS-based stack
#endif

  // Debug practice: you can check if this operation results in a stack in a consistent check
  // It doesn't harm performance as sanity check are disabled at measurement time
  // This is to be updated as your implementation progresses
  stack_check((stack_t*)1);

  return newHead;
}
예제 #9
0
파일: shared.hpp 프로젝트: HuangYuSan/liero
	// const to allow shared_ptr<T const>
	void release() const
	{
#if GVL_THREADSAFE
		#error "Not finished"
		if(_ref_count == 1) // 1 means it has to become 0, nobody can increment it after this read
			_delete();
		else
		{
			// TODO: Implement CAS
			int read_ref_count;
			do
			{
				read_ref_count = _ref_count;
			}
			while(!cas(&_ref_count, read_ref_count, read_ref_count - 1));
			
			if(read_ref_count - 1 == 0)
			{
				_clear_weak_ptrs();
				_delete();
			}
		}
#else
		--_ref_count;
		if(_ref_count == 0)
		{
			_clear_weak_ptrs();
			_delete();
		}
#endif
	}
예제 #10
0
void
runtime·stoptheworld(void)
{
	uint32 v;

	schedlock();
	runtime·gcwaiting = 1;

	setmcpumax(1);

	// while mcpu > 1
	for(;;) {
		v = runtime·sched.atomic;
		if(atomic_mcpu(v) <= 1)
			break;

		// It would be unsafe for multiple threads to be using
		// the stopped note at once, but there is only
		// ever one thread doing garbage collection.
		runtime·noteclear(&runtime·sched.stopped);
		if(atomic_waitstop(v))
			runtime·throw("invalid waitstop");

		// atomic { waitstop = 1 }, predicated on mcpu <= 1 check above
		// still being true.
		if(!runtime·cas(&runtime·sched.atomic, v, v+(1<<waitstopShift)))
			continue;

		schedunlock();
		runtime·notesleep(&runtime·sched.stopped);
		schedlock();
	}
	runtime·singleproc = runtime·gomaxprocs == 1;
	schedunlock();
}
예제 #11
0
파일: cgocall.c 프로젝트: cloudaice/golang
void
runtime·cgocall(void (*fn)(void*), void *arg)
{
	Defer d;

	if(m->racecall) {
		runtime·asmcgocall(fn, arg);
		return;
	}

	if(!runtime·iscgo && !Windows)
		runtime·throw("cgocall unavailable");

	if(fn == 0)
		runtime·throw("cgocall nil");

	if(raceenabled)
		runtime·racereleasemerge(&cgosync);

	// Create an extra M for callbacks on threads not created by Go on first cgo call.
	if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0))
		runtime·newextram();

	m->ncgocall++;

	/*
	 * Lock g to m to ensure we stay on the same stack if we do a
	 * cgo callback. Add entry to defer stack in case of panic.
	 */
	runtime·lockOSThread();
	d.fn = &endcgoV;
	d.siz = 0;
	d.link = g->defer;
	d.argp = (void*)-1;  // unused because unlockm never recovers
	d.special = true;
	d.free = false;
	g->defer = &d;

	m->ncgo++;

	/*
	 * Announce we are entering a system call
	 * so that the scheduler knows to create another
	 * M to run goroutines while we are in the
	 * foreign code.
	 *
	 * The call to asmcgocall is guaranteed not to
	 * split the stack and does not allocate memory,
	 * so it is safe to call while "in a system call", outside
	 * the $GOMAXPROCS accounting.
	 */
	runtime·entersyscall();
	runtime·asmcgocall(fn, arg);
	runtime·exitsyscall();

	if(g->defer != &d || d.fn != &endcgoV)
		runtime·throw("runtime: bad defer entry in cgocallback");
	g->defer = d.link;
	endcgo();
}
예제 #12
0
void * thread_routine(void * arg)
{
  int tid;
  int m = 0, w, h;
  tid = *((int *)arg);
  
  while(1){
    if ( m < MAX ){
      w = (++m) * 11 + tid;
    }
    else{
      pthread_exit(NULL);
    }
    
    h = (w * 7) % SIZE;
    
    if (h<0)
    {
      ERROR: goto ERROR;
      ;
    }

    while ( cas(table, h, 0, w) == 0){
      h = (h+1) % SIZE;
    }
  }

}
예제 #13
0
//returns poped element
stack_t* stack_pop(stack_t* head)
{
    if(head == NULL)
		return NULL;
	stack_t* ret; 
#if NON_BLOCKING == 0
  // Implement a lock_based stack
    pthread_mutex_lock(&mutex);
	ret = head;
    head = head->ptr;
    pthread_mutex_unlock(&mutex);
#elif NON_BLOCKING == 1
  // Implement a harware CAS-based stack
	stack_t *newHead; 
    if (head->ptr == NULL){
        ret=head;
        head = NULL;
    }
    else
    {
        do{
            ret = head;
            newHead = head->ptr;
            head = newHead;
        } 
        while(cas(head,newHead,newHead)==newHead);
    }
#else
  /*** Optional ***/
  // Implement a software CAS-based stack
#endif

  return ret;
}
예제 #14
0
void*
thread_test_aba_1(void* arg) {
#if NON_BLOCKING == 1 || NON_BLOCKING == 2
  thread_test_aba_args_t *args = (thread_test_aba_args_t*) arg;
  pthread_mutex_lock(args->lock);
  printf("thread 1 is in control and begins poping 10 from stack\n");
  node_t* data;
  while (1) {
    data=*(args->shared_stack->head);
    if (data==NULL){
      break;
    }
    int value=data->data;
    pthread_mutex_unlock(args->lock);
    sleep(1);
    pthread_mutex_lock(args->lock);
    if (cas(args->shared_stack->head,data,data->next)==data) {
      printf("thread one successfully pop:ed %i from stack\n",data->data);
      pthread_mutex_unlock(args->lock);
      if (value!=data->data){
      printf("aba problem detected\n");
      args->success=1;
      }

      break;
    }
  }
args->id=0;
#endif
  return NULL;
}
예제 #15
0
파일: lock.c 프로젝트: mytchel/bom
void
unlock(struct lock *l)
{
  struct proc *p;

  if (up == nil) {
    return;
  }

 retry:

  p = l->wlist;
  if (p != nil) {
    if (!cas(&l->wlist, p, p->next)) {
      goto retry;
    }

    p->next = nil;
    
    l->holder = p; 
    procready(p);
  } else {
    l->holder = nil;
  }
}
예제 #16
0
    static inline T fetch_add(volatile T *ptr, T x) {
      T ncount = *ptr, count;
      do {
	count = ncount;
	ncount = cas((T *)ptr, count, count + x);
      } while(ncount != count);
      return count;
    }
예제 #17
0
파일: apc.cpp 프로젝트: 191919/hhvm
TEST(APC, BasicPrimeStuff) {
  auto store = new_primed_store();
  Variant val;

  EXPECT_TRUE(store->get("int_2", val));
  EXPECT_TRUE(cellSame(*val.asCell(), make_tv<KindOfInt64>(2)));

  bool found = false;
  EXPECT_EQ(store->inc("int_3", 1, found), 4);
  EXPECT_TRUE(found);
  EXPECT_FALSE(store->get("int_200", val));

  EXPECT_EQ(store->cas("obj_1", 1, 2), true); // stdclass converts to 1
  EXPECT_EQ(store->cas("obj_2", 4, 5), false);
  EXPECT_EQ(store->cas("int_4", 4, 5), true);
  EXPECT_EQ(store->cas("int_5", 4, 5), false);
}
예제 #18
0
void*
thread_test_aba_2(void* arg) {
#if NON_BLOCKING == 1 || NON_BLOCKING == 2
  thread_test_aba_args_t *args = (thread_test_aba_args_t*) arg;
  pthread_mutex_lock(args->lock);
  printf("thread two is in controll\n");
  node_t* data;
  while (1) {
    data=*(args->shared_stack->head);
    if (data==NULL){
      break;
    }
    if (cas(args->shared_stack->head,data,data->next)==data) {
      printf("thread two successfully poped %i from stack\n",data->data);
      break;
    }
  }
  node_t* node=malloc(sizeof(node_t));
  node->data=15;
  while (1) {
    node_t* temp=*(args->shared_stack->head);
    node->next=temp;
    if(cas(args->shared_stack->head,temp,node)==temp) {
      printf("thread 2 succesfully pushed 15 to stack successfull\n");
      break;
    }
  }
  printf("thread 2 modified data in %i" ,data->data);
  data->data=20;
  printf("to 20 \n");

  while (1) {
    node_t* temp=*(args->shared_stack->head);
    data->next=temp;
    if(cas(args->shared_stack->head,temp,data)==temp) {
      printf("thread 2 pushed 20 to stack \n");
      break;
    }
  }
  printf("thread two gives control back to thread one \n");
  pthread_mutex_unlock(args->lock);


#endif
  return NULL;
}
예제 #19
0
CTraceCollector::~CTraceCollector()
{
    CAutoCriticalSection cas(m_CriticalSectionSys);
    for (TPipeListenerList::iterator it = m_PipeListenerList.begin(); it != m_PipeListenerList.end(); it++)
    {
        delete (*it);
    }
}
예제 #20
0
파일: lace.c 프로젝트: fritzo/lace
static inline void
lock_acquire()
{
    while (1) {
        while (lock) {}
        if (cas(&lock, 0, 1)) return;
    }
}
예제 #21
0
 /* postfix operator */
 T operator --(int)
 {
     for(;;)
     {
         T oldv = value;
         if(likely(cas(&value, oldv, oldv-1)))
             return oldv;
     }
 }
예제 #22
0
bool CTraceCollector::RunPipeReader()
{
    CPipeListener* pPipeListener = new CPipeListener(this);

    CAutoCriticalSection cas(m_CriticalSectionSys);
    m_PipeListenerList.push_back(pPipeListener);

    return pPipeListener->StartReader();
}
예제 #23
0
 static inline T set_to_max(volatile T *ptr, T x) {
   T count = *ptr;
   while(x > count) {
     T ncount = cas(ptr, count, x);
     if(ncount == count)
       return x;
     count = ncount;
   }
   return count;
 }
예제 #24
0
 T operator +=(T v)
 {
     for(;;)
     {
         T oldv = value;
         T newv = oldv + v;
         if(likely(cas(&value, oldv, newv)))
             return newv;
     }
 }
예제 #25
0
static void
futexlock(Lock *l)
{
	uint32 v;

again:
	v = l->key;
	if((v&1) == 0){
		if(cas(&l->key, v, v|1)){
			// Lock wasn't held; we grabbed it.
			return;
		}
		goto again;
	}

	// Lock was held; try to add ourselves to the waiter count.
	if(!cas(&l->key, v, v+2))
		goto again;

	// We're accounted for, now sleep in the kernel.
	//
	// We avoid the obvious lock/unlock race because
	// the kernel won't put us to sleep if l->key has
	// changed underfoot and is no longer v+2.
	//
	// We only really care that (v&1) == 1 (the lock is held),
	// and in fact there is a futex variant that could
	// accomodate that check, but let's not get carried away.)
	futexsleep(&l->key, v+2);

	// We're awake: remove ourselves from the count.
	for(;;){
		v = l->key;
		if(v < 2)
			throw("bad lock key");
		if(cas(&l->key, v, v-2))
			break;
	}

	// Try for the lock again.
	goto again;
}
예제 #26
0
파일: atomic_arm.c 프로젝트: abustany/go
void
runtime·atomicstore(uint32 volatile* addr, uint32 v)
{
	uint32 old;
	
	for(;;) {
		old = *addr;
		if(runtime·cas(addr, old, v))
			return;
	}
}
예제 #27
0
파일: atomic_arm.c 프로젝트: abustany/go
uint32
runtime·xchg(uint32 volatile* addr, uint32 v)
{
	uint32 old;

	for(;;) {
		old = *addr;
		if(runtime·cas(addr, old, v))
			return old;
	}
}
예제 #28
0
void push (int v) {
  struct cell *t;
  struct cell *x = (struct cell*) violin_malloc(sizeof *x);
  x->data = v;

  do {
    t = s;
    x->next = t;
    Yield();
  } while (!cas(&s,t,x));
}
예제 #29
0
파일: atomic_arm.c 프로젝트: abustany/go
uint32
runtime·xadd(uint32 volatile *val, int32 delta)
{
	uint32 oval, nval;

	for(;;){
		oval = *val;
		nval = oval + delta;
		if(runtime·cas(val, oval, nval))
			return nval;
	}
}
예제 #30
0
파일: Evac.c 프로젝트: 23Skidoo/ghc
STATIC_INLINE GNUC_ATTR_HOT void
copy_tag(StgClosure **p, const StgInfoTable *info,
         StgClosure *src, nat size, nat gen_no, StgWord tag)
{
    StgPtr to, from;
    nat i;

    to = alloc_for_copy(size,gen_no);

    from = (StgPtr)src;
    to[0] = (W_)info;
    for (i = 1; i < size; i++) { // unroll for small i
        to[i] = from[i];
    }

//  if (to+size+2 < bd->start + BLOCK_SIZE_W) {
//      __builtin_prefetch(to + size + 2, 1);
//  }

#if defined(PARALLEL_GC)
    {
        const StgInfoTable *new_info;
        new_info = (const StgInfoTable *)cas((StgPtr)&src->header.info, (W_)info, MK_FORWARDING_PTR(to));
        if (new_info != info) {
#ifdef PROFILING
            // We copied this object at the same time as another
            // thread.  We'll evacuate the object again and the copy
            // we just made will be discarded at the next GC, but we
            // may have copied it after the other thread called
            // SET_EVACUAEE_FOR_LDV(), which would confuse the LDV
            // profiler when it encounters this closure in
            // processHeapClosureForDead.  So we reset the LDVW field
            // here.
            LDVW(to) = 0;
#endif
            return evacuate(p); // does the failed_to_evac stuff
        } else {
            *p = TAG_CLOSURE(tag,(StgClosure*)to);
        }
    }
#else
    src->header.info = (const StgInfoTable *)MK_FORWARDING_PTR(to);
    *p = TAG_CLOSURE(tag,(StgClosure*)to);
#endif

#ifdef PROFILING
    // We store the size of the just evacuated object in the LDV word so that
    // the profiler can guess the position of the next object later.
    // This is safe only if we are sure that no other thread evacuates
    // the object again, so we cannot use copy_tag_nolock when PROFILING.
    SET_EVACUAEE_FOR_LDV(from, size);
#endif
}