He implementado PARLANSE, un lenguaje bajo MS Windows que usa pilas de cactus para implementar programas paralelos. Los trozos de pila se asignan por función a y son solo el tamaño correcto para manejar variables locales, push de temperatura de expresión/pops y llamadas a bibliotecas (incluido espacio de pila para que las rutinas de biblioteca funcionen). Tales marcos de pila pueden ser tan pequeños como 32 bytes en la práctica y a menudo lo son.Windows: evite empujar contexto x86 completo en la pila
Todo esto funciona muy bien a menos que el código hace algo estúpido y provoca una trampa de hardware ... y en ese momento aparece de Windows a insistir en empujar todo el contexto máquina x86 "en la pila". Esto es unos 500+ bytes si incluye el FP/MMX/etc. registra, que hace. Naturalmente, una pulsación de 500 bytes en una pila de 32 bytes rompe cosas que no debería. (El hardware empuja unas pocas palabras en una trampa, pero no en todo el contexto).
[EDIT 27/11/2012: Ver this for measured details on the rediculous amount of stack Windows actually pushes]
¿Puedo obtener Windows para almacenar algún lugar del bloque de contexto excepción otra cosa (por ejemplo, a una ubicación específica de un hilo)? Luego, el software podría tomar la excepción presionar sobre la rosca y procesarla sin desbordar mis marcos de pila pequeña .
No creo que esto sea posible, pero pensé que le pediría a un público mucho más grande . ¿Hay una llamada/interfaz estándar del sistema operativo que pueda hacer que esto suceda?
Sería trivial para hacer en el sistema operativo, si podía estafar MS en dejar mi proceso definir opcionalmente una ubicación de almacenamiento contexto, "contextp", que se inicializa para que el comportamiento heredado actual por defecto. volviendo a poner la interrrupt/vector trampa Codee:
hardwareint: push context
mov contextp, esp
... ... con
hardwareint: mov <somereg> contextp
test <somereg>
jnz $2
push context
mov contextp, esp
jmp $1
$2: store context @ somereg
$1: equ *
con los evidentes cambios necesarios para salvar somereg, etc.
[Lo que hago ahora es: verifica el código generado para cada función. Si tiene una posibilidad de generar una trampa (por ejemplo, dividir por cero), o estamos depurando (posible puntero malo deref, etc.), agregue suficiente espacio al marco de la pila para el contexto FP. Los marcos de apilamiento ahora terminan siendo ~~ 500-1000 bytes de tamaño, los programas no pueden recuperarse hasta , lo que a veces es un problema real para las aplicaciones que estamos escribiendo. Así que tenemos una solución viable, pero Complica la depuración]
EDITAR 25 de agosto: Me las he arreglado para conseguir esta historia a un ingeniero interno de Microsoft que tiene la autoridad aparentemente para averiguar quién en realidad podría MS cuidado . Puede haber una débil esperanza para una solución.
EDITAR 14 de septiembre: MS Kernal Group Architect ha escuchado la historia y es comprensivo. Dijo que MS considerará una solución (como la propuesta) pero es poco probable que esté en un paquete de servicio.Puede que tenga que esperar la próxima versión de Windows. (Suspiro ... podría envejecer ...)
EDIT: 13 de septiembre de 2010 (1 año después). Ninguna acción por parte de Microsoft. Mi última pesadilla: ¿tomar una trampa ejecutando un proceso de 32 bits en Windows X64, empujar todo el contexto X64 en la pila antes de que el manejador de interrupciones falsifique empujando un contexto de 32 bits? Eso sería aún más grande (el doble de registros enteros el doble de ancho, el doble de registros SSE (?))?
EDITAR: 25 de febrero de 2012: (han pasado 1.5 años ...) Ninguna reacción por parte de Microsoft. Supongo que simplemente no les importa mi tipo de paralelismo. Creo que esto es un perjuicio para la comunidad; el "modelo de big stack" utilizado por MS en circunstancias normales limita la cantidad de cálculos paralelos que uno puede tener en vivo en cualquier instante al comer grandes cantidades de VM. El modelo PARLANSE le permitirá a uno tener una aplicación con un millón de "granos" en vivo en varios estados de funcionamiento/espera; esto realmente ocurre en algunas de nuestras aplicaciones donde un gráfico de 100 millones de nodos se procesa "en paralelo". El esquema PARLANSE puede hacer esto con aproximadamente 1 Gb de RAM, que es bastante manejable. Si lo intentaste con MS 1Mb "grandes cantidades", necesitarías 10^12 bytes de VM solo para el espacio de pila y estoy seguro de que Windows no te permitirá administrar un millón de subprocesos.
EDITAR: 29 de abril de 2014: (han pasado 4 años). Supongo que MS simplemente no lee SO. He hecho suficiente ingeniería en PARLANSE, por lo que solo pagamos el precio de grandes estructuras de pila durante la depuración o cuando hay operaciones de FP en marcha, por lo que hemos logrado encontrar formas muy prácticas de vivir con esto. MS ha seguido decepcionando; la cantidad de cosas que varias versiones de Windows empujan en la pila parece variar considerablemente y por encima y más allá de la necesidad del contexto del hardware. Hay algunos indicios de que parte de esta variabilidad es causada por la permanencia de productos que no son de MS (por ejemplo, antivirus) metiéndose en la cadena de manejo de excepciones; ¿Por qué no pueden hacer eso desde fuera de mi espacio de direcciones? Cualquiera, manejamos todo esto simplemente agregando un gran factor de pendiente para trampas de depuración/depuración, y esperando el inevitable sistema MS en el campo que excede esa cantidad.
Si aplica parche ntdll.dll en la memoria, los cambios solo se verán en el proceso actual (copiar-en-escribir). Supongo que se usa una dirección directa, no el IAT, pero podría sobrescribir los primeros bytes del manejador con un JMP a su propio código y regresar al anillo 3. Windows podría tener cierta seguridad para evitar este tipo de cosa, pero vale la pena intentarlo. – zildjohn01
Ahora, eso es un pensamiento. ¿Estás sugiriendo que el objetivo del IDT está en ntdll.dll y que puedo pisarlo? ¿Cómo averiguo dónde apunta IDT, o es un punto de entrada publicado en ntdll.dll? ¿Dónde puedo obtener más información sobre la estructura de ntdll.dll? Para repetir una frase que acabo de escuchar, "Esto me mantendrá ocupado un tiempo. Gracias"! –
oops ..He usado IDT, quiero decir vector de interrupción o lo que sea que la arquitectura x86 lo llame en estos días. (Tengo los manuales x86, así que esta es una declaración retórica :-) –