NTSTATUS SERVICECALL NtWaitForSingleObject(IN HANDLE ObjectHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL) { PVOID object; LARGE_INTEGER _timeout; MODE previous_mode; NTSTATUS status; ktrace("ObjectHandle %p, Alertable %d\n", ObjectHandle, Alertable); previous_mode = (unsigned long)TimeOut > TASK_SIZE ? KernelMode : UserMode; if(TimeOut){ if (previous_mode == UserRequest) { if (copy_from_user(&_timeout, TimeOut, sizeof(_timeout))) return STATUS_NO_MEMORY; } else _timeout = *TimeOut; } status = ref_object_by_handle(ObjectHandle, SYNCHRONIZE, NULL, KernelMode, &object, NULL); if (!NT_SUCCESS(status)) return status; if(TimeOut){ status = wait_for_single_object(object, UserRequest, KernelMode, Alertable, &_timeout); } else { status = wait_for_single_object(object, UserRequest, KernelMode, Alertable, NULL); } if (!NT_SUCCESS(status)) goto out; if (previous_mode == UserMode) { if (copy_to_user(TimeOut, &_timeout, sizeof(_timeout))) { status = STATUS_NO_MEMORY; goto out; } } else *TimeOut = _timeout; out: deref_object(object); return status; } /* end NtWaitForSingleObject */
bool mutex::timed_lock(::boost::system_time const& wait_until) { HPX_ITT_SYNC_PREPARE(this); if (try_lock_internal()) { HPX_ITT_SYNC_ACQUIRED(this); util::register_lock(this); return true; } boost::uint32_t old_count = active_count_.load(boost::memory_order_acquire); mark_waiting_and_try_lock(old_count); if (old_count & lock_flag_value) { // wait for lock to get available bool lock_acquired = false; do { if (wait_for_single_object(wait_until)) { // if this timed out, just return false --active_count_; HPX_ITT_SYNC_CANCEL(this); return false; } clear_waiting_and_try_lock(old_count); lock_acquired = !(old_count & lock_flag_value); } while (!lock_acquired); } HPX_ITT_SYNC_ACQUIRED(this); util::register_lock(this); return true; }
VOID acquire_fmutex_unsafe(PFAST_MUTEX FastMutex) { atomic_inc(&FastMutex->Contention); while (xchg(&FastMutex->Count, 0) == 0) wait_for_single_object(&FastMutex->Event, Executive, KernelMode, FALSE, NULL); atomic_dec(&FastMutex->Contention); FastMutex->Owner = (struct kthread *)get_current_ethread(); }
bool Thread::wait(unsigned wait_time) { return wait_for_single_object(h_thread, wait_time); }
NTSTATUS SERVICECALL NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, IN HANDLE WaitableObjectHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL) { PVOID signal_obj, wait_obj; struct dispatcher_header *signal_header; LARGE_INTEGER _timeout; MODE previous_mode; NTSTATUS status; ktrace("ObjectHandleToSignal %p, WaitableObjectHandle %p, Alertable %d\n", ObjectHandleToSignal, WaitableObjectHandle, Alertable); previous_mode = (unsigned long)TimeOut > TASK_SIZE ? KernelMode : UserMode; if(TimeOut){ if (previous_mode == UserMode) { if (copy_from_user(&_timeout, TimeOut, sizeof(_timeout))) return STATUS_NO_MEMORY; } else _timeout = *TimeOut; } status = ref_object_by_handle(ObjectHandleToSignal, 0, NULL, KernelMode, &signal_obj, NULL); if (!NT_SUCCESS(status)) return status; status = ref_object_by_handle(WaitableObjectHandle, SYNCHRONIZE, NULL, KernelMode, &wait_obj, NULL); if (!NT_SUCCESS(status)) { deref_object(signal_obj); return status; } signal_header = (struct dispatcher_header *)signal_obj; if (is_wine_object(signal_header->type)) { struct object *obj = (struct object*)signal_obj; unsigned int access = get_handle_access(process2eprocess(current_thread->process), WaitableObjectHandle); if (BODY_TO_HEADER(obj)->ops->signal) BODY_TO_HEADER(obj)->ops->signal(obj, access); } else switch (signal_header->type) { case EventNotificationObject: case EventSynchronizationObject: set_event(signal_obj, EVENT_INCREMENT, TRUE); break; case MutantObject: release_mutant(signal_obj, IO_NO_INCREMENT, FALSE, TRUE); break; case SemaphoreObject: release_semaphore(signal_obj, SEMAPHORE_INCREMENT, 1, TRUE); break; default: deref_object(signal_obj); deref_object(wait_obj); return STATUS_OBJECT_TYPE_MISMATCH; } if(TimeOut){ status = wait_for_single_object(wait_obj, UserRequest, KernelMode, Alertable, &_timeout); } else { status = wait_for_single_object(wait_obj, UserRequest, KernelMode, Alertable, NULL); } if (!NT_SUCCESS(status)) goto out; if (TimeOut) { if (previous_mode == UserMode) { if (copy_to_user(TimeOut, &_timeout, sizeof(_timeout))) { status = STATUS_NO_MEMORY; goto out; } } else *TimeOut = _timeout; } out: deref_object(signal_obj); deref_object(wait_obj); return status; } /* end NtSignalAndWaitForSingleObject */