Fonction ExInitializeLookasideListEx (wdm.h)

La routine ExInitializeLookasideListEx initialise une liste de lookaside.

Syntaxe

NTSTATUS ExInitializeLookasideListEx(
  [out]          PLOOKASIDE_LIST_EX    Lookaside,
  [in, optional] PALLOCATE_FUNCTION_EX Allocate,
  [in, optional] PFREE_FUNCTION_EX     Free,
  [in]           POOL_TYPE             PoolType,
  [in]           ULONG                 Flags,
  [in]           SIZE_T                Size,
  [in]           ULONG                 Tag,
  [in]           USHORT                Depth
);

Paramètres

[out] Lookaside

Pointeur vers la structure LOOKASIDE_LIST_EX à initialiser. Au retour, cette structure décrit une liste de lookaside vide. L’appelant doit utiliser l’espace système non paginé pour cette structure, que les entrées de la liste de recherche soient allouées à partir de la mémoire paginée ou non paginée. Sur les plateformes 64 bits, cette structure doit être alignée sur 16 octets.

[in, optional] Allocate

Pointeur vers une routine LookasideListAllocateEx fournie par l’appelant qui alloue une nouvelle entrée lookaside-list. La routine ExAllocateFromLookasideListEx appelle cette routine LookasideListAllocateEx si la liste de lookaside est vide (ne contient aucune entrée). Ce paramètre est facultatif et peut être spécifié comme NULL si une routine d’allocation personnalisée n’est pas requise. Si ce paramètre a la valeur NULL, les appels à ExAllocateFromPagedLookasideList allouent automatiquement le stockage paginé ou non paginé (tel que déterminé par le paramètre PoolType ) pour les nouvelles entrées.

[in, optional] Free

Pointeur vers une routine LookasideListFreeEx fournie par l’appelant qui libère une entrée de liste de lookaside précédemment allouée. La routine ExFreeToPagedLookasideList appelle cette routine LookasideListFreeEx si la liste de lookaside est complète (autrement dit, la liste contient déjà le nombre maximal d’entrées, tel que déterminé par le système d’exploitation). Ce paramètre est facultatif et peut être spécifié comme NULL si une routine de désallocation personnalisée n’est pas requise. Si ce paramètre a la valeur NULL, les appels à ExFreeToPagedLookasideList libèrent automatiquement le stockage pour les entrées spécifiées.

[in] PoolType

Spécifie le type de pool des entrées dans la liste de recherche. Définissez ce paramètre sur une valeur d’énumération POOL_TYPE valide.

[in] Flags

Spécifie une valeur d’indicateur facultative pour modifier le comportement par défaut de la routine LookasideListAllocateEx . Définissez ce paramètre sur zéro ou sur l’un des bits d’indicateur EX_LOOKASIDE_LIST_EX_FLAGS_XXX suivants.

Bit d’indicateur Description
EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL Si l’allocation échoue, déclenchez une exception.
EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE Si l’allocation échoue, retournez NULL au lieu de déclencher une exception. Cet indicateur est destiné à être utilisé avec une routine d’allocation, telle que ExAllocatePoolWithQuotaTag, qui facture des quotas pour l’utilisation du pool.

Ces deux bits d’indicateur s’excluent mutuellement.

Si Allouer a la valeur NULL, définissez Indicateurs sur zéro ou EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, mais pas sur EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE. Sinon, le comportement de la routine d’allocation par défaut n’est pas défini.

Si Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, la valeur du paramètre PoolType est ORed au niveau du bit avec le bit d’indicateur POOL_RAISE_IF_ALLOCATION_FAILURE pour former la valeur du paramètre PoolType passée à la routine LookasideListAllocateEx . La routine LookasideListAllocateEx peut passer cette valeur PoolType , sans modification, à la routine ExAllocatePoolWithTag . Pour plus d’informations sur l’indicateur POOL_RAISE_IF_ALLOCATION_FAILURE, consultez ExAllocatePoolWithTag.

Si Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, la valeur du paramètre PoolType est ORed au niveau du bit avec le bit d’indicateur POOL_QUOTA_FAIL_INSTEAD_OF_RAISE pour former la valeur du paramètre PoolType qui est passée à la routine LookasideListAllocateEx . La routine LookasideListAllocateEx peut transmettre cette valeur PoolType , sans modification, à la routine ExAllocatePoolWithQuotaTag . Pour plus d’informations sur l’indicateur POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, consultez ExAllocatePoolWithQuotaTag.

[in] Size

Spécifie la taille, en octets, de chaque entrée de la liste de recherche.

[in] Tag

