void hh_add(value key, value data) { unsigned long hash = get_hash(key); unsigned int slot = hash & (HASHTBL_SIZE - 1); while(1) { unsigned long slot_hash = hashtbl[slot].hash; if(slot_hash == hash) { write_at(slot, data); return; } if(slot_hash == 0) { // We think we might have a free slot, try to atomically grab it. if(__sync_bool_compare_and_swap(&(hashtbl[slot].hash), 0, hash)) { unsigned long size = __sync_fetch_and_add(hcounter, 1); assert(size < HASHTBL_SIZE); write_at(slot, data); return; } // Grabbing it failed -- why? If someone else inserted the data we were // about to, we are done (don't double-insert). Otherwise, keep going. // Note that this read relies on the __sync call above preventing the // compiler from caching the value read out of memory. (And of course // isn't safe on any arch that requires memory barriers.) if(hashtbl[slot].hash == hash) { // FIXME: there is a race here. The data may not actually be written by // the time we return here, and even the sigil value "1" may not be // written into the address by the winning thread. If this thread // manages to call hh_mem on this key before the winning thread can // write the sigil "1", things will be broken since the data we just // wrote will be missing. Want to more carefully think out the right // fix and need to commit a fix for a much worse race, so leaving this // here for now -- this thread has to get all the way back into hh_mem // before the other thread executes the 37 instructions it takes to // write the sigil, so I'm not super worried. return; } } slot = (slot + 1) & (HASHTBL_SIZE - 1); } }
void test_compare_and_swap (void) { sc = __sync_val_compare_and_swap (&sc, uc, sc); uc = __sync_val_compare_and_swap (&uc, uc, sc); ss = __sync_val_compare_and_swap (&ss, uc, sc); us = __sync_val_compare_and_swap (&us, uc, sc); si = __sync_val_compare_and_swap (&si, uc, sc); ui = __sync_val_compare_and_swap (&ui, uc, sc); sll = __sync_val_compare_and_swap (&sll, uc, sc); ull = __sync_val_compare_and_swap (&ull, uc, sc); ui = __sync_bool_compare_and_swap (&sc, uc, sc); ui = __sync_bool_compare_and_swap (&uc, uc, sc); ui = __sync_bool_compare_and_swap (&ss, uc, sc); ui = __sync_bool_compare_and_swap (&us, uc, sc); ui = __sync_bool_compare_and_swap (&si, uc, sc); ui = __sync_bool_compare_and_swap (&ui, uc, sc); ui = __sync_bool_compare_and_swap (&sll, uc, sc); ui = __sync_bool_compare_and_swap (&ull, uc, sc); }
void hh_add(value key, value data) { unsigned long hash = get_hash(key); unsigned int slot = hash & (HASHTBL_SIZE - 1); while(1) { unsigned long slot_hash = hashtbl[slot].hash; if(slot_hash == hash) { write_at(slot, data); return; } if(slot_hash == 0) { // We think we might have a free slot, try to atomically grab it. if(__sync_bool_compare_and_swap(&(hashtbl[slot].hash), 0, hash)) { unsigned long size = __sync_fetch_and_add(hcounter, 1); assert(size < HASHTBL_SIZE); write_at(slot, data); return; } // Grabbing it failed -- why? If someone else is trying to insert // the data we were about to, try to insert it ourselves too. // Otherwise, keep going. // Note that this read relies on the __sync call above preventing the // compiler from caching the value read out of memory. (And of course // isn't safe on any arch that requires memory barriers.) if(hashtbl[slot].hash == hash) { // Some other thread already grabbed this slot to write this // key, but they might not have written the address (or even // the sigil value) yet. We can't return from hh_add until we // know that hh_mem would succeed, which is to say that addr is // no longer null. To make sure hh_mem will work, we try // writing the value ourselves; either we insert it ourselves or // we know the address is now non-NULL. write_at(slot, data); return; } } slot = (slot + 1) & (HASHTBL_SIZE - 1); } }
/** * Create a thread-specific data key. * * Creates a new thread-specific data key that can be used by all threads in * the process to store data local to that thread using pthread_getspecific() * and pthread_setspecific(). * * When the key is first created, the value associated with the key will be * NULL in all threads. When a thread exits, if a key value is non-NULL, the * destructor function (if any) will be called on it. The order of destructor * calls is unspecified. * * @param keyp Where to store created key. * @param dtor Destructor function (can be NULL). * * @return 0 on success, or EAGAIN if the maximum number of keys * per process has been exceeded. */ int pthread_key_create(pthread_key_t *keyp, void (*dtor)(void *val)) { pthread_key_t key; /* Try to allocate a new key. */ while(true) { key = next_pthread_key; if(key >= PTHREAD_KEYS_MAX) return EAGAIN; if(__sync_bool_compare_and_swap(&next_pthread_key, key, key + 1)) break; } assert(!pthread_specific[key].allocated); pthread_specific[key].allocated = true; pthread_specific[key].dtor = dtor; return 0; }
bool ht_acquire_slot(struct t_hash_table * ht, const uint8_t infohash[20], const uint32_t slot) { /* may miss to lookup due to multithread issue, which would not affect functionality */ if (memcmp(ht->slot[slot].infohash, infohash, 20) == 0) { return true; } while (1) { uint8_t oldval = ht->used[BYTE_POS(slot)]; uint8_t newval = oldval | (1 << BIT_POS(slot)); if (oldval & (1 << BIT_POS(slot))) { /* failed to acquire, already occupied */ return false; } /* try set used bit to 1 with CAS */ if (__sync_bool_compare_and_swap(&ht->used[BYTE_POS(slot)], oldval, newval)) { memcpy(&ht->slot[slot].infohash, infohash, 20); return true; } } }
bool Node::try_finish_recalc() { recalc_cnt_++; while (true) { int recalc_state_copy = recalc_state_; switch (recalc_state_copy) { case own_st: if (__sync_bool_compare_and_swap (&recalc_state_, own_st, empty_st)) { holder_id_ = -1; return true; } break; case own_recalc_st: return false; default: assert (0); } } return false; }
int rb_release(rb_ringbuffer * buffer, uint64_t seq_num, uint64_t count) { if(unlikely(count == 0)) { return RB_COUNT_ZERO; } if(unlikely(count > buffer->ring_size)) { return RB_COUNT_OVERFLOW; } /* Should only occur with poorly behaving client */ if(unlikely(seq_num != buffer->read_tail)) { return RB_RELEASE_INVALID; } /* Make sure publish doesn't overlap into unwritten space */ if(unlikely(seq_num+count >= buffer->read_head)) { return RB_RELEASE_OVERRUN; } /* If above have passed then this should be the correct owner and op should proceed */ if(unlikely(!__sync_bool_compare_and_swap(&buffer->read_tail, seq_num, seq_num+count))) { return RB_RELEASE_RACE; } return RB_SUCCESS; }
inline int loop::close(basic_handler &h) { DSCRPTR fd = h.fd(); if (fd == INVALID_FD) { ASSERT(false); return NBR_OK; //already closed once. user try to close client connection, it may happen. } ms_pl[fd]->detach(fd); wp().detach(fd); /* */ if (__sync_bool_compare_and_swap(&(ms_h[fd]), &h, NULL)) { h.on_close(); UNREF_EMPTR(&h); ms_pl[fd] = NULL; } else { ASSERT(false); } return NBR_OK; }
void unlock() { Thread* cur = PerCPU::thread(); ASSERT(locker_ == cur); file_ = 0; line_ = -1; if(recursive_ > 0) { recursive_--; } else { // Use a sync primitive because it includes the required memory // barrier to make sure other CPUs see the change in value_ // properly. ASSERT(__sync_bool_compare_and_swap(&locker_, cur, 0)); } if(enable_interrupts_) cpu::enable_interrupts(); }
int myth_sleeper_push(int *sem, int rank,int num) { int rem = sleeper; //lock (*real_pthread_mutex_lock)(queue_lock); if(num != -1) { if(num != task_num) { //unlock (*real_pthread_mutex_unlock)(queue_lock); return -1; } } if(!__sync_bool_compare_and_swap(&sleeper,rem,rem+1)) { //atomic(sleeper++;) //unlock (*real_pthread_mutex_unlock)(queue_lock); return -1; } if(g_envs[rank].exit_flag == 1) { //unlock (*real_pthread_mutex_unlock)(queue_lock); return -1; } sleep_queue_t tmp = myth_malloc(sizeof(struct sleep_queue)); tmp->head_sem = sem; tmp->head_rank = rank; tmp->tail = tmp; tmp->next = NULL; if(g_sleep_queue == NULL) { g_sleep_queue = tmp; g_sleep_queue->tail = tmp; } else if(g_sleep_queue->tail == NULL) { //real_free(g_sleep_queue); g_sleep_queue = tmp; g_sleep_queue->tail = tmp; }else { g_sleep_queue->tail->next = tmp; g_sleep_queue->tail = tmp; } //unlock (*real_pthread_mutex_unlock)(queue_lock); return 0; }
static void soclCreateKernel_task(void *data) { struct _cl_kernel *k = (struct _cl_kernel *)data; int range = starpu_worker_get_range(); cl_int err; if (k->program->cl_programs[range] == NULL) { k->errcodes[range] = CL_SUCCESS; DEBUG_MSG("[Device %d] Kernel creation skipped: program has not been built for this device.\n", starpu_worker_get_id()); return; } DEBUG_MSG("[Device %d] Creating kernel...\n", starpu_worker_get_id()); k->cl_kernels[range] = clCreateKernel(k->program->cl_programs[range], k->kernel_name, &err); if (err != CL_SUCCESS) { k->errcodes[range] = err; ERROR_STOP("[Device %d] Unable to create kernel. Error %d. Aborting.\n", starpu_worker_get_id(), err); return; } /* One worker creates argument structures */ if (__sync_bool_compare_and_swap(&k->num_args, 0, 666)) { unsigned int i; cl_uint num_args; err = clGetKernelInfo(k->cl_kernels[range], CL_KERNEL_NUM_ARGS, sizeof(num_args), &num_args, NULL); if (err != CL_SUCCESS) { DEBUG_CL("clGetKernelInfo", err); ERROR_STOP("Unable to get kernel argument count. Aborting.\n"); } k->num_args = num_args; DEBUG_MSG("Kernel has %d arguments\n", num_args); k->arg_size = (size_t*)malloc(sizeof(size_t) * num_args); k->arg_value = (void**)malloc(sizeof(void*) * num_args); k->arg_type = (enum kernel_arg_type*)malloc(sizeof(enum kernel_arg_type) * num_args); /* Settings default type to NULL */ for (i=0; i<num_args; i++) { k->arg_value[i] = NULL; k->arg_type[i] = Null; } } }
int main(int argc, char **argv) { int new_val, reg_val, old_val, read; printf("Register value = "); scanf("%d", &read); reg_val = read; printf("New value = "); scanf("%d", &read); new_val = read; do { old_val = reg_val; if(old_val >= new_val) break; } while(!__sync_bool_compare_and_swap(®_val, old_val, new_val)); printf("new_val = %d, reg_val = %d\n", new_val, reg_val); return 0; }
static bool Acquire(QNode* volatile* L, QNode* I, uint64_t waitCount) { I->next = NULL; I->status = LOCKED; QNode* pred = (QNode*) __sync_lock_test_and_set((uint64_t*)L, I); if(pred) { pred->next = I; uint64_t curWaitCount = 0; while( (I->status == LOCKED) && (++curWaitCount < waitCount) ) ; // spin if(I->status == LOCKED) { if(__sync_bool_compare_and_swap(&(I->status), LOCKED, ABORTED)){ // aborted!! return false; } // Predecessor exited, so we have the lock } } return true; }
int sm_munmap(void* addr, size_t len) { //For now, just move the break back if possible. //Clear this so MMAP_CLEARS works right -- free mem is always clear. memset(addr, 0, len); /*int success =*/ __sync_bool_compare_and_swap(&sm_region->brk, (intptr_t)addr + len, addr); //if(success) { // printf("munmap returned break %lx\n", len); //} else { // printf("munmap leaking mem %p len %lx (%p) brk 0x%lx\n", // addr, len, (void*)((uintptr_t)addr + len), sm_region->brk); //} //fflush(stdout); return 0; }
/* * doscom_smemch_trylock */ int doscom_smemch_trylock(const doscom_id_t smemch_id) { doscom_smemch_t *p_smemch; uint32_t *p_lock; int ret; CHECK_NOINIT(); CHECK_SMEMCH_ID(smemch_id); p_smemch = get_smemch(smemch_id); p_lock = p_smemch->p_lock; for(;;){ if (*p_lock == 1) return DOSCOM_LOCKED; ret = __sync_bool_compare_and_swap (p_lock, 0, 1); if (ret == true) break; } return DOSCOM_SUCCESS; }
static int reserve_id(struct socket_server *ss) { int i; for (i=0;i<MAX_SOCKET;i++) { int id = __sync_add_and_fetch(&(ss->alloc_id), 1); if (id < 0) { id = __sync_and_and_fetch(&(ss->alloc_id), 0x7fffffff); } struct socket *s = &ss->slot[id % MAX_SOCKET]; if (s->type == SOCKET_TYPE_INVALID) { if (__sync_bool_compare_and_swap(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) { return id; } else { // retry --i; } } } return -1; }
void start_thread(dmthread_t* thread) { UINTN i = 0; ptr_size* gsp = 0; ptr_size* gbp = 0; int disp; char * stack_btm; __asm( "mov %%" bp_register ",%0":"=m"(gbp):); __asm( "mov %%" sp_register ",%0":"=m"(gsp):); gThreads++; gBS->AllocatePool(EfiBootServicesData, STACK_SIZE + 128, (void**)&thread->stack); disp = (char*)gbp - (char*)gsp; stack_btm = ((char*)thread->stack)+ STACK_SIZE - (gbp - gsp + 4)*sizeof(ptr_size); for(i =0;i<disp /sizeof(ptr_size)+ 4;i++){ ((ptr_size*)stack_btm)[i] = gsp[i]; } gbp = (ptr_size*)((char*)stack_btm + disp); //Print(L"Stack :%p\n", gbp); __asm( "mov %0, %%" sp_register ::"m"(stack_btm)); __asm( "mov %0, %%" bp_register ::"m"(gbp)); i = SetJump(&thread->sig_context); if( i > 0) { __sync_bool_compare_and_swap (&Inschedule, 1, 0); (thread->kernel)(thread->arg); if (sys.threads -> next ){ sys.current->thread.status=STATUS_DEAD; gThreads --; // skedule Skedule(); }else{ *(int*)0 = 0; } // exit threads } }
static int mux_openr(const char *path){ int i, m; int fds[2]; m = muxfind(path); if(m < 0) return m; if(pipe(fds) < 0) return 0-errno; for(i=0;i<Readmax;i++){ if(__sync_bool_compare_and_swap(&muxs[m].wh[i], 0, fds[1])) break; } if(i==Readmax){ close(fds[0]); close(fds[1]); return -ENOMEM; } muxs[m].rh[i]=fds[0]; return i*Muxmax+m; }
int socket_server::reserve_id() { for (int i = 0; i < MAX_SOCKET; i++) { int id = __sync_add_and_fetch(&alloc_id, 1); if (id < 0) { id = __sync_and_and_fetch(&alloc_id, 0x7fffffff); } struct socket *s = &slot[HASH_ID(id)]; if (s->type == SOCKET_TYPE_INVALID) { if (__sync_bool_compare_and_swap(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) { s->id = id; s->fd = -1; return id; } else { --i; } } } return -1; }
static struct cell * globalmq_pop(struct global_queue *q) { uint32_t head = q->head; uint32_t head_ptr = GP(head); if (head_ptr == GP(q->tail)) { return NULL; } if(!q->flag[head_ptr]) { return NULL; } struct cell * c = q->queue[head_ptr]; if (!__sync_bool_compare_and_swap(&q->head, head, head+1)) { return NULL; } q->flag[head_ptr] = false; __sync_synchronize(); return c; }
static int journal_fd(void) { int fd; static int fd_plus_one = 0; retry: if (fd_plus_one > 0) return fd_plus_one - 1; fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; fd_inc_sndbuf(fd, SNDBUF_SIZE); if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) { safe_close(fd); goto retry; } return fd; }
struct message_queue * skynet_globalmq_pop() { struct global_queue *q = Q; uint32_t head = q->head; uint32_t head_ptr = GP(head); if (head_ptr == GP(q->tail)) { return NULL; } if(!q->flag[head_ptr]) { return NULL; } struct message_queue * mq = q->queue[head_ptr]; if (!__sync_bool_compare_and_swap(&q->head, head, head+1)) { return NULL; } q->flag[head_ptr] = false; return mq; }
static inline void dgSpinLock(dgInt32 *spin) { #ifdef _WIN32 while (InterlockedExchange((long*) spin, 1)) { Sleep(0); } #elif defined (__APPLE__) #ifndef TARGET_OS_IPHONE while( ! OSAtomicCompareAndSwap32(0, 1, (int32_t*) spin) ) { sched_yield(); } #endif #else while(! __sync_bool_compare_and_swap((int32_t*)spin, 0, 1) ) { sched_yield(); } #endif }
int rb_claim(rb_ringbuffer * buffer, uint64_t * seq_num, uint64_t count) { if(unlikely(count == 0)) { return RB_COUNT_ZERO; } if(unlikely(count > buffer->ring_size)) { return RB_COUNT_OVERFLOW; } /* Loops until either a slot is claimed or an overrun occurs */ for(*seq_num = buffer->write_head; /* Overrun should only occur in the event of buffer backup */ unlikely(*seq_num+count >= buffer->read_tail + buffer->ring_size) || /* Compete with other claimants until you win */ !__sync_bool_compare_and_swap(&buffer->write_head, *seq_num, *seq_num+count); /* You lost the update race, move to the new position */ *seq_num = buffer->write_head) { /* If the fail was due to lack of room then bail early */ if(unlikely(*seq_num+count >= buffer->read_tail + buffer->ring_size)) { /* Expect caller to implement backoff on overrun */ return RB_CLAIM_OVERRUN; } } return RB_SUCCESS; }
void* doWork(WorkerThread* thread) { WorkItem* item; do { if (item = workList) { if (__sync_bool_compare_and_swap(&workList, item, item->next)) { switch (item->length) { case 1: calculateFrequencies(item->data, thread->hash1, item->first, item->last); break; case 2: calculateFrequencies(item->data, thread->hash2, item->first, item->last); break; case 3: calculateFrequencies(item->data, thread->hash3, item->first, item->last); break; case 4: calculateFrequencies(item->data, thread->hash4, item->first, item->last); break; case 6: calculateFrequencies(item->data, thread->hash6, item->first, item->last); break; case 12: calculateFrequencies(item->data, thread->hash12, item->first, item->last); break; case 18: calculateFrequencies(item->data, thread->hash18, item->first, item->last); break; default: exit(666); break; } delete item; } } else { if (moreWorkIsPossible) usleep(1000); } } while (workList || moreWorkIsPossible); return NULL; }
static void _CFCommandLineInfoInitLinux() { if (!__CFArgv) { int capacity = 2; int count = 0; char **args = malloc(sizeof(*args) * capacity); FILE *fStream = fopen("/proc/self/cmdline", "r"); char *argBuf = NULL; size_t argBufCapacity = 0; while (-1 != getdelim(&argBuf, &argBufCapacity, '\0', fStream)) { // We ensure that argBuf == NULL, so getdelim returns // a malloc'd string. if (count == capacity) { capacity *= 2; args = realloc(args, sizeof(*args) * capacity); } args[count] = argBuf; count++; argBuf = NULL; argBufCapacity = 0; } fclose(fStream); free(argBuf); __CFArgc = count; if (!__sync_bool_compare_and_swap(&__CFArgv, NULL, args)) { // Lost the race for (int i=0; i < count; i++) { free(args[i]); } free(args); } } }
bool GOMP_single_start (void) { #ifdef HAVE_SYNC_BUILTINS struct gomp_thread *thr = gomp_thread (); struct gomp_team *team = thr->ts.team; unsigned long single_count; if (__builtin_expect (team == NULL, 0)) return true; single_count = thr->ts.single_count++; return __sync_bool_compare_and_swap (&team->single_count, single_count, single_count + 1L); #else bool ret = gomp_work_share_start (false); if (ret) gomp_work_share_init_done (); gomp_work_share_end_nowait (); return ret; #endif }
EBBRC MsgMgrPrim_Init(void) { static EventHandlerId theMsgMgrEHId = 0; if (__sync_bool_compare_and_swap(&theMsgMgrEHId, (MsgMgrId)0, (MsgMgrId)-1)) { EBBRC rc; EBBId id; // create root for MsgMgr rc = CObjEBBRootMultiImpCreate(&rootRefMM, MsgMgrPrim_createRepAssert); LRT_RCAssert(rc); rc = EBBAllocPrimId(&id); LRT_RCAssert(rc); rc = EBBBindPrimId(id, CObjEBBMissFunc, (EBBMissArg)rootRefMM); LRT_RCAssert(rc); theMsgMgrId = (MsgMgrId)id; // create root for EventHandler part of MsgMgr rc = CObjEBBRootMultiImpCreate(&rootRefEH, MsgMgrPrim_createRepAssert); LRT_RCAssert(rc); rc = EBBAllocPrimId(&id); LRT_RCAssert(rc); rc = EBBBindPrimId(id, CObjEBBMissFunc, (EBBMissArg)rootRefEH); LRT_RCAssert(rc); theMsgMgrEHId = (EventHandlerId)id; LRT_Assert(id != NULL); } else { while (((volatile uintptr_t)theMsgMgrEHId)==-1); } // initialize the msgmgr rep on this core, since we need to take // over the event locally for IPI even before anyone sends a message from // this event location LRT_Assert(theMsgMgrEHId != NULL); MsgMgrPrim_createRep(rootRefMM, rootRefEH, theMsgMgrEHId); return EBBRC_OK; }
void pmap_pcid_deallocate_pcid(int ccpu, pmap_t tpmap) { pcid_t pcid; pmap_t lp; pcid_ref_t prior_count; pcid = tpmap->pmap_pcid_cpus[ccpu]; pmap_assert(pcid != PMAP_PCID_INVALID_PCID); if (pcid == PMAP_PCID_INVALID_PCID) return; lp = cpu_datap(ccpu)->cpu_pcid_last_pmap_dispatched[pcid]; pmap_assert(pcid > 0 && pcid < PMAP_PCID_MAX_PCID); pmap_assert(cpu_datap(ccpu)->cpu_pcid_refcounts[pcid] >= 1); if (lp == tpmap) (void)__sync_bool_compare_and_swap(&cpu_datap(ccpu)->cpu_pcid_last_pmap_dispatched[pcid], tpmap, PMAP_INVALID); if ((prior_count = __sync_fetch_and_sub(&cpu_datap(ccpu)->cpu_pcid_refcounts[pcid], 1)) == 1) { cpu_datap(ccpu)->cpu_pcid_free_hint = pcid; } pmap_assert(prior_count <= PMAP_PCID_MAX_REFCOUNT); }
static void __fini_lib(void) { clock_t clck = clock(); /* check already finalized */ if(!__sync_bool_compare_and_swap(&g_ctx.init_done, LOG_MALLOC_INIT_DONE, LOG_MALLOC_FINI_DONE)) return; if(!g_ctx.memlog_disabled) { int s, w; char buf[LOG_BUFSIZE]; const char maps_head[] = "# FILE /proc/self/maps\n"; s = snprintf(buf, sizeof(buf), "+ FINI [%u:%u] malloc=%u calloc=%u realloc=%u memalign=%u/%u valloc=%u free=%u\n", g_ctx.mem_used, g_ctx.mem_rused, g_ctx.stat.malloc, g_ctx.stat.calloc, g_ctx.stat.realloc, g_ctx.stat.memalign, g_ctx.stat.posix_memalign, g_ctx.stat.valloc, g_ctx.stat.free); w = write(g_ctx.memlog_fd, buf, s); /* maps out here, because dynamic libs could by mapped during run */ copyfile(maps_head, sizeof(maps_head) - 1, g_maps_path, g_ctx.memlog_fd); s = snprintf(buf, sizeof(buf), "# CLOCK-END %lu\n", clck); w = write(g_ctx.memlog_fd, buf, s); s = snprintf(buf, sizeof(buf), "# CLOCK-DIFF %lu\n", clck - g_ctx.clock_start); w = write(g_ctx.memlog_fd, buf, s); } if(g_ctx.statm_fd != -1) close(g_ctx.statm_fd); g_ctx.statm_fd = -1; return; }