void Sound::detach() { // Ignore if we are not attached to any source if (!source) return; // Unqueue all buffers and detach source if(isStream()) unqueue(); source = nullptr; }
void Sound::update() { // Buffered sound does not need any update if (!sampler) return; // Unattached streamed sound, neither if (!source) return; // Update queue unqueue(); queue(); }
error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_event_t> dummy_event, u64 timeout) { sys_event.trace("sys_event_queue_receive(equeue_id=0x%x, *0x%x, timeout=0x%llx)", equeue_id, dummy_event, timeout); const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id, [&](lv2_event_queue& queue) -> CellError { if (queue.type != SYS_PPU_QUEUE) { return CELL_EINVAL; } semaphore_lock lock(queue.mutex); if (queue.events.empty()) { queue.sq.emplace_back(&ppu); queue.sleep(ppu, timeout); return CELL_EBUSY; } std::tie(ppu.gpr[4], ppu.gpr[5], ppu.gpr[6], ppu.gpr[7]) = queue.events.front(); queue.events.pop_front(); return {}; }); if (!queue) { return CELL_ESRCH; } if (queue.ret) { if (queue.ret != CELL_EBUSY) { return queue.ret; } } else { return CELL_OK; } // If cancelled, gpr[3] will be non-zero. Other registers must contain event data. ppu.gpr[3] = 0; while (!ppu.state.test_and_reset(cpu_flag::signal)) { if (timeout) { const u64 passed = get_system_time() - ppu.start_time; if (passed >= timeout) { semaphore_lock lock(queue->mutex); if (!queue->unqueue(queue->sq, &ppu)) { timeout = 0; continue; } ppu.gpr[3] = CELL_ETIMEDOUT; break; } thread_ctrl::wait_for(timeout - passed); } else { thread_ctrl::wait(); } } return not_an_error(ppu.gpr[3]); }
int main() { struct nodo * pila; struct nodo * cola; struct nodo * lista; struct nodo nodo1; struct nodo nodo2; struct nodo nodo3; struct nodo nodo4; struct nodo * aux; nodo1.val=1; nodo2.val=2; nodo3.val=3; nodo4.val=4; //pila printf("-- pila --\n"); init(&pila); push(&pila, &nodo1); push(&pila, &nodo2); push(&pila, &nodo3); while(aux=pop(&pila)) printf("%i\n",(*aux).val); //cola printf("-- cola --\n"); init(&cola); push(&cola, &nodo1); push(&cola, &nodo2); push(&cola, &nodo3); while(aux=unqueue(&cola)) printf("%i\n",(*aux).val); //lista printf("-- lista --\n"); init(&lista); agregar(&lista,&nodo1,0); agregar(&lista,&nodo3,1); agregar(&lista,&nodo2,1); aux=quitar(&lista,1); printf("%i\n",(*aux).val); while(aux=quitar(&lista,0)) printf("%i\n",(*aux).val); //lista misc printf("-- lista misc --\n"); init(&lista); agregar(&lista,&nodo1,0); agregar(&lista,&nodo3,1); agregar(&lista,&nodo2,1); agregar(&lista,&nodo4,3); intercambiar(&lista, 1, 3); printf("la lista tiene %i items\n",len(&lista)); while(aux=pop(&lista)) printf("%i\n",(*aux).val); printf("la lista tiene %i items\n",len(&lista)); //lista misc printf("-- lista ordenar --\n"); init(&lista); push(&lista, &nodo3); push(&lista, &nodo1); push(&lista, &nodo4); push(&lista, &nodo2); printf("burbuja\n"); ordenar_burbujeo(&lista); mostrar(&lista); return 0; }
error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout) { sys_lwmutex.trace("_sys_lwmutex_lock(lwmutex_id=0x%x, timeout=0x%llx)", lwmutex_id, timeout); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex) { if (mutex.signaled.try_dec()) { return true; } std::lock_guard lock(mutex.mutex); if (mutex.signaled.try_dec()) { return true; } mutex.sq.emplace_back(&ppu); mutex.sleep(ppu, timeout); return false; }); if (!mutex) { return CELL_ESRCH; } if (mutex.ret) { return CELL_OK; } ppu.gpr[3] = CELL_OK; while (!ppu.state.test_and_reset(cpu_flag::signal)) { if (ppu.is_stopped()) { return 0; } if (timeout) { const u64 passed = get_system_time() - ppu.start_time; if (passed >= timeout) { std::lock_guard lock(mutex->mutex); if (!mutex->unqueue(mutex->sq, &ppu)) { timeout = 0; continue; } ppu.gpr[3] = CELL_ETIMEDOUT; break; } thread_ctrl::wait_for(timeout - passed); } else { thread_ctrl::wait(); } } return not_an_error(ppu.gpr[3]); }
error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mode) { sys_lwcond.trace("_sys_lwcond_signal(lwcond_id=0x%x, lwmutex_id=0x%x, ppu_thread_id=0x%x, mode=%d)", lwcond_id, lwmutex_id, ppu_thread_id, mode); // Mode 1: lwmutex was initially owned by the calling thread // Mode 2: lwmutex was not owned by the calling thread and waiter hasn't been increased // Mode 3: lwmutex was forcefully owned by the calling thread if (mode < 1 || mode > 3) { fmt::throw_exception("Unknown mode (%d)" HERE, mode); } lv2_lwmutex* mutex = nullptr; const auto cond = idm::check<lv2_obj, lv2_lwcond>(lwcond_id, [&](lv2_lwcond& cond) -> cpu_thread* { mutex = idm::check_unlocked<lv2_obj, lv2_lwmutex>(lwmutex_id); if (cond.waiters) { std::lock_guard lock(cond.mutex); cpu_thread* result = nullptr; if (ppu_thread_id != -1) { for (auto cpu : cond.sq) { if (cpu->id == ppu_thread_id) { verify(HERE), cond.unqueue(cond.sq, cpu); result = cpu; break; } } } else { result = cond.schedule<ppu_thread>(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK); } if (result) { cond.waiters--; if (mode == 2) { static_cast<ppu_thread*>(result)->gpr[3] = CELL_EBUSY; } if (mode == 1) { verify(HERE), !mutex->signaled; std::lock_guard lock(mutex->mutex); mutex->sq.emplace_back(result); result = nullptr; mode = 2; // Enforce CELL_OK } return result; } } return nullptr; }); if ((lwmutex_id && !mutex) || !cond) { return CELL_ESRCH; } if (cond.ret) { cond->awake(*cond.ret); } else if (mode == 2) { return CELL_OK; } else if (mode == 1 || ppu_thread_id == -1) { return not_an_error(CELL_EPERM); } else { return not_an_error(CELL_ENOENT); } return CELL_OK; }
error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u64 timeout) { sys_lwcond.trace("_sys_lwcond_queue_wait(lwcond_id=0x%x, lwmutex_id=0x%x, timeout=0x%llx)", lwcond_id, lwmutex_id, timeout); std::shared_ptr<lv2_lwmutex> mutex; const auto cond = idm::get<lv2_obj, lv2_lwcond>(lwcond_id, [&](lv2_lwcond& cond) -> cpu_thread* { mutex = idm::get_unlocked<lv2_obj, lv2_lwmutex>(lwmutex_id); if (!mutex) { return nullptr; } std::lock_guard lock(cond.mutex); // Add a waiter cond.waiters++; cond.sq.emplace_back(&ppu); cond.sleep(ppu, timeout); std::lock_guard lock2(mutex->mutex); // Process lwmutex sleep queue if (const auto cpu = mutex->schedule<ppu_thread>(mutex->sq, mutex->protocol)) { return cpu; } mutex->signaled++; return nullptr; }); if (!cond || !mutex) { return CELL_ESRCH; } if (cond.ret) { cond->awake(*cond.ret); } ppu.gpr[3] = CELL_OK; while (!ppu.state.test_and_reset(cpu_flag::signal)) { if (ppu.is_stopped()) { return 0; } if (timeout) { const u64 passed = get_system_time() - ppu.start_time; if (passed >= timeout) { std::lock_guard lock(cond->mutex); if (!cond->unqueue(cond->sq, &ppu)) { timeout = 0; continue; } cond->waiters--; if (mutex->signaled.try_dec()) { ppu.gpr[3] = CELL_EDEADLK; break; } ppu.gpr[3] = CELL_ETIMEDOUT; break; } thread_ctrl::wait_for(timeout - passed); } else { thread_ctrl::wait(); } } // Return cause return not_an_error(ppu.gpr[3]); }
void Source::unqueue(lost::shared_ptr<Buffer> buffer) { unqueue(buffer->buffer); }
error_code _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mode) { sys_lwcond.trace("_sys_lwcond_signal(lwcond_id=0x%x, lwmutex_id=0x%x, ppu_thread_id=0x%x, mode=%d)", lwcond_id, lwmutex_id, ppu_thread_id, mode); // Mode 1: lwmutex was initially owned by the calling thread // Mode 2: lwmutex was not owned by the calling thread and waiter hasn't been increased // Mode 3: lwmutex was forcefully owned by the calling thread if (mode < 1 || mode > 3) { fmt::throw_exception("Unknown mode (%d)" HERE, mode); } lv2_lwmutex* mutex = nullptr; const auto cond = idm::check<lv2_obj, lv2_lwcond>(lwcond_id, [&](lv2_lwcond& cond) -> cpu_thread* { mutex = idm::check_unlocked<lv2_obj, lv2_lwmutex>(lwmutex_id); if (mutex && cond.waiters) { semaphore_lock lock(mutex->mutex); cpu_thread* result = nullptr; if (ppu_thread_id != -1) { for (auto cpu : cond.sq) { if (cpu->id == ppu_thread_id) { verify(HERE), cond.unqueue(cond.sq, cpu); result = cpu; break; } } } else { result = cond.schedule<ppu_thread>(cond.sq, mutex->protocol); } if (result) { cond.waiters--; static_cast<ppu_thread*>(result)->gpr[3] = mode == 2; if (mode != 2 && !mutex->signaled.fetch_op([](u32& v) { if (v) v--; })) { mutex->sq.emplace_back(result); result = nullptr; mode = 2; // Enforce CELL_OK } return result; } } return nullptr; }); if ((lwmutex_id && !mutex) || !cond) { return CELL_ESRCH; } if (cond.ret) { cond.ret->set_signal(); } else if (mode == 2) { return CELL_OK; } else if (mode == 1 || ppu_thread_id == -1) { return not_an_error(CELL_EPERM); } else { return not_an_error(CELL_ENOENT); } return CELL_OK; }
error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u64 timeout) { sys_lwcond.trace("_sys_lwcond_queue_wait(lwcond_id=0x%x, lwmutex_id=0x%x, timeout=0x%llx)", lwcond_id, lwmutex_id, timeout); const u64 start_time = ppu.gpr[10] = get_system_time(); std::shared_ptr<lv2_lwmutex> mutex; const auto cond = idm::get<lv2_obj, lv2_lwcond>(lwcond_id, [&](lv2_lwcond& cond) -> cpu_thread* { mutex = idm::get_unlocked<lv2_obj, lv2_lwmutex>(lwmutex_id); if (!mutex) { return nullptr; } semaphore_lock lock(mutex->mutex); // Add a waiter cond.waiters++; cond.sq.emplace_back(&ppu); // Process lwmutex sleep queue if (const auto cpu = mutex->schedule<ppu_thread>(mutex->sq, mutex->protocol)) { return cpu; } mutex->signaled++; return nullptr; }); if (!cond || !mutex) { return CELL_ESRCH; } if (cond.ret) { cond.ret->set_signal(); } // SLEEP while (!ppu.state.test_and_reset(cpu_flag::signal)) { if (timeout) { const u64 passed = get_system_time() - start_time; if (passed >= timeout) { semaphore_lock lock(mutex->mutex); if (!cond->unqueue(cond->sq, &ppu)) { timeout = 0; continue; } cond->waiters--; if (mutex->signaled.fetch_op([](u32& v) { if (v) v--; })) { return not_an_error(CELL_EDEADLK); } return not_an_error(CELL_ETIMEDOUT); } thread_ctrl::wait_for(timeout - passed); } else { thread_ctrl::wait(); } } // Return cause return not_an_error(ppu.gpr[3] ? CELL_EBUSY : CELL_OK); }
error_code sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout) { sys_mutex.trace("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx)", mutex_id, timeout); const auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id, [&](lv2_mutex& mutex) { CellError result = mutex.try_lock(ppu.id); if (result == CELL_EBUSY) { std::lock_guard lock(mutex.mutex); if (mutex.try_own(ppu, ppu.id)) { result = {}; } else { mutex.sleep(ppu, timeout); } } return result; }); if (!mutex) { return CELL_ESRCH; } if (mutex.ret) { if (mutex.ret != CELL_EBUSY) { return mutex.ret; } } else { return CELL_OK; } ppu.gpr[3] = CELL_OK; while (!ppu.state.test_and_reset(cpu_flag::signal)) { if (ppu.is_stopped()) { return 0; } if (timeout) { const u64 passed = get_system_time() - ppu.start_time; if (passed >= timeout) { std::lock_guard lock(mutex->mutex); if (!mutex->unqueue(mutex->sq, &ppu)) { timeout = 0; continue; } ppu.gpr[3] = CELL_ETIMEDOUT; break; } thread_ctrl::wait_for(timeout - passed); } else { thread_ctrl::wait(); } } return not_an_error(ppu.gpr[3]); }
error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout) { sys_semaphore.trace("sys_semaphore_wait(sem_id=0x%x, timeout=0x%llx)", sem_id, timeout); const u64 start_time = ppu.gpr[10] = get_system_time(); const auto sem = idm::get<lv2_obj, lv2_sema>(sem_id, [&](lv2_sema& sema) { const s32 val = sema.val; if (val > 0) { if (sema.val.compare_and_swap_test(val, val - 1)) { return true; } } semaphore_lock lock(sema.mutex); if (sema.val-- <= 0) { sema.sq.emplace_back(&ppu); sema.sleep(ppu, start_time, timeout); return false; } return true; }); if (!sem) { return CELL_ESRCH; } if (sem.ret) { return CELL_OK; } ppu.gpr[3] = CELL_OK; while (!ppu.state.test_and_reset(cpu_flag::signal)) { if (timeout) { const u64 passed = get_system_time() - start_time; if (passed >= timeout) { semaphore_lock lock(sem->mutex); const s32 val = sem->val.fetch_op([](s32& val) { if (val < 0) { val++; } }); if (val >= 0) { timeout = 0; continue; } verify(HERE), sem->unqueue(sem->sq, &ppu); ppu.gpr[3] = CELL_ETIMEDOUT; break; } thread_ctrl::wait_for(timeout - passed); } else { thread_ctrl::wait(); } } ppu.check_state(); return not_an_error(ppu.gpr[3]); }