Spécifie la balise de pool de quatre octets à utiliser pour marquer le stockage alloué pour les entrées de liste de recherche. Pour plus d’informations sur les balises de pool, consultez la description du paramètre Tag dans ExAllocatePoolWithTag.

[in] Depth

Réservé. Définissez toujours ce paramètre sur zéro.

Valeur retournée

ExInitializeLookasideListEx retourne STATUS_SUCCESS si l’appel réussit. Les valeurs de retour possibles incluent le code d’erreur suivant :

Code de retour Description
STATUS_INVALID_PARAMETER_4 La valeur du paramètre PoolType n’est pas valide.
STATUS_INVALID_PARAMETER_5 La valeur du paramètre Flags n’est pas valide.

Remarques

Un pilote doit appeler cette routine pour initialiser une liste de lookaside avant que le pilote puisse commencer à utiliser la liste. Une liste de recherche est un pool de mémoires tampons de taille fixe que le pilote peut gérer localement pour réduire le nombre d’appels aux routines d’allocation système et, par conséquent, améliorer les performances. Les mémoires tampons sont stockées sous forme d’entrées dans la liste de recherche. Toutes les entrées de la liste sont de la même taille, uniforme, qui est spécifiée par le paramètre Size .

Une fois ExInitializeLookasideListEx retourné, la liste de recherche est initialisée, mais ne contient aucune entrée. Lorsqu’un client appelle la routine ExAllocateFromLookasideListEx pour demander une entrée, cette routine détermine que la liste de recherche est vide et appelle la routine LookasideListAllocateEx fournie par le pilote pour allouer dynamiquement le stockage pour une nouvelle entrée. Des entrées supplémentaires peuvent être allouées en réponse à des demandes similaires de clients. Plus tard, lorsque les clients appellent ExFreeToLookasideListEx pour libérer ces entrées, cette routine insère les entrées dans la liste de recherche. Si le nombre d’entrées dans la liste atteint une limite qui est déterminée par le système d’exploitation, ExFreeToLookasideListEx cesse d’ajouter d’autres entrées à la liste et transmet ces entrées à la routine LookasideListFreeEx fournie par le pilote à libérer.

Si le pilote ne fournit pas les routines LookasideListAllocateEx et LookasideListFreeEx , les routines ExAllocateFromLookasideListEx et ExFreeToLookasideListEx utilisent plutôt des routines d’allocation et de désallocation par défaut.

Il n’y a aucun avantage à fournir des routines LookasideListAllocateEx et LookasideListFreeEx qui ne font rien d’autre qu’appeler ExAllocatePoolWithTag et ExFreePool. Le même effet peut être obtenu avec de meilleures performances en définissant simplement les paramètres Allocate et Free sur NULL.

Avant qu’un pilote ne se décharge, il doit libérer explicitement toutes les listes de lookaside qu’il a créées. Si vous ne le faites pas, il s’agit d’une erreur de programmation grave. Appelez la routine ExDeleteLookasideListEx pour libérer une liste de lookaside. Cette routine libère le stockage pour toutes les entrées restantes dans la liste de recherche spécifiée, puis supprime la liste de l’ensemble à l’échelle du système des listes de lookaside actives.

Le système d’exploitation effectue le suivi de toutes les listes de lookaside actuellement utilisées. Étant donné que la quantité de mémoire non paginé disponible et la demande d’entrées de liste de recherche varient au fil du temps, le système d’exploitation ajuste dynamiquement ses limites pour le nombre maximal d’entrées dans chaque liste de recherche non paginé.

Dans Windows 2000 et versions ultérieures de Windows, une liste de lookaside contenant des entrées paginées ou non paginées peut être décrite par une structure PAGED_LOOKASIDE_LIST ou NPAGED_LOOKASIDE_LIST , respectivement.

Pour plus d’informations sur les listes de lookaside, consultez Utilisation de lookaside Listes.

Les appelants d’ExInitializeLookasideListEx peuvent s’exécuter sur IRQL <= DISPATCH_LEVEL, mais ils s’exécutent généralement sur IRQL = PASSIVE_LEVEL.

Exemples

Les routines LookasideListAllocateEx et LookasideListFreeEx fournies par le pilote reçoivent des paramètres lookaside qui pointent vers la structure LOOKASIDE_LIST_EX qui décrit la liste de lookaside. Les routines peuvent utiliser ce paramètre pour accéder aux données privées que le pilote a associées à la liste de recherche. Par exemple, le pilote peut allouer une instance de la structure suivante pour collecter des données privées pour chaque liste de recherche qu’il crée :

typedef struct
{
  ULONG NumberOfAllocations;  // number of entries allocated
  ULONG NumberOfFrees;        // number of entries freed
  LOOKASIDE_LIST_EX LookasideField;
} MY_PRIVATE_DATA;

