static void wq_init(workqueue_t *wq, int nfiles) { int throttle, nslots, i; if (getenv("CTFMERGE_MAX_SLOTS")) nslots = atoi(getenv("CTFMERGE_MAX_SLOTS")); else nslots = MERGE_PHASE1_MAX_SLOTS; if (getenv("CTFMERGE_PHASE1_BATCH_SIZE")) wq->wq_maxbatchsz = atoi(getenv("CTFMERGE_PHASE1_BATCH_SIZE")); else wq->wq_maxbatchsz = MERGE_PHASE1_BATCH_SIZE; nslots = MIN(nslots, (nfiles + wq->wq_maxbatchsz - 1) / wq->wq_maxbatchsz); wq->wq_wip = xcalloc(sizeof (wip_t) * nslots); wq->wq_nwipslots = nslots; wq->wq_nthreads = MIN(sysconf(_SC_NPROCESSORS_ONLN) * 3 / 2, nslots); wq->wq_thread = xmalloc(sizeof (pthread_t) * wq->wq_nthreads); if (getenv("CTFMERGE_INPUT_THROTTLE")) throttle = atoi(getenv("CTFMERGE_INPUT_THROTTLE")); else throttle = MERGE_INPUT_THROTTLE_LEN; wq->wq_ithrottle = throttle * wq->wq_nthreads; debug(1, "Using %d slots, %d threads\n", wq->wq_nwipslots, wq->wq_nthreads); wq->wq_next_batchid = 0; for (i = 0; i < nslots; i++) { pthread_mutex_init(&wq->wq_wip[i].wip_lock, NULL); wq->wq_wip[i].wip_batchid = wq->wq_next_batchid++; } pthread_mutex_init(&wq->wq_queue_lock, NULL); wq->wq_queue = fifo_new(); pthread_cond_init(&wq->wq_work_avail, NULL); pthread_cond_init(&wq->wq_work_removed, NULL); wq->wq_ninqueue = nfiles; wq->wq_nextpownum = 0; pthread_mutex_init(&wq->wq_donequeue_lock, NULL); wq->wq_donequeue = fifo_new(); wq->wq_lastdonebatch = -1; pthread_cond_init(&wq->wq_done_cv, NULL); pthread_cond_init(&wq->wq_alldone_cv, NULL); wq->wq_alldone = 0; barrier_init(&wq->wq_bar1, wq->wq_nthreads); barrier_init(&wq->wq_bar2, wq->wq_nthreads); wq->wq_nomorefiles = 0; }
void init_ev() { main_base = event_base_new(); dns_base = evdns_base_new(main_base, 1); ready_sites_fifo = fifo_new(NULL); wait_sites_fifo = fifo_new(NULL); /* set timer */ struct event *ev; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 50000; /* 30 milliseconds */ ev = event_new(main_base, -1, EV_TIMEOUT | EV_PERSIST, timer_cb, NULL); event_add(ev, &tv); }
// in: linda_ud, key, ... // out: true|false int keepercall_send( lua_State* L) { keeper_fifo* fifo; int n = lua_gettop( L) - 2; push_table( L, 1); // ud key ... fifos // get the fifo associated to this key in this linda, create it if it doesn't exist lua_pushvalue( L, 2); // ud key ... fifos key lua_rawget( L, -2); // ud key ... fifos fifo if( lua_isnil( L, -1)) { lua_pop( L, 1); // ud key ... fifos fifo_new( L); // ud key ... fifos fifo lua_pushvalue( L, 2); // ud key ... fifos fifo key lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo lua_rawset( L, -4); // ud key ... fifos fifo } lua_remove( L, -2); // ud key ... fifo fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo->limit >= 0 && fifo->count + n > fifo->limit) { lua_settop( L, 0); // lua_pushboolean( L, 0); // false } else { fifo = prepare_fifo_access( L, -1); lua_replace( L, 2); // ud fifo ... fifo_push( L, fifo, n); // ud fifo lua_settop( L, 0); // lua_pushboolean( L, 1); // true } return 1; }
/* Add an operation to the queue for tile @index * Note: if an operation affects more than one tile, it must be added once per tile. * * Concurrency: This function is not thread-safe on the same @self instance. */ void operation_queue_add(OperationQueue *self, TileIndex index, OperationDataDrawDab *op) { while (!tile_map_contains(self->tile_map, index)) { #ifdef HEAVY_DEBUG operation_queue_resize(self, self->tile_map->size+1); #else operation_queue_resize(self, self->tile_map->size*2); #endif } Fifo **queue_pointer = (Fifo **)tile_map_get(self->tile_map, index); Fifo *op_queue = *queue_pointer; if (op_queue == NULL) { // Lazy initialization op_queue = fifo_new(); *queue_pointer = op_queue; } if (fifo_peek_first(op_queue) == NULL) { // Critical section, not thread-safe if (!(self->dirty_tiles_n < self->tile_map->size*2*self->tile_map->size*2)) { // Prune duplicate tiles that cause us to almost exceed max self->dirty_tiles_n = remove_duplicate_tiles(self->dirty_tiles, self->dirty_tiles_n); } assert(self->dirty_tiles_n < self->tile_map->size*2*self->tile_map->size*2); self->dirty_tiles[self->dirty_tiles_n++] = index; } fifo_push(op_queue, (void *)op); }
// in: linda_ud key n // out: true or nil int keepercall_limit( lua_State* L) { keeper_fifo* fifo; int limit = (int) lua_tointeger( L, 3); push_table( L, 1); // ud key n fifos lua_replace( L, 1); // fifos key n lua_pop( L, 1); // fifos key lua_pushvalue( L, -1); // fifos key key lua_rawget( L, -3); // fifos key fifo|nil fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) { // fifos key nil lua_pop( L, 1); // fifos key fifo_new( L); // fifos key fifo fifo = (keeper_fifo*) lua_touserdata( L, -1); lua_rawset( L, -3); // fifos } // remove any clutter on the stack lua_settop( L, 0); // return true if we decide that blocked threads waiting to write on that key should be awakened // this is the case if we detect the key was full but it is no longer the case if( ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit ) { lua_pushboolean( L, 1); } // set the new limit fifo->limit = limit; // return 0 or 1 value return lua_gettop( L); }
//in: linda_ud key [val] int keepercall_set( lua_State* L) { STACK_GROW( L, 6); // make sure we have a value on the stack if( lua_gettop( L) == 2) // ud key val? { lua_pushnil( L); // ud key nil } // retrieve fifos associated with the linda push_table( L, 1); // ud key val fifos lua_replace( L, 1); // fifos key val if( !lua_isnil( L, 3)) // set/replace contents stored at the specified key? { keeper_fifo* fifo; lua_pushvalue( L, -2); // fifos key val key lua_rawget( L, 1); // fifos key val fifo|nil fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) // might be NULL if we set a nonexistent key to nil { lua_pop( L, 1); // fifos key val fifo_new( L); // fifos key val fifo lua_pushvalue( L, 2); // fifos key val fifo key lua_pushvalue( L, -2); // fifos key val fifo key fifo lua_rawset( L, 1); // fifos key val fifo } else // the fifo exists, we just want to clear its contents { // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! lua_newtable( L); // fifos key val fifo {} lua_setuservalue( L, -2); // fifos key val fifo fifo->first = 1; fifo->count = 0; } fifo = prepare_fifo_access( L, -1); lua_insert( L, -2); // fifos key fifo val fifo_push( L, fifo, 1); // fifos key fifo } else // val == nil // fifos key nil { keeper_fifo* fifo; lua_pop( L, 1); // fifos key lua_rawget( L, 1); // fifos fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo != NULL) // might be NULL if we set a nonexistent key to nil { lua_newtable( L); // fifos fifo {} lua_setuservalue( L, -2); // fifos fifo fifo->first = 1; fifo->count = 0; } } return 0; }
static bool init_thread(ffemu_t *handle) { handle->lock = slock_new(); handle->cond_lock = slock_new(); handle->cond = scond_new(); handle->audio_fifo = fifo_new(32000 * sizeof(int16_t) * handle->params.channels * MAX_FRAMES / 60); handle->attr_fifo = fifo_new(sizeof(struct ffemu_video_data) * MAX_FRAMES); handle->video_fifo = fifo_new(handle->params.fb_width * handle->params.fb_height * handle->video.pix_size * MAX_FRAMES); handle->alive = true; handle->can_sleep = true; handle->thread = sthread_create(ffemu_thread, handle); assert(handle->lock && handle->cond_lock && handle->cond && handle->audio_fifo && handle->attr_fifo && handle->video_fifo && handle->thread); return true; }
static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency) { (void)device; if (SDL_WasInit(0) == 0) { if (SDL_Init(SDL_INIT_AUDIO) < 0) return NULL; } else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) return NULL; sdl_audio_t *sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl)); if (!sdl) return NULL; // We have to buffer up some data ourselves, so we let SDL carry approx half of the latency. SDL double buffers audio and we do as well. int frames = find_num_frames(rate, latency / 4); SDL_AudioSpec spec = {0}; spec.freq = rate; spec.format = AUDIO_S16SYS; spec.channels = 2; spec.samples = frames; // This is in audio frames, not samples ... :( spec.callback = sdl_audio_cb; spec.userdata = sdl; SDL_AudioSpec out; if (SDL_OpenAudio(&spec, &out) < 0) { RARCH_ERR("Failed to open SDL audio: %s\n", SDL_GetError()); free(sdl); return 0; } g_settings.audio.out_rate = out.freq; sdl->lock = slock_new(); sdl->cond = scond_new(); RARCH_LOG("SDL audio: Requested %u ms latency, got %d ms\n", latency, (int)(out.samples * 4 * 1000 / g_settings.audio.out_rate)); // Create a buffer twice as big as needed and prefill the buffer. size_t bufsize = out.samples * 4 * sizeof(int16_t); void *tmp = calloc(1, bufsize); sdl->buffer = fifo_new(bufsize); if (tmp) { fifo_write(sdl->buffer, tmp, bufsize); free(tmp); } SDL_PauseAudio(0); return sdl; }
static cell_audio_handle_t audioport_init(const struct cell_audio_params *params) { init_audioport(); audioport_t *handle = calloc(1, sizeof(*handle)); CellAudioPortParam port_params = { .nChannel = params->channels, .nBlock = 8, .attr = 0 }; handle->channels = params->channels; handle->sample_cb = params->sample_cb; handle->userdata = params->userdata; handle->buffer = fifo_new(params->buffer_size ? params->buffer_size : 4096); if (params->samplerate != 48000) { handle->re = resampler_new(resampler_cb, 48000.0 / params->samplerate, params->channels, handle); } sys_lwmutex_attribute_t attr; sys_lwmutex_attribute_t attr2; sys_lwmutex_attribute_t cond_attr; sys_lwmutex_attribute_initialize(attr); sys_lwmutex_create(&handle->lock, &attr); sys_lwmutex_attribute_initialize(attr2); sys_lwmutex_create(&handle->cond_lock, &attr2); sys_lwcond_attribute_initialize(cond_attr); sys_lwcond_create(&handle->cond, &handle->cond_lock, &cond_attr); cellAudioPortOpen(&port_params, &handle->audio_port); cellAudioPortStart(handle->audio_port); pthread_create(&handle->thread, NULL, event_loop, handle); return handle; } static void audioport_pause(cell_audio_handle_t handle) { audioport_t *port = handle; port->is_paused = 1; cellAudioPortStop(port->audio_port); }
int main(int argc, char *argv[]) { random_fd = open("/dev/urandom", O_RDONLY); if (random_fd < 0) { perror("Could not open /dev/urandom"); return random_fd; } fifo = fifo_new(16); if (!fifo) { perror("Could not create fifo"); close(random_fd); return -1; } struct producer ps[] = { {.start=5, .end=60}, {.start=50, .end=125},
static void *rs_init(const char *device, unsigned rate, unsigned latency) { int channels, format; rsd_t *rsd = (rsd_t*)calloc(1, sizeof(rsd_t)); if (!rsd) return NULL; rsound_t *rd; if (rsd_init(&rd) < 0) { free(rsd); return NULL; } rsd->cond_lock = slock_new(); rsd->cond = scond_new(); rsd->buffer = fifo_new(1024 * 4); channels = 2; format = RSD_S16_NE; rsd_set_param(rd, RSD_CHANNELS, &channels); rsd_set_param(rd, RSD_SAMPLERATE, &rate); rsd_set_param(rd, RSD_LATENCY, &latency); if (device) rsd_set_param(rd, RSD_HOST, (void*)device); rsd_set_param(rd, RSD_FORMAT, &format); rsd_set_callback(rd, rsound_audio_cb, err_cb, 256, rsd); if (rsd_start(rd) < 0) { free(rsd); rsd_free(rd); return NULL; } rsd->rd = rd; return rsd; }
static void test2() { fifo_t *f1 = fifo_new(1024 * 4); int i; void *p; for (i = 0; i < 1023; i++) { p = fifo_alloc(f1, 13); assert(p); *(int *)p = i; fifo_put(f1, p, 13); p = fifo_get(f1, 13); assert(p); assert(*(int *)p == i); fifo_end(f1, p, 13); } assert(fifo_empty(f1)); }
// in: linda_ud key n // out: nothing int keepercall_limit( lua_State* L) { keeper_fifo* fifo; int limit = (int) lua_tointeger( L, 3); push_table( L, 1); // ud key n fifos lua_replace( L, 1); // fifos key n lua_pop( L, 1); // fifos key lua_pushvalue( L, -1); // fifos key key lua_rawget( L, -3); // fifos key fifo fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) { lua_pop( L, 1); // fifos key fifo_new( L); // fifos key fifo fifo = (keeper_fifo*) lua_touserdata( L, -1); lua_rawset( L, -3); // fifos } fifo->limit = limit; return 0; }
task task_new(void) { task p; int err; if ((p = calloc(1, sizeof *p)) == NULL) return NULL; if ((err = pthread_rwlock_init(&p->sublock, NULL)) != 0) { free(p); return NULL; } if ((p->q = fifo_new(METAL_TASK_QUEUE_SIZE)) == NULL) { free(p); return NULL; } p->name[0] = '\0'; p->tid = 0; // system tid. Hmm... -1 is not allowed. return p; }
static void test3() { fifo_t *f1 = fifo_new(1024 * 4); int i; void *p; for (i = 0; i < 1023; i++) { p = fifo_alloc(f1, 13); assert(p); *(int *)p = i; fifo_put(f1, p, 13); p = fifo_extend(f1, p, 13, 13 * 2); assert(p); fifo_put(f1, p, 26); printf("%u %u\n", f1->pt, f1->gt); p = fifo_get(f1, 26); assert(p); assert(*(int *)p == i); fifo_end(f1, p, 26); } assert(fifo_empty(f1)); }
bool initialize_packet_slinger() { if (slinger_initialized) return true; initialize_slinger_frame_lookup(); e_memset(link_state, 0, 2 * sizeof(slinger_link_state_t)); link_state[slinger_link_highrate].link_enum = slinger_link_highrate; link_state[slinger_link_biphase].link_enum = slinger_link_biphase; link_state[slinger_link_highrate].downlink_pq = create_pq(SLINGER_MAX_PRIORITY); link_state[slinger_link_biphase].downlink_pq = create_pq(SLINGER_MAX_PRIORITY); link_state[slinger_link_highrate].resend_fifo = fifo_new(); link_state[slinger_link_biphase].resend_fifo = fifo_new(); link_state[slinger_link_highrate].control_fifo_queue = fifo_new(); link_state[slinger_link_highrate].downlink_fifo = fifo_new(); link_state[slinger_link_biphase].control_fifo_queue = fifo_new(); link_state[slinger_link_biphase].downlink_fifo = fifo_new(); link_state[slinger_link_highrate].fifo_pause_us = 50000; link_state[slinger_link_biphase].fifo_pause_us = 9984; link_state[slinger_link_highrate].device = bstrdup(err, "/dev/ttyHighRate"); link_state[slinger_link_biphase].device = bstrdup(err, "/dev/bi0_pci"); link_state[slinger_link_biphase].bps = 1000000; /// Initialize the downlink rate for TDRSS Omni-directional set_slinger_dl_rate(CommandData.packet_slinger.downlink_rate_bps); initialize_slinger_tables(); if (!slinger_xml_load_preferences("/data/etc/packetslinger.xml")) return false; slinger_initialized = true; return true; }
static void *alsa_thread_init(const char *device, unsigned rate, unsigned latency) { snd_pcm_uframes_t buffer_size; snd_pcm_format_t format; snd_pcm_hw_params_t *params = NULL; snd_pcm_sw_params_t *sw_params = NULL; const char *alsa_dev = device ? device : "default"; unsigned latency_usec = latency * 1000 / 2; unsigned channels = 2; unsigned periods = 4; alsa_thread_t *alsa = (alsa_thread_t*) calloc(1, sizeof(alsa_thread_t)); if (!alsa) return NULL; TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0)); TRY_ALSA(snd_pcm_hw_params_malloc(¶ms)); alsa->has_float = alsathread_find_float_format(alsa->pcm, params); format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16; TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params)); TRY_ALSA(snd_pcm_hw_params_set_access( alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED)); TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format)); TRY_ALSA(snd_pcm_hw_params_set_channels(alsa->pcm, params, channels)); TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0)); TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near( alsa->pcm, params, &latency_usec, NULL)); TRY_ALSA(snd_pcm_hw_params_set_periods_near( alsa->pcm, params, &periods, NULL)); TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params)); /* Shouldn't have to bother with this, * but some drivers are apparently broken. */ if (snd_pcm_hw_params_get_period_size(params, &alsa->period_frames, NULL)) snd_pcm_hw_params_get_period_size_min( params, &alsa->period_frames, NULL); RARCH_LOG("ALSA: Period size: %d frames\n", (int)alsa->period_frames); if (snd_pcm_hw_params_get_buffer_size(params, &buffer_size)) snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size); RARCH_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size); alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size); alsa->period_size = snd_pcm_frames_to_bytes(alsa->pcm, alsa->period_frames); TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params)); TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params)); TRY_ALSA(snd_pcm_sw_params_set_start_threshold( alsa->pcm, sw_params, buffer_size / 2)); TRY_ALSA(snd_pcm_sw_params(alsa->pcm, sw_params)); snd_pcm_hw_params_free(params); snd_pcm_sw_params_free(sw_params); alsa->fifo_lock = slock_new(); alsa->cond_lock = slock_new(); alsa->cond = scond_new(); alsa->buffer = fifo_new(alsa->buffer_size); if (!alsa->fifo_lock || !alsa->cond_lock || !alsa->cond || !alsa->buffer) goto error; alsa->worker_thread = sthread_create(alsa_worker_thread, alsa); if (!alsa->worker_thread) { RARCH_ERR("error initializing worker thread"); goto error; } return alsa; error: RARCH_ERR("ALSA: Failed to initialize...\n"); if (params) snd_pcm_hw_params_free(params); if (sw_params) snd_pcm_sw_params_free(sw_params); alsa_thread_free(alsa); return NULL; }
//in: linda_ud key [[val] ...] //out: true or nil int keepercall_set( lua_State* L) { bool_t should_wake_writers = FALSE; STACK_GROW( L, 6); // retrieve fifos associated with the linda push_table( L, 1); // ud key [val [, ...]] fifos lua_replace( L, 1); // fifos key [val [, ...]] // make sure we have a value on the stack if( lua_gettop( L) == 2) // fifos key { keeper_fifo* fifo; lua_pushvalue( L, -1); // fifos key key lua_rawget( L, 1); // fifos key fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo != NULL) // might be NULL if we set a nonexistent key to nil { // fifos key fifo if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it { lua_pop( L, 1); // fifos key lua_pushnil( L); // fifos key nil lua_rawset( L, -3); // fifos } else { // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); lua_remove( L, -2); // fifos fifo lua_newtable( L); // fifos fifo {} lua_setuservalue( L, -2); // fifos fifo fifo->first = 1; fifo->count = 0; } } } else // set/replace contents stored at the specified key? { int count = lua_gettop( L) - 2; // number of items we want to store keeper_fifo* fifo; // fifos key [val [, ...]] lua_pushvalue( L, 2); // fifos key [val [, ...]] key lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) // can be NULL if we store a value at a new key { // fifos key [val [, ...]] nil // no need to wake writers in that case, because a writer can't wait on an inexistent key lua_pop( L, 1); // fifos key [val [, ...]] fifo_new( L); // fifos key [val [, ...]] fifo lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo lua_rawset( L, 1); // fifos key [val [, ...]] fifo } else // the fifo exists, we just want to update its contents { // fifos key [val [, ...]] fifo // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! lua_newtable( L); // fifos key [val [, ...]] fifo {} lua_setuservalue( L, -2); // fifos key [val [, ...]] fifo fifo->first = 1; fifo->count = 0; } fifo = prepare_fifo_access( L, -1); // move the fifo below the values we want to store lua_insert( L, 3); // fifos key fifo [val [, ...]] fifo_push( L, fifo, count); // fifos key fifo } return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; }
static void *ps3_audio_init(const char *device, unsigned rate, unsigned latency) { CellAudioPortParam params; ps3_audio_t *data = NULL; (void)latency; (void)device; (void)rate; data = calloc(1, sizeof(*data)); if (!data) return NULL; cellAudioInit(); params.numChannels = AUDIO_CHANNELS; params.numBlocks = AUDIO_BLOCKS; #if 0 #ifdef HAVE_HEADSET if(global->console.sound.mode == SOUND_MODE_HEADSET) params.param_attrib = CELL_AUDIO_PORTATTR_OUT_SECONDARY; else #endif #endif params.param_attrib = 0; if (cellAudioPortOpen(¶ms, &data->audio_port) != CELL_OK) { cellAudioQuit(); free(data); return NULL; } data->buffer = fifo_new(CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS * AUDIO_BLOCKS * sizeof(float)); #ifdef __PSL1GHT__ sys_lwmutex_attr_t lock_attr = {SYS_LWMUTEX_ATTR_PROTOCOL, SYS_LWMUTEX_ATTR_RECURSIVE, "\0"}; sys_lwmutex_attr_t cond_lock_attr = {SYS_LWMUTEX_ATTR_PROTOCOL, SYS_LWMUTEX_ATTR_RECURSIVE, "\0"}; sys_lwcond_attribute_t cond_attr = {"\0"}; #else sys_lwmutex_attribute_t lock_attr; sys_lwmutex_attribute_t cond_lock_attr; sys_lwcond_attribute_t cond_attr; sys_lwmutex_attribute_initialize(lock_attr); sys_lwmutex_attribute_initialize(cond_lock_attr); sys_lwcond_attribute_initialize(cond_attr); #endif sys_lwmutex_create(&data->lock, &lock_attr); sys_lwmutex_create(&data->cond_lock, &cond_lock_attr); sys_lwcond_create(&data->cond, &data->cond_lock, &cond_attr); cellAudioPortStart(data->audio_port); data->started = true; sys_ppu_thread_create(&data->thread, event_loop, #ifdef __PSL1GHT__ data, #else (uint64_t)data, #endif 1500, 0x1000, SYS_PPU_THREAD_CREATE_JOINABLE, (char*)"sound"); return data; }
int main(void) { fifo f; size_t i, nelem; status_t rc; char dummydata[1000] = "Hello"; clock_t stop, start; double duration; nelem = 1*1000*1000; f = fifo_new(nelem); #if 1 /* Fill the fifo completely */ start = clock(); for (i = 0; i < nelem; i++) { rc = fifo_add(f, dummydata); assert(rc != 0); } stop = clock(); duration = (stop - start) * 1.0 / CLOCKS_PER_SEC; printf("%s: Added %lu elements in %f seconds\n", __FILE__, (unsigned long)nelem, duration); assert(fifo_nelem(f) == nelem); /* Test fifo_peek() */ for (i = 0; i < nelem; i++) { const char *s = fifo_peek(f, i); /* Stupid workaround for gcc 4.0.2 optimization in conjunction with assert() */ int xi; xi = (s != NULL); assert(xi); xi = (strcmp(s, dummydata) == 0); assert(xi); } /* Add a new one, this should fail */ assert(fifo_add(f, dummydata) == 0); /* Now read two and then add one. That should be possible */ assert(fifo_get(f)); assert(fifo_get(f)); assert(fifo_nelem(f) == nelem - 2); assert(fifo_add(f, dummydata) != 0); assert(fifo_nelem(f) == nelem - 1); /* Test fifo_peek() */ for (i = 0; i < fifo_nelem(f); i++) { const char *s = fifo_peek(f, i); int xi; xi = (s != NULL); assert(xi); xi = (strcmp(s, dummydata) == 0); assert(xi); } /* The first should be OK, the next must fail */ assert(fifo_add(f, dummydata) != 0); assert(fifo_nelem(f) == nelem); assert(fifo_add(f, dummydata) == 0); assert(fifo_nelem(f) == nelem); start = clock(); for (i = 0; i < nelem; i++) { char *x = fifo_get(f); (void)x; } stop = clock(); duration = (stop - start) * 1.0 / CLOCKS_PER_SEC; printf("%s: Got %lu elements in %f seconds\n", __FILE__, (unsigned long)nelem, duration); #endif /* Now check signalling and wait for data. * We start two threads, a reader and a writer. * The writer writes n times to the fifo and the reader * prints the data. * This thread joins the writer and calls fifo_wake() when * the writer is done, to stop the reader thread in a controlled * manner. */ { pthread_t w, r; pthread_create(&r, NULL, reader, f); pthread_create(&w, NULL, writer, f); pthread_join(w, NULL); if (!fifo_wake(f)) exit(EXIT_FAILURE); pthread_join(r, NULL); } fifo_free(f, free); return 0; }
static void *coreaudio_init(const char *device, unsigned rate, unsigned latency) { size_t fifo_size; UInt32 i_size; AudioStreamBasicDescription real_desc; #ifdef OSX_PPC Component comp; #else AudioComponent comp; #endif #ifndef TARGET_OS_IPHONE AudioChannelLayout layout = {0}; #endif AURenderCallbackStruct cb = {0}; AudioStreamBasicDescription stream_desc = {0}; bool component_unavailable = false; static bool session_initialized = false; coreaudio_t *dev = NULL; #ifdef OSX_PPC ComponentDescription desc = {0}; #else AudioComponentDescription desc = {0}; #endif settings_t *settings = config_get_ptr(); (void)session_initialized; (void)device; dev = (coreaudio_t*)calloc(1, sizeof(*dev)); if (!dev) return NULL; dev->lock = slock_new(); dev->cond = scond_new(); #if TARGET_OS_IPHONE if (!session_initialized) { session_initialized = true; AudioSessionInitialize(0, 0, coreaudio_interrupt_listener, 0); AudioSessionSetActive(true); } #endif /* Create AudioComponent */ desc.componentType = kAudioUnitType_Output; #if TARGET_OS_IPHONE desc.componentSubType = kAudioUnitSubType_RemoteIO; #else desc.componentSubType = kAudioUnitSubType_HALOutput; #endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; #ifdef OSX_PPC comp = FindNextComponent(NULL, &desc); #else comp = AudioComponentFindNext(NULL, &desc); #endif if (comp == NULL) goto error; #ifdef OSX_PPC component_unavailable = (OpenAComponent(comp, &dev->dev) != noErr); #else component_unavailable = (AudioComponentInstanceNew(comp, &dev->dev) != noErr); #endif if (component_unavailable) goto error; #if !TARGET_OS_IPHONE if (device) choose_output_device(dev, device); #endif dev->dev_alive = true; /* Set audio format */ stream_desc.mSampleRate = rate; stream_desc.mBitsPerChannel = sizeof(float) * CHAR_BIT; stream_desc.mChannelsPerFrame = 2; stream_desc.mBytesPerPacket = 2 * sizeof(float); stream_desc.mBytesPerFrame = 2 * sizeof(float); stream_desc.mFramesPerPacket = 1; stream_desc.mFormatID = kAudioFormatLinearPCM; stream_desc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | (is_little_endian() ? 0 : kAudioFormatFlagIsBigEndian); if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &stream_desc, sizeof(stream_desc)) != noErr) goto error; /* Check returned audio format. */ i_size = sizeof(real_desc); if (AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &real_desc, &i_size) != noErr) goto error; if (real_desc.mChannelsPerFrame != stream_desc.mChannelsPerFrame) goto error; if (real_desc.mBitsPerChannel != stream_desc.mBitsPerChannel) goto error; if (real_desc.mFormatFlags != stream_desc.mFormatFlags) goto error; if (real_desc.mFormatID != stream_desc.mFormatID) goto error; RARCH_LOG("[CoreAudio]: Using output sample rate of %.1f Hz\n", (float)real_desc.mSampleRate); settings->audio.out_rate = real_desc.mSampleRate; /* Set channel layout (fails on iOS). */ #ifndef TARGET_OS_IPHONE layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof(layout)) != noErr) goto error; #endif /* Set callbacks and finish up. */ cb.inputProc = audio_write_cb; cb.inputProcRefCon = dev; if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &cb, sizeof(cb)) != noErr) goto error; if (AudioUnitInitialize(dev->dev) != noErr) goto error; fifo_size = (latency * settings->audio.out_rate) / 1000; fifo_size *= 2 * sizeof(float); dev->buffer_size = fifo_size; dev->buffer = fifo_new(fifo_size); if (!dev->buffer) goto error; RARCH_LOG("[CoreAudio]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)fifo_size, latency); if (AudioOutputUnitStart(dev->dev) != noErr) goto error; return dev; error: RARCH_ERR("[CoreAudio]: Failed to initialize driver ...\n"); coreaudio_free(dev); return NULL; }
static void *dsound_init(const char *device, unsigned rate, unsigned latency) { WAVEFORMATEX wfx = {0}; DSBUFFERDESC bufdesc = {0}; struct dsound_dev dev = {0}; dsound_t *ds = (dsound_t*)calloc(1, sizeof(*ds)); if (!ds) goto error; InitializeCriticalSection(&ds->crit); if (device) dev.device = strtoul(device, NULL, 0); RARCH_LOG("DirectSound devices:\n"); #ifndef _XBOX DirectSoundEnumerate(enumerate_cb, &dev); #endif if (DirectSoundCreate(dev.guid, &ds->ds, NULL) != DS_OK) goto error; #ifndef _XBOX if (IDirectSound_SetCooperativeLevel(ds->ds, GetDesktopWindow(), DSSCL_PRIORITY) != DS_OK) goto error; #endif wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = rate; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2 * sizeof(int16_t); wfx.nAvgBytesPerSec = rate * 2 * sizeof(int16_t); ds->buffer_size = (latency * wfx.nAvgBytesPerSec) / 1000; ds->buffer_size /= CHUNK_SIZE; ds->buffer_size *= CHUNK_SIZE; if (ds->buffer_size < 4 * CHUNK_SIZE) ds->buffer_size = 4 * CHUNK_SIZE; RARCH_LOG("[DirectSound]: Setting buffer size of %u bytes\n", ds->buffer_size); RARCH_LOG("[DirectSound]: Latency = %u ms\n", (unsigned)((1000 * ds->buffer_size) / wfx.nAvgBytesPerSec)); bufdesc.dwSize = sizeof(DSBUFFERDESC); bufdesc.dwFlags = 0; #ifndef _XBOX bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; #endif bufdesc.dwBufferBytes = ds->buffer_size; bufdesc.lpwfxFormat = &wfx; ds->event = CreateEvent(NULL, false, false, NULL); if (!ds->event) goto error; ds->buffer = fifo_new(4 * 1024); if (!ds->buffer) goto error; if (IDirectSound_CreateSoundBuffer(ds->ds, &bufdesc, &ds->dsb, 0) != DS_OK) goto error; IDirectSoundBuffer_SetVolume(ds->dsb, DSBVOLUME_MAX); IDirectSoundBuffer_SetCurrentPosition(ds->dsb, 0); dsound_clear_buffer(ds); if (IDirectSoundBuffer_Play(ds->dsb, 0, 0, DSBPLAY_LOOPING) != DS_OK) goto error; if (!dsound_start_thread(ds)) goto error; return ds; error: RARCH_ERR("[DirectSound] Error occured in init.\n"); dsound_free(ds); return NULL; }
static int add_adapter(void *data, struct libusb_device *dev) { int rc; struct libusb_device_descriptor desc; const char *device_name = NULL; struct libusb_adapter *old_head = NULL; struct libusb_hid *hid = (struct libusb_hid*)data; struct libusb_adapter *adapter = (struct libusb_adapter*) calloc(1, sizeof(struct libusb_adapter)); if (!adapter) return -1; if (!hid) { free(adapter); RARCH_ERR("Allocation of adapter failed.\n"); return -1; } rc = libusb_get_device_descriptor(dev, &desc); if (rc != LIBUSB_SUCCESS) { RARCH_ERR("Error getting device descriptor.\n"); goto error; } adapter->device = dev; libusb_get_description(adapter->device, adapter); if (adapter->endpoint_in == 0) { RARCH_ERR("Could not find HID config for device.\n"); goto error; } rc = libusb_open (adapter->device, &adapter->handle); if (rc != LIBUSB_SUCCESS) { RARCH_ERR("Error opening device 0x%p (VID/PID: %04x:%04x).\n", (void*)adapter->device, desc.idVendor, desc.idProduct); goto error; } if (desc.iManufacturer) { libusb_get_string_descriptor_ascii(adapter->handle, desc.iManufacturer, adapter->manufacturer_name, sizeof(adapter->manufacturer_name)); #if 0 RARCH_ERR(" Adapter Manufacturer name: %s\n", adapter->manufacturer_name); #endif } if (desc.iProduct) { libusb_get_string_descriptor_ascii(adapter->handle, desc.iProduct, adapter->name, sizeof(adapter->name)); #if 0 RARCH_ERR(" Adapter name: %s\n", adapter->name); #endif } device_name = (const char*)adapter->name; if (string_is_empty((const char*)adapter->name)) goto error; adapter->send_control_lock = slock_new(); adapter->send_control_buffer = fifo_new(4096); if (!adapter->send_control_lock || !adapter->send_control_buffer) { RARCH_ERR("Error creating send control buffer.\n"); goto error; } adapter->slot = pad_connection_pad_init(hid->slots, device_name, desc.idVendor, desc.idProduct, adapter, &libusb_hid_device_send_control); if (adapter->slot == -1) goto error; if (!pad_connection_has_interface(hid->slots, adapter->slot)) { RARCH_ERR(" Interface not found (%s).\n", adapter->name); goto error; } RARCH_LOG("Interface found: [%s].\n", adapter->name); if (libusb_kernel_driver_active(adapter->handle, 0) == 1 && libusb_detach_kernel_driver(adapter->handle, 0)) { RARCH_ERR("Error detaching handle 0x%p from kernel.\n", adapter->handle); goto error; } rc = libusb_claim_interface(adapter->handle, adapter->interface_number); if (rc != LIBUSB_SUCCESS) { RARCH_ERR("Error claiming interface %d .\n", adapter->interface_number); goto error; } RARCH_LOG("Device 0x%p attached (VID/PID: %04x:%04x).\n", adapter->device, desc.idVendor, desc.idProduct); libusb_hid_device_add_autodetect(adapter->slot, device_name, libusb_hid.ident, desc.idVendor, desc.idProduct); adapter->hid = hid; adapter->thread = sthread_create(adapter_thread, adapter); if (!adapter->thread) { RARCH_ERR("Error initializing adapter thread.\n"); goto error; } old_head = adapters.next; adapters.next = adapter; adapter->next = old_head; return 0; error: if (adapter->thread) sthread_join(adapter->thread); if (adapter->send_control_lock) slock_free(adapter->send_control_lock); if (adapter->send_control_buffer) fifo_free(adapter->send_control_buffer); if (adapter) free(adapter); return -1; }
static int add_adapter(void *data, usb_device_entry *dev) { int rc; usb_devdesc desc; const char *device_name = NULL; struct wiiusb_adapter *old_head = NULL; struct wiiusb_hid *hid = (struct wiiusb_hid*)data; struct wiiusb_adapter *adapter = (struct wiiusb_adapter*) calloc(1, sizeof(struct wiiusb_adapter)); (void)rc; if (!adapter) return -1; if (!hid) { free(adapter); RARCH_ERR("Allocation of adapter failed.\n"); return -1; } if (USB_OpenDevice(dev->device_id, dev->vid, dev->pid, &adapter->handle) < 0) { RARCH_ERR("Error opening device 0x%p (VID/PID: %04x:%04x).\n", (void*)&adapter->device, dev->vid, dev->pid); free(adapter); return -1; } adapter->device = *dev; USB_GetDescriptors(adapter->handle, &desc); wiiusb_get_description(&adapter->device, adapter, &desc); if (adapter->endpoint_in == 0) { RARCH_ERR("Could not find HID config for device.\n"); goto error; } if (desc.iManufacturer) { USB_GetAsciiString(adapter->handle, desc.iManufacturer, 0, sizeof(adapter->manufacturer_name), adapter->manufacturer_name); #if 0 RARCH_ERR(" Adapter Manufacturer name: %s\n", adapter->manufacturer_name); #endif } if (desc.iProduct) { USB_GetAsciiString(adapter->handle, desc.iProduct, 0, sizeof(adapter->name), adapter->name); #if 0 RARCH_ERR(" Adapter name: %s\n", adapter->name); #endif } device_name = (const char *)adapter->name; adapter->send_control_lock = slock_new(); adapter->send_control_buffer = fifo_new(4096); if (!adapter->send_control_lock || !adapter->send_control_buffer) { RARCH_ERR("Error creating send control buffer.\n"); goto error; } adapter->slot = pad_connection_pad_init(hid->slots, device_name, desc.idVendor, desc.idProduct, adapter, &wiiusb_hid_device_send_control); if (adapter->slot == -1) goto error; if (!pad_connection_has_interface(hid->slots, adapter->slot)) { RARCH_ERR(" Interface not found (%s).\n", adapter->name); goto error; } RARCH_LOG("Interface found: [%s].\n", adapter->name); RARCH_LOG("Device 0x%p attached (VID/PID: %04x:%04x).\n", adapter->device, desc.idVendor, desc.idProduct); wiiusb_hid_device_add_autodetect(adapter->slot, device_name, wiiusb_hid.ident, desc.idVendor, desc.idProduct); adapter->hid = hid; adapter->thread = sthread_create(adapter_thread, adapter); if (!adapter->thread) { RARCH_ERR("Error initializing adapter thread.\n"); goto error; } adapter->data = memalign(32, 2048); old_head = adapters.next; adapters.next = adapter; adapter->next = old_head; USB_FreeDescriptors(&desc); USB_DeviceRemovalNotifyAsync(adapter->handle, wiiusb_hid_removalnotify_cb, (void *)hid); return 0; error: if (adapter->thread) sthread_join(adapter->thread); if (adapter->send_control_lock) slock_free(adapter->send_control_lock); if (adapter->send_control_buffer) fifo_free(adapter->send_control_buffer); if (adapter) free(adapter); USB_FreeDescriptors(&desc); USB_CloseDevice(&adapter->handle); return -1; }