Función KeWaitForMultipleObjects (wdm.h)

La rutina KeWaitForMultipleObjects coloca el subproceso actual en un estado de espera alertable o nonalertable hasta que cualquiera o todos los objetos distribuidores se establecen en un estado señalado o (opcionalmente) hasta que se agote el tiempo de espera.

Sintaxis

NTSTATUS
KeWaitForMultipleObjects (
    ULONG Count,
    PVOID Object[],
    WaitType,
    KWAIT_REASON WaitReason,
    KPROCESSOR_MODE WaitMode,
    BOOLEAN Alertable,
    PLARGE_INTEGER Timeout,
    PKWAIT_BLOCK WaitBlockArray
    );

Parámetros

[in] Count

Número de objetos en los que se va a esperar. Este parámetro especifica el número de elementos de la matriz a los que apunta el parámetro Object .

[in] Object

Puntero a una matriz de punteros a objetos de distribuidor (eventos, exclusiones mutuas, semáforos, subprocesos y temporizadores) para los que el autor de la llamada proporciona el almacenamiento. Tanto la matriz de punteros como los objetos de distribuidor deben residir en la memoria del sistema no paginada. Para obtener más información, vea la sección Comentarios.

[in] WaitType

Tipo de operación de espera que se va a realizar. Especifique waitAll, que indica que todos los objetos especificados deben alcanzar un estado señalado antes de que se cumpla la espera; o WaitAny, que indica que cualquiera de los objetos debe alcanzar un estado señalado antes de que se cumpla la espera.

[in] WaitReason

Motivo de la espera. Los controladores deben establecer este valor en Executive o, si el controlador está trabajando en nombre de un usuario y se ejecuta en el contexto de un subproceso de usuario, en UserRequest.

[in] WaitMode

Si el autor de la llamada espera en KernelMode o UserMode. Los controladores intermedios y de nivel más bajo deben especificar KernelMode. Si el conjunto de objetos esperados incluye una exclusión mutua, el autor de la llamada debe especificar KernelMode.

[in] Alertable

Valor booleano que indica si el subproceso se puede alertar mientras está en estado de espera.

[in, optional] Timeout

Puntero a un valor de tiempo de espera que especifica el tiempo absoluto o relativo, en unidades de 100 nanosegundos, en las que se va a completar la espera.

Un valor positivo especifica una hora absoluta, relativa al 1 de enero de 1601. Un valor negativo especifica un intervalo relativo a la hora actual. Los tiempos de expiración absolutos realizan un seguimiento de los cambios en la hora del sistema; los tiempos de expiración relativos no se ven afectados por los cambios de hora del sistema.

Si *Timeout = 0, la rutina devuelve sin esperar. Si el autor de la llamada proporciona un puntero NULL , la rutina espera indefinidamente hasta que cualquiera o todos los objetos de distribuidor se establezcan en el estado señalado. Para obtener más información, vea la sección Comentarios que se muestra más adelante.

[out, optional] WaitBlockArray

Puntero a una matriz de KWAIT_BLOCK asignada por el autor de la llamada. Si Count<= THREAD_WAIT_OBJECTS, WaitBlockArray puede ser NULL. De lo contrario, este parámetro debe apuntar a un búfer de memoria de sizeof(KWAIT_BLOCK) * Bytes de recuento . La rutina usa este búfer para mantener registros mientras se realiza la operación de espera. El búfer WaitBlockArray debe residir en la memoria del sistema no paginada. Para obtener más información, vea la sección Comentarios.

Valor devuelto

KeWaitForMultipleObjects puede devolver una de las siguientes opciones:

Código devuelto Descripción
STATUS_SUCCESS El llamador especificó WaitAll para el parámetro WaitType y todos los objetos distribuidores de la matriz Object se han establecido en el estado señalado.
STATUS_ALERTED La espera se interrumpió para entregar una alerta al subproceso que llama.
STATUS_USER_APC La espera se interrumpió para entregar una llamada de procedimiento asincrónico de usuario (APC) al subproceso que llama.
STATUS_TIMEOUT Se agotó el tiempo de espera antes de que se cumpla el conjunto especificado de condiciones de espera. Este valor se puede devolver cuando se especifica un valor de tiempo de espera explícito de cero, pero no se puede cumplir inmediatamente el conjunto especificado de condiciones de espera.
STATUS_WAIT_0 a través de STATUS_WAIT_63 El autor de la llamada especificó WaitAny para WaitType y uno de los objetos distribuidores de la matriz Object se ha establecido en el estado señalado. Los seis bits inferiores del valor devuelto codifican el índice de base cero del objeto que satisface la espera.
STATUS_ABANDONED_WAIT_0 a través de STATUS_ABANDONED_WAIT_63 El autor de la llamada intentó esperar una exclusión mutua que se ha abandonado. Los seis bits inferiores del valor devuelto codifican el índice de base cero de la exclusión mutua en la matriz Object .

Tenga en cuenta que la macro NT_SUCCESS reconoce todos estos valores de estado como valores "correctos".

Comentarios

