diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 30 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 5 | 
2 files changed, 29 insertions, 6 deletions
| diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index abde2a6d3..0e22d9273 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -52,6 +52,8 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&              return IocCtrlEventRegister(input, output);          case 0x20:              return IocCtrlEventUnregister(input, output); +        case 0x21: +            return IocCtrlEventUnregisterBatch(input, output);          }          break;      default: @@ -249,6 +251,25 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input,      return FreeEvent(event_id);  } +NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input, +                                                  std::vector<u8>& output) { +    IocCtrlEventUnregisterBatchParams params{}; +    std::memcpy(¶ms, input.data(), sizeof(params)); +    u64 event_mask = params.user_events; +    LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask); + +    auto lock = NvEventsLock(); +    while (event_mask != 0) { +        const u64 event_id = std::countr_zero(event_mask); +        event_mask &= ~(1ULL << event_id); +        const auto result = FreeEvent(static_cast<u32>(event_id)); +        if (result != NvResult::Success) { +            return result; +        } +    } +    return NvResult::Success; +} +  NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) {      IocCtrlEventClearParams params{};      std::memcpy(¶ms, input.data(), sizeof(params)); @@ -362,10 +383,11 @@ u32 nvhost_ctrl::FindFreeNvEvent(u32 syncpoint_id) {  }  void nvhost_ctrl::SignalNvEvent(u32 syncpoint_id, u32 value) { -    const u32 max = MaxNvEvents - std::countl_zero(events_mask); -    const u32 min = std::countr_zero(events_mask); -    for (u32 i = min; i < max; i++) { -        auto& event = events[i]; +    u64 signal_mask = events_mask; +    while (signal_mask != 0) { +        const u64 event_id = std::countr_zero(signal_mask); +        signal_mask &= ~(1ULL << event_id); +        auto& event = events[event_id];          if (event.assigned_syncpt != syncpoint_id || event.assigned_value != value) {              continue;          } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index f2fc5d047..9bd10257b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -177,16 +177,17 @@ private:      static_assert(sizeof(IocCtrlEventUnregisterParams) == 4,                    "IocCtrlEventUnregisterParams is incorrect size"); -    struct IocCtrlEventKill { +    struct IocCtrlEventUnregisterBatchParams {          u64_le user_events{};      }; -    static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size"); +    static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, "IocCtrlEventKill is incorrect size");      NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);      NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,                                bool is_allocation);      NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);      NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); +    NvResult IocCtrlEventUnregisterBatch(const std::vector<u8>& input, std::vector<u8>& output);      NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output);      NvResult FreeEvent(u32 slot); | 
