static void * api_main_loop(void * itf) { rh_aout_api_itf self = (rh_aout_api_itf)itf; struct sles_api_instance * instance = (struct sles_api_instance *)itf; rh_aout_itf * array; int len; for(;;) { poll_cmd_pipe(self); process_cmd_pipe(self); if( bucket_lock( instance->aout_itf_bucket, (void***)&array, &len ) == 0 ) { int i; for(i=0; i<len; i++) (*(array[i]))->update(array[i]); bucket_unlock( instance->aout_itf_bucket ); } } return NULL; }
static int recv_consumed_buffer_cmd(rh_aout_api_itf self, rh_asmp_itf asmp_itf) { struct sles_api_instance * api_instance = (struct sles_api_instance *)self; int len; rh_aout_itf * array; int e = 0; if( bucket_lock( api_instance->aout_itf_bucket, (void***)&array, &len ) == 0 ) { int i; for(i=0; i<len; i++) { rh_asmp_itf audio_sample; rh_aout_itf audio_channel = array[i]; if( (*audio_channel)->get_sample(audio_channel, &audio_sample) == 0 ) { if( audio_sample == asmp_itf ) { struct aout_instance * channel_instance = (struct aout_instance *)audio_channel; e = buffer_queue_return_drain_buffer( &channel_instance->bq ); break; } } } bucket_unlock( api_instance->aout_itf_bucket ); } return e; }
static int stop(rh_aout_api_itf self, rh_asmp_itf asmp_itf) { struct sles_api_instance * api_instance = (struct sles_api_instance *)self; int len; rh_aout_itf * array; int e = 0; if( bucket_lock( api_instance->aout_itf_bucket, (void***)&array, &len ) == 0 ) { int i; for(i=0; i<len; i++) { rh_asmp_itf audio_sample; rh_aout_itf audio_channel = array[i]; if( (*audio_channel)->get_sample(audio_channel, &audio_sample) == 0 ) { if( audio_sample == asmp_itf ) { e = (*audio_channel)->stop(audio_channel); (*audio_channel)->set_sample(audio_channel, NULL); break; } } } bucket_unlock( api_instance->aout_itf_bucket ); } return e; }
/* * heap_get_bestfit_block -- * extracts a memory block of equal size index */ int heap_get_bestfit_block(PMEMobjpool *pop, struct bucket *b, struct memory_block *m) { if (bucket_lock(b) != 0) return EAGAIN; int i; uint32_t units = m->size_idx; for (i = 0; i < MAX_BUCKET_REFILL; ++i) { if (bucket_get_rm_block_bestfit(b, m) != 0) heap_ensure_bucket_filled(pop, b, 1); else break; } if (i == MAX_BUCKET_REFILL) { bucket_unlock(b); return ENOMEM; } if (units != m->size_idx) heap_recycle_block(pop, b, m, units); bucket_unlock(b); return 0; }
/* * heap_get_exact_block -- * extracts exactly this memory block and cuts it accordingly */ int heap_get_exact_block(PMEMobjpool *pop, struct bucket *b, struct memory_block *m, uint32_t units) { if (bucket_lock(b) != 0) return EAGAIN; if (bucket_get_rm_block_exact(b, *m) != 0) return ENOMEM; if (units != m->size_idx) heap_recycle_block(pop, b, m, units); bucket_unlock(b); return 0; }
static int close_all_channels(rh_aout_api_itf self) { struct sles_api_instance * api_instance = (struct sles_api_instance *)self; int len; rh_aout_itf * array; if( bucket_lock( api_instance->aout_itf_bucket, (void***)&array, &len ) == 0 ) { int i; for(i=0; i<len; i++) if(array[i]) (*(array[i]))->close(&array[i]); bucket_unlock( api_instance->aout_itf_bucket ); } return 0; }
static int _play(rh_aout_api_itf self, rh_asmp_itf asmp_itf, int loop_flag) { struct sles_api_instance * api_instance = (struct sles_api_instance *)self; int len; rh_aout_itf * array; int e = 0; for(;;) { int found = 0; if( bucket_lock( api_instance->aout_itf_bucket, (void***)&array, &len ) == 0 ) { int i; // is this sample already assigned to a channel? try to find its channel. for(i=0; i<len; i++) { rh_asmp_itf audio_sample; rh_aout_itf audio_channel = array[i]; if( (*audio_channel)->get_sample(audio_channel, &audio_sample) == 0 ) { if( audio_sample == asmp_itf ) { found = 1; if(loop_flag) e = (*audio_channel)->loop(audio_channel); else e = (*audio_channel)->play(audio_channel); break; } } } if(!found) { // sample not yet assigned to a channel, find and empty one and assign it. for(i=0; i<len; i++) { rh_asmp_itf audio_sample; rh_aout_itf audio_channel = array[i]; if( (*audio_channel)->get_sample(audio_channel, &audio_sample) == 0 ) { if( audio_sample == NULL ) { found = 1; (*audio_channel)->set_sample(audio_channel, asmp_itf); (*audio_channel)->open( audio_channel, (*asmp_itf)->channels(asmp_itf), (*asmp_itf)->samplerate(asmp_itf), (*asmp_itf)->samplesize(asmp_itf) ); if(loop_flag) e = (*audio_channel)->loop(audio_channel); else e = (*audio_channel)->play(audio_channel); break; } } } } bucket_unlock( api_instance->aout_itf_bucket ); } if(!found) { // no empty channels available, create a new channel and try again. if((e = add_channels(self, 1)) != 0) break; } else break; } return e; }
/* * heap_degrade_run_if_empty -- makes a chunk out of an empty run */ int heap_degrade_run_if_empty(PMEMobjpool *pop, struct bucket *b, struct memory_block m) { struct zone *z = &pop->heap->layout->zones[m.zone_id]; struct chunk_header *hdr = &z->chunk_headers[m.chunk_id]; ASSERT(hdr->type == CHUNK_TYPE_RUN); struct chunk_run *run = (struct chunk_run *)&z->chunks[m.chunk_id]; int err = 0; if ((err = pthread_mutex_lock(heap_get_run_lock(pop, m))) != 0) return err; int i; for (i = 0; i < bucket_bitmap_nval(b) - 1; ++i) if (run->bitmap[i] != 0) goto out; if (run->bitmap[i] != bucket_bitmap_lastval(b)) goto out; m.block_off = 0; m.size_idx = RUN_UNIT_MAX; uint32_t size_idx_sum = 0; while (size_idx_sum != bucket_bitmap_nallocs(b)) { if (bucket_get_rm_block_exact(b, m) != 0) { ERR("persistent and volatile state mismatched"); ASSERT(0); } size_idx_sum += m.size_idx; m.block_off += RUN_UNIT_MAX; if (m.block_off + RUN_UNIT_MAX > bucket_bitmap_nallocs(b)) m.size_idx = bucket_bitmap_nallocs(b) - m.block_off; else m.size_idx = RUN_UNIT_MAX; } struct bucket *defb = pop->heap->buckets[DEFAULT_BUCKET]; if ((err = bucket_lock(defb)) != 0) { ERR("Failed to lock default bucket"); ASSERT(0); } m.block_off = 0; m.size_idx = 1; heap_chunk_init(pop, hdr, CHUNK_TYPE_FREE, m.size_idx); uint64_t *mhdr; uint64_t op_result; struct memory_block fm = heap_free_block(pop, defb, m, &mhdr, &op_result); VALGRIND_ADD_TO_TX(mhdr, sizeof (*mhdr)); *mhdr = op_result; VALGRIND_REMOVE_FROM_TX(mhdr, sizeof (*mhdr)); pop->persist(mhdr, sizeof (*mhdr)); if ((err = bucket_insert_block(defb, fm)) != 0) { ERR("Failed to update heap volatile state"); } bucket_unlock(defb); out: if (pthread_mutex_unlock(heap_get_run_lock(pop, m)) != 0) { ERR("Failed to release run lock"); ASSERT(0); } return err; }