Le pilote peut initialiser une liste de lookaside, comme illustré dans l’exemple de code suivant :

#define ENTRY_SIZE  256
#define MY_POOL_TAG  'tsLL'      
MY_PRIVATE_DATA *MyContext;
NTSTATUS status = STATUS_SUCCESS;
 
MyContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MY_PRIVATE_DATA), MY_POOL_TAG);
if (MyContext)
{
    MyContext.NumberOfAllocations = 0;
    MyContext.NumberOfFrees = 0;

    status = ExInitializeLookasideListEx(
                 &MyContext.LookasideField,
                 MyLookasideListAllocateEx,
                 MyLookasideListFreeEx,
                 NonPagedPool,
                 0,
                 ENTRY_SIZE,
                 MY_POOL_TAG,
                 0);
}
else
{
    status = STATUS_INSUFFICIENT_RESOURCES;
}

L’exemple de code suivant montre comment la routine LookasideListAllocateEx peut utiliser son paramètre Lookaside pour accéder aux données privées associées à la liste de recherche :

PVOID
  MyLookasideListAllocateEx(
    __in POOL_TYPE  PoolType,
    __in SIZE_T  NumberOfBytes,
    __in ULONG  Tag,
    __inout PLOOKASIDE_LIST_EX  Lookaside)
{
    MY_PRIVATE_DATA *MyContext;
    PVOID NewEntry;

    MyContext = CONTAINING_RECORD(Lookaside, MY_PRIVATE_DATA, LookasideField);

    NewEntry = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);

    if (NewEntry)
    {
        ULONG NumberOfAllocations = (ULONG) InterlockedIncrement((LONG volatile*)&MyContext->NumberOfAllocations);
    }

    return NewEntry;
}

La macro CONTAINING_RECORD est définie dans le fichier d’en-tête Ntdef.h. La routine LookAsideListFreeEx peut également utiliser son paramètre Lookaside pour accéder aux données privées.

Une fois que la routine MyLookasideListAllocateEx de cet exemple est retournée, ExAllocateFromLookasideListEx insère la mémoire tampon vers laquelle pointe la variable NewEntry dans la liste de recherche. Pour que cette opération d’insertion soit sécurisée par thread, ExAllocateFromLookasideListEx synchronise son accès à la liste de recherche avec d’autres opérations d’insertion et de suppression de liste qui peuvent être effectuées par d’autres threads. De même, quand ExFreeFromLookasideListEx supprime une mémoire tampon de la liste de recherche, il synchronise son accès à la liste.

ExAllocateFromLookasideListEx et ExFreeFromLookasideListEx ne synchronisent pas leurs appels avec les routines LookasideListAllocateEx et LookasideListFreeEx fournies par le pilote. Par conséquent, si les routines MyLookasideListAllocateEx et MyLookasideListFreeEx dans les exemples de code précédents doivent être thread-safe, le pilote doit fournir la synchronisation nécessaire.

L’exemple de routine, MyLookasideListAllocateEx, synchronise son accès à la variable MyContext-NumberOfAllocations> avec d’autres threads susceptibles d’incrémenter et de décrémenter cette variable. Pour fournir cette synchronisation, MyLookasideListAllocateEx appelle la routine InterlockedIncrement pour incrémenter atomiquement cette variable. De même, la routine MyLookasideListFreeEx (non affichée) peut appeler la routine InterlockedDecrement pour décrémenter atomiquement cette variable.

Toutefois, si le seul objectif de la variable MyContext-NumberOfAllocations> dans l’exemple de code précédent est simplement de collecter des statistiques sur les allocations de liste de recherche, les incréments atomiques et les décrémentments ne sont guère nécessaires. Dans ce cas, la possibilité à distance d’un incrément ou d’une décrémentation manquée ne devrait pas être un problème.

Pour plus d’informations sur la sécurité des threads pour les listes de lookaside, consultez Utilisation des Listes lookaside.

Configuration requise

Condition requise Valeur
Client minimal pris en charge Disponible à partir de Windows Vista.
Plateforme cible Universal
En-tête wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Bibliothèque NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <= DISPATCH_LEVEL (voir la section Notes)

Voir aussi

ExAllocateFromLookasideListEx

ExAllocatePoolWithQuotaTag

ExAllocatePoolWithTag

ExDeleteLookasideListEx

ExFreePool

ExFreeToLookasideListEx

InterlockedDecrement

InterlockedIncrement

LOOKASIDE_LIST_EX

LookasideListAllocateEx

LookasideListFreeEx

NPAGED_LOOKASIDE_LIST

PAGED_LOOKASIDE_LIST

POOL_TYPE