ReacOS源代码阅读之进程间通信--SetEvent

来源:互联网 发布:手机同花顺炒股软件 编辑:程序博客网 时间:2024/05/29 14:05

        ReacOS的源代码是从svn服务器下载,下载地址为:"svn://svn.reactos.org/reactos/trunk/reactos"(不包括双引号)。

        源代码的根目录存放在ReactOS。SetEvent的函数路径为 ReactOS\dll\win32\kernel32\client\synch.c 。这个函数的作用是设置事件为有信号状态,使得其他线程可以获取该事件。

/* * @implemented */BOOLWINAPIDECLSPEC_HOTPATCHSetEvent(IN HANDLE hEvent){    NTSTATUS Status;    /* Set the event */    Status = NtSetEvent(hEvent, NULL);    if (NT_SUCCESS(Status)) return TRUE;    /* If we got here, then we failed */    BaseSetLastNTError(Status);    return FALSE;}
        SetEvent函数调用NtSetEvent函数,该函数路径为 ReactOS\ntoskrnl\ex\event.c 。

/* * @implemented */NTSTATUSNTAPINtSetEvent(IN HANDLE EventHandle,           OUT PLONG PreviousState  OPTIONAL){    PKEVENT Event;    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();    NTSTATUS Status;    PAGED_CODE();    DPRINT("NtSetEvent(EventHandle 0%p PreviousState 0%p)\n",           EventHandle, PreviousState);    /* Check if we were called from user-mode */    if ((PreviousState) && (PreviousMode != KernelMode))    {        /* Entry SEH Block */        _SEH2_TRY        {            /* Make sure the state pointer is valid */            ProbeForWriteLong(PreviousState);        }        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)        {            /* Return the exception code */            _SEH2_YIELD(return _SEH2_GetExceptionCode());        }        _SEH2_END;    }    /* Open the Object */    Status = ObReferenceObjectByHandle(EventHandle,                                       EVENT_MODIFY_STATE,                                       ExEventObjectType,                                       PreviousMode,                                       (PVOID*)&Event,                                       NULL);    if (NT_SUCCESS(Status))    {        /* Set the Event */        LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);        ObDereferenceObject(Event);        /* Check if caller wants the old state back */        if (PreviousState)        {            /* Entry SEH Block for return */            _SEH2_TRY            {                /* Return previous state */                *PreviousState = Prev;            }            _SEH2_EXCEPT(ExSystemExceptionFilter())            {                Status = _SEH2_GetExceptionCode();            }            _SEH2_END;        }    }    /* Return Status */    return Status;}

        NtSetEvent函数较多代码都是SEH异常处理机制。主体部分首先是调用ObReferenceObjectByHandle获取KEVENT内核事件对象,然后调用KeSetEvent,该函数路径为ReactOS\ntoskrnl\ke\eventobj.c。关键部分源代码原本都已经有注释,这里就不画蛇添足了。

/* * @implemented */LONGNTAPIKeSetEvent(IN PKEVENT Event,           IN KPRIORITY Increment,           IN BOOLEAN Wait){    KIRQL OldIrql;    LONG PreviousState;    PKTHREAD Thread;    ASSERT_EVENT(Event);    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);    /*     * Check if this is an signaled notification event without an upcoming wait.     * In this case, we can immediately return TRUE, without locking.     */    if ((Event->Header.Type == EventNotificationObject) &&        (Event->Header.SignalState == 1) &&        !(Wait))    {        /* Return the signal state (TRUE/Signalled) */        return TRUE;    }    /* Lock the Dispathcer Database */    OldIrql = KiAcquireDispatcherLock();    /* Save the Previous State */    PreviousState = Event->Header.SignalState;    /* Set the Event to Signaled */    Event->Header.SignalState = 1;    /* Check if the event just became signaled now, and it has waiters */    if (!(PreviousState) && !(IsListEmpty(&Event->Header.WaitListHead)))    {        /* Check the type of event */        if (Event->Header.Type == EventNotificationObject)        {            /* Unwait the thread */            KxUnwaitThread(&Event->Header, Increment);        }        else        {            /* Otherwise unwait the thread and unsignal the event */            KxUnwaitThreadForEvent(Event, Increment);        }    }    /* Check what wait state was requested */    if (!Wait)    {        /* Wait not requested, release Dispatcher Database and return */        KiReleaseDispatcherLock(OldIrql);    }    else    {        /* Return Locked and with a Wait */        Thread = KeGetCurrentThread();        Thread->WaitNext = TRUE;        Thread->WaitIrql = OldIrql;    }    /* Return the previous State */    return PreviousState;}




0 0