void consumer(struct buffer *b) /*@ requires [_]b->m |-> ?m &*& [_]b->v |-> ?v &*& [_]mutex(m) &*& inv(m) == buffer(b) &*& [_]b->gid |-> ?gid &*& obs(?O) &*& tic(gid) &*& no_cycle(v,O) == true &*& no_cycle(m,O) == true; @*/ /*@ ensures [_]b->m |-> m &*& [_]b->v |-> v &*& [_]mutex(m) &*& obs(O); @*/ { //@ close mutex_inv(m,buffer(b)); mutex_acquire(b->m); //@ open buffer(b)(?Wt1,?Ot1); //@ leak [_]b->v |-> v; while (size_of(b->q)==0) /*@ invariant [_]b->m |-> m &*& [_]b->v |-> v &*& b->q |-> ?q &*& [_]b->gid |-> gid &*& queue(q,?s) &*& s>=0 &*& mutex_held(m, _, ?Wt, ?Ot) &*& ctr(gid,?Ct) &*& Wt(v) + Ct <= Ot(v) + s &*& Wt(v) <= Ot(v) &*& obs(cons(m,O)) &*& tic(gid); @*/ { //@ dec_ctr(gid); //@ close buffer(b)(finc(Wt,v),Ot); //@ close mutex_inv(m,buffer(b)); //@ close condvar_trn(v,vtrn(gid)); condvar_wait(b->v, b->m); //@ open buffer(b)(_,_); //@ open vtrn(gid)(); } dequeue(b->q); //@ dec_ctr(gid); //@ close buffer(b)(Wt, Ot); //@ close mutex_inv(m,buffer(b)); mutex_release(b->m); //@ leak [_]mutex(m); }
void WA_lock(WA_recursiveLock _lock) #endif { NSAPIThreadRecursiveLock *lock = (NSAPIThreadRecursiveLock *)_lock; SYS_THREAD self = systhread_current(); #ifdef EXTRA_DEBUGGING_LOGS if (_lock != logMutex) WOLog(WO_DBG, " locking %s from %s:%d", lock->name, file, line); #endif crit_enter(lock->crit); while (lock->lockingThread != self && lock->lockCount != 0) condvar_wait(lock->condvar); lock->lockingThread = self; lock->lockCount++; crit_exit(lock->crit); }
/* * This method sends packets from the queue * * @param send_func Function pointer to radio send function * @p Parameters of environment */ void bs_send(void* send_func, bs_params_t* p) { message_t m; message_t* m_ptr; for(;;) { mutex_lock( &(p->mutex) ); while( (m_ptr = dequeueMsg(p)) == NULL ) condvar_wait( &(p->condvar), &(p->mutex) ); m = *m_ptr; mutex_unlock( &(p->mutex) ); condvar_signalAll( &(p->condvar) ); if(TOS_NODE_ID == 0) { // we just received a serial msg sendSerialMsg(&m); } else { // we just receive a radio msg sendRadioMsg(&m); } } }
/* * This method is called when a packet is received * * @param recv_func Function pointer to either serial or radio receive function * @p Parameters of environment */ void bs_receive(error_t (*recv_func)(message_t*, uint32_t, am_id_t), bs_params_t* p) { message_t m; BlinkToRadioMsg_t* btrpkt; for(;;) { if( (*(recv_func))(&m, 0, AM_RECEIVE_FROM_ANY) == SUCCESS ) { btrpkt = (BlinkToRadioMsg_t*)radioGetPayload(&m, sizeof(BlinkToRadioMsg_t)); if( isValidMsgID(btrpkt->msgID) ) { //only accept if new msgID messageID = btrpkt->msgID; //save newest msgID if(isValidDestination(btrpkt->destMask)){ //check if current mote is addressed setLeds(btrpkt->ledID); } mutex_lock( &(p->mutex) ); while( enqueueMsg(p, &m) == FAIL ) condvar_wait( &(p->condvar), &(p->mutex) ); mutex_unlock( &(p->mutex) ); condvar_signalAll( &(p->condvar) ); } } } }
int bitcui_start(bool withui) { int res; btcui->inuse = withui; btcui->lock = mutex_alloc(); btcui->cv = condvar_alloc(); btcui->blockProdIdx = -1; btcui->blockConsIdx = -1; if (btcui->inuse == 0) { return 0; } Log(LGPFX " starting ui thread.\n"); res = pthread_create(&btcui->tid, NULL, bitcui_main, NULL); ASSERT(res == 0); mutex_lock(btcui->lock); condvar_wait(btcui->cv, btcui->lock); mutex_unlock(btcui->lock); return res; }
/** Allocate frames of physical memory. * * @param count Number of continuous frames to allocate. * @param flags Flags for host zone selection and address processing. * @param constraint Indication of physical address bits that cannot be * set in the address of the first allocated frame. * @param pzone Preferred zone. * * @return Physical address of the allocated frame. * */ uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags, uintptr_t constraint, size_t *pzone) { ASSERT(count > 0); size_t hint = pzone ? (*pzone) : 0; pfn_t frame_constraint = ADDR2PFN(constraint); /* * If not told otherwise, we must first reserve the memory. */ if (!(flags & FRAME_NO_RESERVE)) reserve_force_alloc(count); loop: irq_spinlock_lock(&zones.lock, true); /* * First, find suitable frame zone. */ size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), frame_constraint, hint); /* * If no memory, reclaim some slab memory, * if it does not help, reclaim all. */ if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) { irq_spinlock_unlock(&zones.lock, true); size_t freed = slab_reclaim(0); irq_spinlock_lock(&zones.lock, true); if (freed > 0) znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), frame_constraint, hint); if (znum == (size_t) -1) { irq_spinlock_unlock(&zones.lock, true); freed = slab_reclaim(SLAB_RECLAIM_ALL); irq_spinlock_lock(&zones.lock, true); if (freed > 0) znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), frame_constraint, hint); } } if (znum == (size_t) -1) { if (flags & FRAME_ATOMIC) { irq_spinlock_unlock(&zones.lock, true); if (!(flags & FRAME_NO_RESERVE)) reserve_free(count); return 0; } size_t avail = frame_total_free_get_internal(); irq_spinlock_unlock(&zones.lock, true); if (!THREAD) panic("Cannot wait for %zu frames to become available " "(%zu available).", count, avail); /* * Sleep until some frames are available again. */ #ifdef CONFIG_DEBUG log(LF_OTHER, LVL_DEBUG, "Thread %" PRIu64 " waiting for %zu frames " "%zu available.", THREAD->tid, count, avail); #endif /* * Since the mem_avail_mtx is an active mutex, we need to * disable interrupts to prevent deadlock with TLB shootdown. */ ipl_t ipl = interrupts_disable(); mutex_lock(&mem_avail_mtx); if (mem_avail_req > 0) mem_avail_req = min(mem_avail_req, count); else mem_avail_req = count; size_t gen = mem_avail_gen; while (gen == mem_avail_gen) condvar_wait(&mem_avail_cv, &mem_avail_mtx); mutex_unlock(&mem_avail_mtx); interrupts_restore(ipl); #ifdef CONFIG_DEBUG log(LF_OTHER, LVL_DEBUG, "Thread %" PRIu64 " woken up.", THREAD->tid); #endif goto loop; } pfn_t pfn = zone_frame_alloc(&zones.info[znum], count, frame_constraint) + zones.info[znum].base; irq_spinlock_unlock(&zones.lock, true); if (pzone) *pzone = znum; return PFN2ADDR(pfn); }