Cada objeto de subproceso tiene una matriz integrada de bloques de espera que se pueden usar para esperar a que varios objetos se establezcan simultáneamente. Siempre que sea posible, la matriz integrada de bloques de espera debe usarse en una operación wait-multiple, ya que no es necesario asignar ningún almacenamiento de bloque de espera adicional y desasignarse más adelante. Sin embargo, si el número de objetos que se deben esperar simultáneamente es mayor que el número de bloques de espera integrados, use el parámetro WaitBlockArray para especificar un conjunto alternativo de bloques de espera que se usarán en la operación de espera. Los controladores solo necesitan asignar un búfer de memoria suficientemente grande para WaitBlockArray. No es necesario inicializar el búfer; sin embargo, se debe asignar a partir de la memoria del sistema no paginada. Si el parámetro WaitMode es UserMode, el búfer WaitBlockArray no se debe asignar en la pila local porque la pila podría intercambiarse sin memoria. Los controladores pueden tratar este búfer como una estructura opaca y pueden liberarlo después de que la rutina vuelva. Si Count> MAXIMUM_WAIT_OBJECTS o si WaitBlockArray es NULL y Count> THREAD_WAIT_OBJECTS, el sistema emite la comprobación de errores 0xC (MAXIMUM_WAIT_OBJECTS_EXCEEDED).

El estado actual de cada uno de los objetos especificados se examina para determinar si la espera se puede satisfacer inmediatamente. Si se realizan los efectos secundarios necesarios en los objetos , se devuelve un valor adecuado.

Si no se puede satisfacer la espera inmediatamente y no se ha especificado ningún valor de tiempo de espera o se ha especificado un valor de tiempo de espera distinto de cero, el subproceso actual se coloca en un estado de espera y se selecciona un subproceso nuevo para su ejecución en el procesador actual. Si no se proporciona ningún tiempo de espera , el subproceso que realiza la llamada permanecerá en un estado de espera hasta que se cumplan las condiciones especificadas por Object y WaitType .

Si se especifica Timeout , la espera se cumplirá automáticamente si no se cumple ninguna de las condiciones de espera especificadas cuando expire el intervalo especificado.

Un valor de tiempo de espera de cero permite probar un conjunto de condiciones de espera, realizando condicionalmente los efectos secundarios si la espera puede cumplirse inmediatamente, como en la adquisición de una exclusión mutua.

Los intervalos de tiempo de espera se miden en relación con el reloj del sistema y la precisión con la que el sistema operativo puede detectar el final de un intervalo de tiempo de espera está limitado por la granularidad del reloj del sistema. Para obtener más información, consulte Precisión del temporizador.

El parámetro Alertable determina cuándo se puede alertar al subproceso y su estado de espera, por lo tanto, anulado. Para obtener más información, consulte Waits and APCs (Esperas y API).

La matriz a la que apunta el parámetro Objects debe residir en la memoria del sistema no paginada. Normalmente, un controlador asigna el almacenamiento de la matriz Objects en la pila local. La matriz Objects se puede asignar en la pila local, independientemente del valor del parámetro WaitMode .

Los objetos distribuidores a los que apuntan los elementos de la matriz Objects deben residir en la memoria del sistema no paginada. Si el parámetro WaitMode es UserMode, la pila del kernel se puede intercambiar durante la espera. Por lo tanto, un llamador nunca debe intentar pasar parámetros en la pila al llamar a KeWaitForMultipleObjects con el argumento UserMode . Si asigna el evento en la pila, debe establecer el parámetro WaitMode en KernelMode.

Se aplica una consideración especial cuando el parámetro Object pasado a KeWaitForMultipleObjects es una exclusión mutua. Si el objeto distribuidor en el que se espera es una exclusión mutua, la entrega de APC es la misma que para todos los demás objetos de distribuidor durante la espera. Sin embargo, después de que KeWaitForMultipleObjects vuelva con STATUS_SUCCESS y el subproceso contiene realmente la exclusión mutua, solo se entregan las API de modo kernel especiales. La entrega de todas las demás API, tanto en modo kernel como en modo de usuario, está deshabilitada. Esta restricción en la entrega de LAS API persiste hasta que se libera la exclusión mutua.

Es especialmente importante comprobar el valor devuelto de KeWaitForMultipleObjects cuando el parámetro WaitMode es UserMode o Alertable es TRUE, ya que KeWaitForMultipleObjects puede devolverse al principio con un estado de STATUS_USER_APC o STATUS_ALERTED.

Todas las esperas a largo plazo que un usuario puede anular deben ser esperas UserMode y Alertable debe establecerse en FALSE.

Siempre que sea posible, Alertable debe establecerse en FALSE y WaitMode debe establecerse en KernelMode para reducir la complejidad del controlador. La excepción principal a esto es cuando la espera es una espera a largo plazo.

Una exclusión mutua solo se puede adquirir de forma recursiva solo las veces minLONG. Si se supera este límite, la rutina genera una excepción de STATUS_MUTANT_LIMIT_EXCEEDED.

Los autores de llamadas de KeWaitForMultipleObjects se pueden ejecutar en IRQL <= DISPATCH_LEVEL. Sin embargo, si Timeout = NULL o *Timeout != 0, el autor de la llamada debe ejecutarse en IRQL <= APC_LEVEL y en un contexto de subproceso nobitrario. (Si Timeout != NULL y *Timeout = 0, el autor de la llamada debe ejecutarse en IRQL <= DISPATCH_LEVEL).

Requisitos

Requisito Value
Cliente mínimo compatible Disponible a partir de Windows 2000.
Plataforma de destino Universal
Encabezado wdm.h (incluya Wdm.h, Ntddk.h, Ntifs.h)
Library NtosKrnl.lib
Archivo DLL NtosKrnl.exe
IRQL vea la sección Comentarios.
Reglas de cumplimiento de DDI HwStorPortProhibitedDIs(storport), IrpProcessingComplete(wdm), IrqlKeWaitForMultipleObjects(wdm), SpNoWait(storport)

Consulte también

ExInitializeFastMutex

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForSingleObject