static uint32_t resampler_cb(void *userdata, float **data) { audioport_t *port = userdata; uint32_t has_read = 0; if (port->sample_cb) has_read = port->sample_cb(port->re_pull_buffer, CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t), port->userdata); else { has_read = CELL_AUDIO_BLOCK_SAMPLES * port->channels; sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT); uint32_t avail = fifo_read_avail(port->buffer); if (avail < CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t)) has_read = avail / sizeof(int16_t); fifo_read(port->buffer, port->re_pull_buffer, has_read * sizeof(int16_t)); sys_lwmutex_unlock(&port->lock); sys_lwcond_signal(&port->cond); } if (has_read < CELL_AUDIO_BLOCK_SAMPLES * port->channels * 2) memset(port->re_pull_buffer + has_read, 0, (CELL_AUDIO_BLOCK_SAMPLES * port->channels - has_read) * sizeof(int16_t)); audio_convert_s16_to_float_altivec(port->re_buffer, port->re_pull_buffer, CELL_AUDIO_BLOCK_SAMPLES * port->channels); *data = port->re_buffer; return CELL_AUDIO_BLOCK_SAMPLES; }
error_code sys_lwmutex_destroy(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex) { sysPrxForUser.trace("sys_lwmutex_destroy(lwmutex=*0x%x)", lwmutex); if (g_cfg.core.hle_lwmutex) { return sys_mutex_destroy(lwmutex->sleep_queue); } // check to prevent recursive locking in the next call if (lwmutex->vars.owner.load() == ppu.id) { return CELL_EBUSY; } // attempt to lock the mutex if (error_code res = sys_lwmutex_trylock(ppu, lwmutex)) { return res; } // call the syscall if (error_code res = _sys_lwmutex_destroy(lwmutex->sleep_queue)) { // unlock the mutex if failed sys_lwmutex_unlock(ppu, lwmutex); return res; } // deleting succeeded lwmutex->vars.owner.release(lwmutex_dead); return CELL_OK; }
static void event_loop(uint64_t data) #endif { float out_tmp[CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS] __attribute__((aligned(16))); sys_event_queue_t id; sys_ipc_key_t key; sys_event_t event; ps3_audio_t *aud = data; cellAudioCreateNotifyEventQueue(&id, &key); cellAudioSetNotifyEventQueue(key); while (!aud->quit_thread) { sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT); sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT); if (fifo_read_avail(aud->buffer) >= sizeof(out_tmp)) fifo_read(aud->buffer, out_tmp, sizeof(out_tmp)); else memset(out_tmp, 0, sizeof(out_tmp)); sys_lwmutex_unlock(&aud->lock); sys_lwcond_signal(&aud->cond); cellAudioAddData(aud->audio_port, out_tmp, CELL_AUDIO_BLOCK_SAMPLES, 1.0); } cellAudioRemoveNotifyEventQueue(key); sys_ppu_thread_exit(0); }
static void pull_event_loop(audioport_t *port, sys_event_queue_t id) { sys_event_t event; int16_t *in_buf = memalign(128, CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t)); float *conv_buf = memalign(128, CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(float)); while (!port->quit_thread) { uint32_t has_read = 0; if (port->sample_cb) has_read = port->sample_cb(in_buf, CELL_AUDIO_BLOCK_SAMPLES * port->channels, port->userdata); else { has_read = CELL_AUDIO_BLOCK_SAMPLES * port->channels; sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT); uint32_t avail = fifo_read_avail(port->buffer); if (avail < CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t)) has_read = avail / sizeof(int16_t); fifo_read(port->buffer, in_buf, has_read * sizeof(int16_t)); sys_lwmutex_unlock(&port->lock); } if (has_read < CELL_AUDIO_BLOCK_SAMPLES * port->channels) memset(in_buf + has_read, 0, (CELL_AUDIO_BLOCK_SAMPLES * port->channels - has_read) * sizeof(int16_t)); resampler_int16_t_to_float(conv_buf, in_buf, CELL_AUDIO_BLOCK_SAMPLES * port->channels); sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT); cellAudioAddData(port->audio_port, conv_buf, CELL_AUDIO_BLOCK_SAMPLES, 1.0); pthread_cond_signal(&port->cond); } free(conv_buf); }
s32 sys_lwmutex_destroy(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex) { sysPrxForUser.Log("sys_lwmutex_destroy(lwmutex=*0x%x)", lwmutex); // check to prevent recursive locking in the next call if (lwmutex->owner.read_relaxed() == CPU.GetId()) { return CELL_EBUSY; } // attempt to lock the mutex if (s32 res = sys_lwmutex_trylock(CPU, lwmutex)) { return res; } // call the syscall if (s32 res = _sys_lwmutex_destroy(lwmutex->sleep_queue)) { // unlock the mutex if failed sys_lwmutex_unlock(CPU, lwmutex); return res; } // deleting succeeded lwmutex->owner.exchange(lwmutex::dead); return CELL_OK; }
s32 sys_lwcond_signal(PPUThread& ppu, vm::ptr<sys_lwcond_t> lwcond) { sysPrxForUser.trace("sys_lwcond_signal(lwcond=*0x%x)", lwcond); const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; if ((lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_RETRY) { // TODO (protocol ignored) //return _sys_lwcond_signal(lwcond->lwcond_queue, 0, -1, 2); } if (lwmutex->vars.owner.load() == ppu.get_id()) { // if owns the mutex lwmutex->all_info++; // call the syscall if (s32 res = _sys_lwcond_signal(lwcond->lwcond_queue, lwmutex->sleep_queue, -1, 1)) { lwmutex->all_info--; return res == CELL_EPERM ? CELL_OK : res; } return CELL_OK; } if (s32 res = sys_lwmutex_trylock(ppu, lwmutex)) { // if locking failed if (res != CELL_EBUSY) { return CELL_ESRCH; } // call the syscall return _sys_lwcond_signal(lwcond->lwcond_queue, 0, -1, 2); } // if locking succeeded lwmutex->all_info++; // call the syscall if (s32 res = _sys_lwcond_signal(lwcond->lwcond_queue, lwmutex->sleep_queue, -1, 3)) { lwmutex->all_info--; // unlock the lightweight mutex sys_lwmutex_unlock(ppu, lwmutex); return res == CELL_ENOENT ? CELL_OK : res; } return CELL_OK; }
static uint32_t audioport_write_avail(cell_audio_handle_t handle) { audioport_t *port = handle; sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT); uint32_t ret = fifo_write_avail(port->buffer); sys_lwmutex_unlock(&port->lock); return ret / sizeof(int16_t); }
s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id) { sysPrxForUser.Log("sys_lwcond_signal_to(lwcond=*0x%x, ppu_thread_id=0x%x)", lwcond, ppu_thread_id); const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; if ((lwmutex->attribute.data() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) == se32(SYS_SYNC_RETRY)) { // TODO (protocol ignored) //return _sys_lwcond_signal(lwcond->lwcond_queue, 0, ppu_thread_id, 2); } if (lwmutex->owner.read_relaxed() == CPU.GetId()) { // if owns the mutex lwmutex->all_info++; // call the syscall if (s32 res = _sys_lwcond_signal(lwcond->lwcond_queue, lwmutex->sleep_queue, ppu_thread_id, 1)) { lwmutex->all_info--; return res; } return CELL_OK; } if (s32 res = sys_lwmutex_trylock(CPU, lwmutex)) { // if locking failed if (res != CELL_EBUSY) { return CELL_ESRCH; } // call the syscall return _sys_lwcond_signal(lwcond->lwcond_queue, 0, ppu_thread_id, 2); } // if locking succeeded lwmutex->all_info++; // call the syscall if (s32 res = _sys_lwcond_signal(lwcond->lwcond_queue, lwmutex->sleep_queue, ppu_thread_id, 3)) { lwmutex->all_info--; // unlock the lightweight mutex sys_lwmutex_unlock(CPU, lwmutex); return res; } return CELL_OK; }
s32 sys_lwcond_signal_all(PPUThread& ppu, vm::ptr<sys_lwcond_t> lwcond) { sysPrxForUser.trace("sys_lwcond_signal_all(lwcond=*0x%x)", lwcond); const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; if ((lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_RETRY) { // TODO (protocol ignored) //return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2); } if (lwmutex->vars.owner.load() == ppu.get_id()) { // if owns the mutex, call the syscall const s32 res = _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 1); if (res <= 0) { // return error or CELL_OK return res; } lwmutex->all_info += res; return CELL_OK; } if (s32 res = sys_lwmutex_trylock(ppu, lwmutex)) { // if locking failed if (res != CELL_EBUSY) { return CELL_ESRCH; } // call the syscall return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2); } // if locking succeeded, call the syscall s32 res = _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 1); if (res > 0) { lwmutex->all_info += res; res = CELL_OK; } // unlock mutex sys_lwmutex_unlock(ppu, lwmutex); return res; }
s32 sys_lwcond_signal_all(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond) { sysPrxForUser.Log("sys_lwcond_signal_all(lwcond=*0x%x)", lwcond); const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; if ((lwmutex->attribute.data() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) == se32(SYS_SYNC_RETRY)) { // TODO (protocol ignored) //return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2); } if (lwmutex->owner.read_relaxed() == CPU.GetId()) { // if owns the mutex, call the syscall const s32 res = _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 1); if (res <= 0) { // return error or CELL_OK return res; } lwmutex->all_info += res; return CELL_OK; } if (s32 res = sys_lwmutex_trylock(CPU, lwmutex)) { // if locking failed if (res != CELL_EBUSY) { return CELL_ESRCH; } // call the syscall return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2); } // if locking succeeded, call the syscall s32 res = _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 1); if (res > 0) { lwmutex->all_info += res; res = CELL_OK; } // unlock mutex sys_lwmutex_unlock(CPU, lwmutex); return res; }
static int32_t audioport_write(cell_audio_handle_t handle, const int16_t *data, uint32_t samples) { int32_t ret = samples; uint32_t bytes = samples * sizeof(int16_t); audioport_t *port = handle; while (bytes) { sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT); uint32_t avail = fifo_write_avail(port->buffer); sys_lwmutex_unlock(&port->lock); uint32_t to_write = avail < bytes ? avail : bytes; if (to_write) { sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT); fifo_write(port->buffer, data, to_write); sys_lwmutex_unlock(&port->lock); bytes -= to_write; data += to_write >> 1; } else sys_lwcond_wait(&port->cond, 0); }
static ssize_t ps3_audio_write(void *data, const void *buf, size_t size) { ps3_audio_t *aud = data; if (aud->nonblocking) { if (fifo_write_avail(aud->buffer) < size) return 0; } while (fifo_write_avail(aud->buffer) < size) sys_lwcond_wait(&aud->cond, 0); sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT); fifo_write(aud->buffer, buf, size); sys_lwmutex_unlock(&aud->lock); return size; }
int __libc_lock_release(__libc_lock_t *lock) { if(SYS_LWMUTEX_UNINITIALIZED(lock)) __libc_auto_lock_allocate(lock); return sys_lwmutex_unlock(lock); }