Vous êtes sur la page 1sur 63

UNIVERSIDAD NACIONAL DE LA MATANZA

INFORME DE AVANCE DEL PROYECTO DE INVESTIGACION:


Cdigo del proyecto: C098 -- ING 014 / 2007
Ttulo del Proyecto: Anlisis del comportamiento de hilos de kernel y usuario en un sistema
operativo de estudio

Unidad Ejecutora: Departamento: Ingeniera e Investigaciones Tecnolgicas


Grupo de Investigacin: Sistemas Operativos
Direccin: Florencio Varela 1703 Cdigo Postal: .............................. Tel: 4480-8900

Investigadores Miembros del Equipo:


Ing. Nicanor Blas Casas
Lic. Graciela De Luca
Sr. Martn Cortina
Ing. Gerardo Puyo
Ing. Waldo Valiente
Ing. Sergio Martn
Director:
Hugo Ryckeboer
Legajo UNLM: 1825
Categora Docente: Profesor Titular, dedicacin exclusiva
Direccin particular: San Martn 5591 Lujn de Cuyo - Mendoza.

El presente informe corresponde a las tareas realizadas durante el ao 2010

Registrado en Direccin Nacional de Derecho de Autor


Expediente N 946.157 el 27/7/2011
Todos los Derechos Reservados SECyT-UNLaM

Acerca de este informe


Este informe consta de dos secciones bien diferenciadas.
En la primera seccin trata sobre la segunda parte del estudio de hilos para incorporar al sistema
operativo didctico SODIUM.
En este caso la investigacin se dirigi a los hilos de Kernel profundizando an ms los hilos de
usuario, pero fundamentalmente el estudio se enmarc en los Scheduler Activations que fueron
desarrollados por la Universidad de Washington y que poco a poco se han ido incorporando al
desarrollo de los sistemas operativos si bien las normas POSIX no los incluyen en sus desarrollos.
Este trabajo corresponde a las etapas tercera y cuarta definidas en el proyecto presentado.
El avance de las diferentes etapas implic ligeras modificaciones en las etapas finales del mismo
debido a que se alcanz un grado mayor de conocimiento y familiaridad con el desarrollo, la creacin y
el manejo de los mismos, buscndose alternativas que permitieran una mejor puesta final.
Esta puesta final no solo involucra la forma didctica en que el concepto de hilos, por dems engorroso,
se traslada a los alumnos sino tambin a los profesores y equipo docente que esta y otras ctedras.
Transcribimos aqu la tercera y cuarta etapa de nuestro proyecto.

Tercer Etapa:
Estudio de hilos de kernel. Anlisis de una biblioteca de hilos considerando los estndares
determinados por el lenguaje C y el lenguaje C++. Anlisis de la creacin de los mismos. Anlisis el
Assembler generado por el uso de hilos.
Uso de sentencias bloqueantes para el desarrollo de procesos que manejen ms de un hilo. Anlisis de
los resultados y del comportamiento del resto de los hilos. Creacin de algoritmos para el manejo de
biblioteca. Anlisis del comportamiento. Uso de sentencias no bloqueantes en hilos alternados. Anlisis
de los resultados y del comportamiento del resto de los hilos. En este proyecto el sistema operativo
SODIUM manejar un mnimo de 3 (tres) hilos de kernel, hasta un mximo de 10 (diez) quedando
limitado este mximo a las complicaciones de desarrollo.

Cuarta etapa:
Estudio de hilos (continuacin). Anlisis del comportamiento de hilos con sentencias no
bloqueantes para todos los hilos generados. Sincronizacin de hilos a travs de semforos. Generacin
de hilos modificando variables globales (o variables locales del padre). Generacin de programas con
mutua exclusin utilizando semforos contadores. Generacin de programas con mutua exclusin
utilizando semforos binarios. Anlisis del costo de sincronizacin con semforos. Creacin de hilos
kernel por hilos kernel. Creacin de hilos de kernel por hilos de kernel utilizando la sentencia EXEC en
cualquiera de sus variantes.

Logros Alcanzados.
La nueva forma en el manejo de los conocimientos transferidos a los alumnos nos permiti por primera

vez presentar un trabajo realizado por ellos, con el apoyo y la coordinacin del equipo docente en un
congreso internacional y el mismo fue aprobado. Este congreso fue el CACIC 2010.
Cabe consignar que el mayor trabajo empleado en estas dos etapas corresponde a la programacin de
los mismos de acuerdo a los avances indicados en el informe anterior con los ajustes antes
mencionados

HILOS
Introduccin
El objetivo general de esta investigacin se centra en el diseo de hilos de kernel y en los distintos
mecanismos de administracin de los mismos. Buscar informacin acerca del Manejo y la
comunicacin de Hilos de Tiempo Real, as como de su planificacin para luego poder sacar
conclusiones de un paralelismo entre hilos de usuario.
Posteriormente ser necesario centrarse en el concepto de relaciones entre hilos de usuario e hilos de
kernel y establecer una relacin muchos a algunos de manera prctica en SODIUM.
Como punto de partida nos centramos en esta definicin: En los sistemas operativos tradicionales,
cada proceso tiene su propio espacio de direcciones y un nico flujo (hilo) de control. De hecho, casi es
esa la definicin de proceso. Sin embargo, frecuentemente hay situaciones en las que es deseable contar
con mltiples hilos de control (threads) en el mismo espacio de direcciones ejecutndose quasiparalelamente, como si fueran procesos separados (excepto que comparten el mismo espacio de
direcciones). En las secciones siguientes vamos a discutir esas situaciones y sus implicaciones.
Andrew Stuart Tanenbaum
Adems podemos agregar que un hilo al igual que los procesos, posee un estado de ejecucin y puede
sincronizarse con otros hilos para evitar problemas de compartimiento de recursos. Generalmente, cada
hilo tiene una tarea especfica y determinada, como forma de aumentar la eficiencia del uso del
procesador. Generalmente no se crean hilos si no tienen una funcin preestablecida.
El modelo de los procesos se basa en dos conceptos independientes:
Unidad poseedora de recursos.
Ejecucin secuencial de un programa.

Beneficios
A manera de resumen podemos enumerar los beneficios que produce la incorporacin de los hilos en
forma general y en especial en el sistema operativo didctico que se et desarrollando.
El punto principal es la generacin de procesos de arranque que puedan solaparse en tiempo lo que
redondear una mejor performance, aunque como hemos dicho en diferentes oportunidades la misma
no es prioritaria y si en la descripcin del trabajo con hilos y en las scuencias que oos mismos emplean
para su desenvolvimiento.
Capacidad de Respuesta
Compartir Recursos: Dado que los hilos dentro de un mismo proceso comparten memoria y
archivos, pueden comunicarse unos con otros sin invocar al kernel.
Economa

o Toma menos tiempo crear un nuevo hilo que un proceso


o Toma menos tiempo terminar un hilo que un proceso
o Toma menos tiempo en conmutar entre dos hilos dentro del mismo proceso
Utilizacin de Arquitecturas Multiprocesador
Escalabilidad

Definicin
El hilo es la una secuencia de control que opera dentro del mismo espacio de direcciones (como otra
secuencia de control independiente) del proceso, compartiendo ficheros abiertos y otros recursos.
Necesita un contador de programa, que indica cual es la prxima instruccin a ejecutar, un Stack (pila)
y un conjunto de registros que poseen sus variables. Los hilos existen dentro del contexto de su
proceso.

Estados de un hilo
Los principales estados de los hilos son: Ejecucin, Listo y Bloqueado. No tiene sentido asociar estados
de suspensin de hilos ya que es un concepto de proceso. En todo caso, si un proceso est expulsado de
la memoria principal (ram), todos sus hilos debern estarlo ya que todos comparten el espacio de
direcciones del proceso.

Cambio de estados
Creacin: Cuando se crea un proceso se crea un hilo para ese proceso. Luego, este hilo puede
crear otros hilos dentro del mismo proceso, proporcionando un puntero de instruccin y los
argumentos del nuevo hilo. El hilo tendr su propio contexto y su propio espacio de la columna,
y pasara a la final de los listos.
Bloqueo: Cuando un hilo necesita esperar por un suceso, se bloquea (salvando sus registros de
usuario, contador de programa y punteros de pila). Ahora el procesador podr pasar a ejecutar
otro hilo que est en la final de los Listos mientras el anterior permanece bloqueado.
Desbloqueo: Cuando el suceso por el que el hilo se bloque se produce, el mismo pasa a la
final de los Listos.
Terminacin: Cuando un hilo finaliza se liberan tanto su contexto como sus columnas.
Intermedio: Estado que toma un hilo cuando es interrumpido por otro hilo de mayor prioridad

Tipos de hilos:
Implementaciones
Hay dos grandes categoras en la implementacin de hilos:
Hilos a nivel de usuario.
Hilos a nivel de kernel.
Tambin conocidos como ULT (user level thread) y KLT (kernel level thread)

Los primeros son los que se van a utilizar para encarar los procesos del sistema operativo
didctico. En segundo plano se irn preparando la investigacin fina sobre la aplicacin de hilos
de Kernel.

Hilos de usuario: ULT (User level thread)


En una aplicacin ULT pura, todo el trabajo de gestin de hilos lo realiza la aplicacin y el ncleo o
kernel no es consciente de la existencia de hilos. Es posible programar una aplicacin como multihilo
mediante una biblioteca de hilos. La misma contiene el cdigo para crear y destruir hilos, intercambiar
mensajes y datos entre hilos, para planificar la ejecucin de hilos y para salvar y restaurar el contexto
de los hilos.
Todas las operaciones descritas se llevan a cabo en el espacio de usuario de un mismo proceso. El
kernel continua planificando el proceso como una unidad y asignndole un nico estado (Listo,
bloqueado, etc.).
Su implementacin est a cargo totalmente de la aplicacin, a travs de una biblioteca de hilos
(es rpida ya que no hay llamada al sistema, con cambio de modo) El sistema operativo administra
el proceso como una unidad, y la aplicacin migra de un hilo a otro con su propia administracin. El
kernel no tiene conocimiento de la existencia de los hilos, no involucrar al kernel significa un
intercambio rpido. Esto facilitar la comprensin y el desarrollo de la programacin de hilos.
Solo requiere un Stack y un contador de programa.

Hilos a nivel de ncleo (KLT)


En una aplicacin KLT pura, todo el trabajo de gestin de hilos lo realiza el kernel. En el rea de la
aplicacin no hay cdigo de gestin de hilos.
Cuadro comparativo de los diferentes hilos.
Hilos a nivel de usuario

Hilos a nivel de ncleo

El sistema operativo crea slo un hilo en el El sistema operativo soporta hilos de


ncleo por cada proceso.
ejecucin y proporciona un conjunto de
llamadas al sistema para su manipulacin.
El resto de los hilos son implementados dentro
del proceso (por ejemplo, por el soporte en El sistema crea un hilo de ejecucin por
ejecucin del lenguaje).
cada hilo a nivel de usuario.
Es la nica posibilidad en sistemas operativos Son la unidad de planificacin del Sistema.
que no soportan hilos.
El bloqueo y activacin de hilos corre a
Los cambios de contexto entre los hilos a nivel cargo del ncleo.
de usuario son rpidos, ya que no involucran Se planifican por la poltica del ncleo.
llamadas al sistema.
Los cambios de contexto son manejados por
La planificacin de estos hilos se realiza
el ncleo.
dentro del proceso.
Cuando un hilo invoca una llamada al sistema
bloqueante, se bloquea todo el proceso.

Modelos multihilo
Muchos-a-Uno
Uno-a-Uno
Muchos-a-Muchos

Muchos-a-Uno
Muchos hilos a nivel de usuario se mapean a un hilo del kernel.
Administracin en espacio de usuario (eficiente).
Usado en sistemas que no soportan hilos de kernel.
El proceso entero se bloquea en las llamadas al sistema.
Solo un hilo de usuario puede acceder al kernel al mismo tiempo.

Uno-a-Uno
Cada hilo del nivel de usuario se mapea a un hilo del kernel.
Otros hilos pueden correr durante llamadas al sistema con bloqueo.
Corren en paralelo en multiprocesadores.
Los hilos de usuario crean automticamente un hilo del kernel correspondiente (Esto puede causar
una sobrecarga significativa).
Ejemplos
- Windows 95/98/NT/2000, OS/2

Muchos-a-Muchos
Permite a muchos hilos a nivel de usuario ser mapeados a muchos hilos de kernel.
Permite al sistema operativo crear un nmero suficiente de hilos de kernel (Menor o igual al nmero
de hilos de usuario).
Llamadas al sistema no bloqueantes.
Procesamiento continuo en arquitectura MP.
Ejemplos
Solaris 2, Windows NT/2000 con el paquete ThreadFiber

Problemas con los hilos


Semntica de las llamadas al sistema fork() y exec(), ya que algunos duplican todos los hilos y
algunos no.
Cancelacin de hilos:
Terminacin antes de completado (este hilo se llama el hilo objetivo)

Escenarios diferentes: Cancelacin asncrona


Terminacin inmediata de hilos objetivo: Cancelacin diferida
Peridicamente se comprueban los hilos objetivos
Una seal se genera porque ocurre un evento en particular.
Una seal generada se entrega a un proceso.
Una vez que se entrega la seal debe ser manejada.
Ejemplo: acceso ilegal a memoria
Seales sncronas (entregadas al mismo proceso).
Seales asncronas (p.e. producidas por un evento externo a un proceso corriendo).
Manejadores de seales por defecto y definido por el usuario.
Manejo de seales (en programas multihilo).
Opciones de entrega:
Al hilo al que se le aplica la seal
A todos los hilos en el proceso
A ciertos hilos en el proceso
Asigna un hilo para recibir todas las seales en un proceso
Reserva de hilos
Crea un nmero de hilos al principio y los pone en reserva
Beneficios
Es ms rpido usar un hilo existente que crear uno nuevo a peticin.
La reserva limita el nmero de hilos existentes (importante cuando el nmero de hilos es limitado).
Datos especficos del hilo
En general comparten los mismos datos con el proceso pero pueden necesitar sus propias copias
(privadas)
La mayora de las bibliotecas soportan datos especficos de hilos (p.e. Java)

Funciones que cumple la biblioteca de hilos:


Crear y destruir hilos.
Intercambiar datos y mensajes entre hilos.
Planificar la ejecucin de hilos.
Salvar y restaurar el contexto de los hilos.

Procesos con Hilos


En Windows cada proceso se representa mediante un bloque de ejecucin del proceso (EPROCESS), el
que adems de contener varios atributos del proceso, tambin apunta a otras estructuras importantes,
por ej.: bloque de ejecucin del thread (ETHREAD) y bloque de kernel del proceso (KPROCESS o

PCB). El bloque EPROCESS junto con sus estructuras se almacena en el espacio del sistema, a
diferencia del bloque de entorno del proceso (PEB) que solo existe en el espacio de direcciones del
proceso. Esto se puede ver en el siguiente diagrama:

Adems del EPROCESS, el subsistema de procesos (Csrss) mantiene una estructura paralela de cada
proceso que ejecuta un programa.
La estructura de cada bloque mencionado se detalla a continuacin:

Bloque de ejecucin del proceso (EPROCESS)

Bloque de kernel del proceso (PCB)

Bloque de entorno del proceso (PEB)

A continuacin se detallan las funciones ms usadas a la hora de trabajar con los procesos:
Funcin

Descripcin

CreateProcess

Crea un nuevo proceso y su thread inicial usando la


identificacin de seguridad del llamador.

CreateProcessAsUser

Crea un nuevo proceso y su thread inicial con la


especificacin del campo de seguridad alternativo.

CreateProcessWithLogonW

Crea un nuevo proceso y su thread inicial para que se


ejecute bajo los credenciales del usuario especificado

CreateProcessWithTokenW

Crea un nuevo proceso y su thread inicial con la


especificacin del campo de seguridad alternativo con
opciones adicionales

OpenProcess

Devuelve el handle al objeto especificado del proceso.

ExitProcess

Termina el proceso e informa a todas las libreras asociadas.

TerminateProcess

Termina el proceso sin informar a las libreras asociadas.

FlushlnstructionCache

Vaca cache de instrucciones del proceso especificado.

GetProcessTimes

Obtiene informacin de tiempos del proceso, que describe el


tiempo durante el cual el proceso estuvo en modo de
usuario y de kernel.

GetExitCodeProcess

Devuelve el cdigo de salida para el proceso que indica


cmo y porque se termin el proceso.

GetCommandUne

Devuelve un puntero a la cadena de lnea de comandos


pasado al proceso actual.

GetCurrentProcess

Devuelve el seudo handle para el proceso actual.

GetCurrentProcessId

Devuelve el identificador del proceso actual.

GetProcess Version

Devuelve la mayor y la menor versin de la versin en la


cual el proceso especificado debe ejecutarse.

GetStartuplnfo

Devuelve el contenido de la estructura STARTUPINFO


especificada durante CreateProcess.

GetEnvironmentStrings

Devuelve la direccin del bloque de entorno.

GetEnvironmentVariable

Devuelve la variable del entorno especfica.

Get/SetProcessShutdownPara Define la prioridad y el nmero de intentos de salida para el


meters
proceso actual.
GetGuiResources

Devuelve la cantidad de handles de usuario y GDI.

Los procesos en Windows se crean mediante alguna de las siguientes funciones: CreateProcess,
CreateProcessAsUser, CreateProcessWithTokenW, o CreateProcessWithLogonW. La creacin consta
de varias etapas que son llevadas a cabo mediante tres partes del sistema operativo: librera
Kernel32.dll, ejecutable y el subsistema (Csrss).
Las etapas de creacin de un programa en Windows se pueden resumirse en los siguientes:
Abrir un archivo de imagen (.exe) que ser ejecutado dentro del proceso.
Crear un objeto de proceso ejecutivo.
Crear un thread inicial (pila, contexto y objeto de thread ejecutivo).
Notificar al subsistema acerca del nuevo proceso para que ste pueda crear al proceso y a su thread
inicial.
Empezar la ejecucin del thread inicial (a menos que la bandera CREATE_SUSPENDED fuera
especificada).
En el contexto del nuevo proceso y su thread, completar la inicializacin del espacio de direcciones
(cargando todas las bibliotecas necesarias) y empezar la ejecucin del programa.
Estos pasos se muestran en el siguiente grfico:

Etapa 1: Apertura de la imagen que va a ser ejecutada


El primer paso de CreateProcess es encontrar la imagen apropiada que va a ejecutar el archivo
especificado por el llamador y crear un objeto el cual luego se va a mapear dentro del espacio de
direcciones del nuevo proceso. Si el nombre de la imagen no fue especificado entonces se va a utilizar
el primer parmetro de la lnea de comandos como el nombre de la imagen.
Las imgenes que se pueden activar se detallan en el siguiente esquema:
Si el archivo ejecutable especificado es el .exe entonces se va a usar directamente. En caso contrario,
CreateProcess ir a travs de una serie de pasos adicionales para encontrar una imagen de soporte para
ejecutarlo. De acuerdo a tipo especificado, se va a utilizar alguna de las siguientes imgenes de soporte:

Etapa 2: Creacin del objeto de proceso ejecutivo


Una vez que el archivo ejecutable es abierto, CreateProcess crea un objeto de proceso ejecutivo para
correr la imagen a travs de la llamada a la funcin interna del sistema NtCreateProcess. La creacin de

este objeto involucra los siguientes pasos:


Inicializar el bloque EPROCESS.
Crear el espacio de direcciones inicial del proceso.
Inicializar PCB.
Finalizar la inicializacin del espacio de direcciones del proceso (lo que incluye la inicializacin de la
lista de trabajo y los descriptores del espacio de direcciones virtual y mapeo de la imagen dentro del
espacio de direcciones).
Inicializar PEB.
Completar la inicializacin del objeto de proceso ejecutivo.

Etapa 3: Creacin del thread inicial con su pila y contexto


En este momento el EPROCESS ya est inicializado completamente pero aun sigue sin tener un thread,
con lo cual todava no puede realizar ninguna operacin. Antes que el thread se cree, el necesita una
pila y un contexto donde ejecutarse.
El thread se crea mediante la funcin NtCreateThread. Su parmetro (que se especifica mediante
CreateThread) es la direccin del PEB. NtCreateThread llama a PspCreateThread y realiza los
siguientes pasos:
El contador de threads en el proceso se incrementa.
ETHREAD se crea y se inicializa.
Se genera un identificador para el nuevo thread.
El TEB se inicializa en el espacio de direcciones del proceso en modo de usuario.
La direccin inicial del thread en modo de usuario se almacena en el ETHREAD.
Se llama a KeInitThread para que cargue el bloque KTHREAD. Las prioridades base inicial y actual
del thread se cargan a la prioridad base del proceso, y su afinidad y el quantum se cargan al proceso.
Se llama a cualquier rutina registrada de notificacin de la creacin del proceso.
El parmetro de acceso del thread se establecido al punto del parmetro de acceso del proceso, y la
verificacin del acceso se realiza para determinar donde el llamado tiene derecho de crear su thread.
Finalmente el thread est preparado para la ejecucin.

Etapa 4: Notificacin del subsistema acerca del nuevo proceso


Kernel32.dll enva un mensaje al subsistema para que ste pueda cargar al nuevo proceso y a su thread.
Este mensaje contiene:
Handles del proceso y del thread.
Entradas en las banderas de creacin.
Identificador del creador del proceso.
Una bandera que indica si el proceso pertenece a la aplicacin.
El subsistema, al recibir la llamada, realiza los siguientes pasos:
CreateProcess duplica el handle del proceso y del thread, es decir, que el contador de usado pasa a ser

2.
Si la clase de prioridad del proceso no se especifica, CreateProcess la establece mediante un algoritmo
especfico.
Se aloja el bloque de proceso de Csrss.
El puerto de excepciones del proceso se establece para ser el puerto de funcin general del subsistema.
Si el proceso es debugueado, el puerto del debug del proceso se establece como puerto de funcin
general del subsistema.
Se aloja y se inicializa el bloque de thread de Csrss.
CreateProcess incierta al thread a la lista de threads del proceso.
La cantidad de procesos en esta sesin se incrementa.
En nivel de terminacin del proceso se establece al de por defecto (0x280).
El nuevo bloque del proceso se incierta dentro de la lista de procesos del subsistema.
La estructura de datos por proceso usada por el subsistema en modo de kernel se aloja y se inicializa.
Se despliega el cursor de inicio de la aplicacin.

Etapa 5: Empezar la ejecucin del thread inicial


A menos que el llamador ha especificado la bandera CREATE_SUSPENDED, el thread inicial se
resume para que pueda empezar su ejecucin.

Etapa 6: Completar inicializacin del proceso en el nuevo contexto


El nuevo thread cobra vida al ejecutar KiThreadStartup (rutina de inicio del thread en modo de
kernel). KiThreadStartup disminuye el nivel de IRQL del thread desde DPT/dispatch hasta el nivel
APC y luego llama a PspUserThreadStartup (rutina del sistema de inicializacin de threads).
Finalmente la imagen comienza a ejecutarse en modo de usuario cuando el cargador de inicializacin
vuelve al APC despachador del modo de usuario, el cual despus llama a la funcin del inicio del
thread que fue colocada a la pila del usuario cuando el APC del usuario fue entregado.
Threads
En el nivel del sistema operativo, el thread se representa mediante el bloque ejecutivo de thread
(ETREAD). Al igual que con EPROCESS, el bloque ETHREAD y las estructuras a la que apunta se
almacenan en espacio de direcciones del sistema, a excepcin del bloque de entorno de thread (TEB)
que est en el espacio de direcciones del proceso. Tambin el subsistema de procesos (Csrss) mantiene
una estructura paralela para cada thread creado en un proceso.
Las estructuras que utiliza un thread se detallan a continuacin:

Estructura de ETHREAD

Estructura del TCB

Estructura del TEB


El ciclo de vida del thread empieza cuando el programa crea un nuevo thread. Los siguientes pasos se
realizan por la funcin CreateThread de la librera Kernel32.dll:
Crea la pila en el modo de usuario para el thread dentro del espacio de direcciones del proceso.
Inicializa el contexto de hardware del thread.
NtCreateThread en llamada para crear el objeto ejecutivo del thread en el estado de suspendido.
CreateThread notifica al subsistema acerca del nuevo thread, y el subsistema hace algn trabajo de
inicializacin del nuevo thread.
El handle y el identificador del thread son devueltos al llamador.
A menos que la bandera CREATE_SUSPENDED fuera especificada, el thread se resume para que
pueda ser planeado para la ejecucin.
Existen algunas herramientas a travs de las cuales se puede examinar la actividad de los threads. Estas
son: Perfmon, Pviewer, Pstat, Qslice, Tlist, KD !thread, Pslist y Process Explorer.
Windows implementa un sistema de prioridades apreciativo; el thread con la prioridad ms alta siempre
se ejecuta, con la precaucin de que el proceso seleccionado para la ejecucin pueda estar limitado por

procesador en el cual el thread es alojado para la ejecucin, este fenmeno se conoce como afinidad del
procesador. Por defecto, los thread pueden ejecutarse en cualquier procesador disponible, pero se
puede cambiar la afinidad del procesador usando alguna de las funciones de planificacin o
estableciendo una mscara de afinidad en el encabezado de la imagen.
Cuando un thread el elegido para ejecutarse, se ejecuta durante una cantidad de tiempo llamado
quantum. El quantum puede variar de un sistema a otro y de un proceso a otro por alguna de las
siguientes tres razones: propiedades de configuracin (quantum largo o corto), el estado del proceso (de
primer plano o de fondo) o usar un objeto de trabajo (job).
El cdigo de planificacin est implementado en el kernel. No hay una sola rutina o un solo mdulo de
planificacin, sino que el cdigo est repartido por todo el kernel en el cual los eventos de la
planificacin ocurren. Las rutinas que realizan este trabajo se llaman despachador. Los eventos que
requieren que un thread sea despachado son las siguientes:
El thread pasa de preparado a en ejecucin.
El thread deja el estado de ejecucin porque termin su quantum, el mismo se termin, en caso de
excepcin o cuando entra al estado de espera.
Se cambia la prioridad del thread.
Se cambia la afinidad del procesador.
En estos casos, Windows debe determinar el siguiente proceso que debe ejecutarse. Cuando lo
selecciona, realiza un cambio de contexto a l. Es el procedimiento de almacenar el estado voltil de la
mquina asociado con el thread en ejecucin, cargar el estado voltil del otro thread y empezar la
ejecucin del nuevo thread.
Windows tiene 32 niveles de prioridad que van desde 0 y hasta 31 y son las siguientes:
16 niveles de tiempo real (16 - 31)
15 niveles variables (1 - 15)
1 nivel del sistema (0)
Los niveles de prioridades se asigna desde dos puntos de vista diferentes: API y kernel. Las API
organizan los procesos primero por las clases de prioridades a las cuales stos se asignan al momento
de la creacin (Tiempo real, Alta, Superior a la Normal, Normal, Inferior a la Normal y Ocioso) y luego
por la prioridad relativa del thread individual (Tiempo crtico, Alta, Superior a la Normal, Normal,
Inferior a la Normal, Baja y Ocioso).

Mientras que los procesos tienes solo una prioridad, los threads tienen dos: actual y base. Las
decisiones de planificacin se toman basndose en la prioridad actual. El sistema bajo ciertas
circunstancias incrementa la prioridad de lo threads en el rango dinmico (1 - 15), pero nunca toca las
prioridades de los threads en el rango de tiempo real (16 - 31), asique ellos tienen las mismas
prioridades base y actual.
La prioridad base del thread se hereda de la prioridad base del proceso, la cual, a su vez, por defecto se
hereda de la prioridad base del proceso que lo cre. La prioridad del proceso despus de su creacin
puede ser cambiada mediante la funcin SetPriorityClass. Normalmente la prioridad base del proceso
(y por ende de sus threads) es el valor intermedio de cada rango de prioridades.
Tambin se pueden aumentar o disminuir las prioridades que estn fuera del rango dinmico, es decir,
las que son de tiempo real. Pero para realizarlo, es necesario tener los privilegios de incremento de
prioridades de la planificacin.
Un thread (tanto en Windows 2000 como en Windows XP) puede encontrarse en uno de los siguientes
estados (los nmeros representan valores del contador de estado de la performance del thread):

Preparado: un thread en este estado est esperando para ser ejecutado. Cuando se busca un thread para
la ejecucin, el despachador revisa solamente esta cola.
En espera: un thread en este estado ha sido seleccionado para ejecutarse en un procesador particular.
Cuando la condicin es correcta, el despachador cambia de contexto a este thread. En esta cola, para
cada procesador solo puede existir un thread.
En ejecucin: cuando se cambia de contexto a un thread, ste entra a este estado y pasa a ejecutarse.
En espera: un thread puede entrar a este estado en una de las siguientes situaciones: un thread
voluntariamente espera algn objeto para su sincronizacin, el sistema operativo espera a un thread, o
el sistema de entorno dirige al thread para que entre al estado de espera. Cuando un thread sale de este
estado, dependiendo de su prioridad, puede ir directamente a la ejecucin o volver a la cola de procesos
preparados.
Transicin: un thread entra a este estado cuando est preparado para ser ejecutado pero su pila de
kernel no est paginada en la memoria. Cuando esta pila vuelve a la memoria, el thread pasa al estado
de preparados.
Terminado: cuando un thread finaliza su ejecucin, entra a este estado. Una vez terminado, ETB puede
o no ser desalojado.
Inicio: este estado es usado internamente cuando se crea un thread.
En Windows Server 2003 este esquema cambia con la aparicin de un nuevo estado llamado
preparado diferido. Se usa para threads que han sido seleccionados para la ejecucin en un procesador
determinado pero todava no se han planificado. Este estado se agrega para que el kernel pueda
minimizar la cantidad de tiempo durante el cual se realiza el bloqueo del sistema en la base de datos del
planificador.

Para tomar las decisiones de la planificacin de threads, el kernel mantiene en conjunto de estructuras
de datos llamado base de datos del despachador. sta almacena que threads estn preparados para la
ejecucin y que procesadores ejecutan que threads.

Las colas de preparados del despachador (hay una para cada una de las 32 prioridades) contienen los
threads que estn preparados para la ejecucin.
Quantums
En Windows 2000 Pro y en Windows XP, los threads por defecto se ejecutan durante 2 intervalos de
reloj; en cambio, en Windows Server por defecto son 12 intervalos. La razn para tener un valor ms
grande es la de minimizar los cambios de contexto.
La longitud del intervalo vara acorde al hardware. Por ejemplo, el intervalo en la mayora de los
sistemas x86 de un procesador es de 10 ms y en la mayora de los x86 de multiprocesadores es de 15
ms.
Cada proceso tiene un valor de quantum en el bloque del proceso de kernel. Este valor se usa cuando se

da un nuevo quantum a thread. A medida que un thread se ejecuta, su quantum se reduce con cada
intervalo de reloj.
Internamente, el valor del quantum se almacena como un mltiplo de 3 del nmero de intervalos del
reloj. Es decir, que en Windows 2000 y Windows XP el quantum es de 6 (2*3) y en Windows Server es
de 36 (12*3).
Cuando un thread que tiene su prioridad actual menor a 16 y su prioridad base menor a 14 llama a la
funcin de espera (WaitForSingleObject o WaitForMultipleObjects) y es satisfecha inmediatamente, su
quantum se reduce en 1 unidad. En el caso de que la espera no se satisface inmediatamente, a los
threads con prioridad menor a 16 tambin se reduce su quantum en 1. Sin embargo, antes de la
reduccin, si su prioridad es mayor o igual a 14, su quantum se resetea al turno completo. Esto tambin
se hace para los threads con la prioridad menor a 14 en el caso de que no se ejecuten con el incremento
especial de prioridades y si reciben el incremento de prioridades como resultado de una operacin sin
espera.
Se puede cambiar el quantum de threads para todos los procesos, pero eligiendo solo entre 2 valores:
corto (2 intervalos) o largo (12 intervalos).
En los sistemas Windows NT inferiores a la versin 4.0, cuando se traa una ventana a la primera plana,
todos los threads de la misma reciban una inyeccin del quantum de 2 unidades. Esto se cambi en la
versin 4.0, haciendo que se inyecte el triple del quantum original, es decir, que los threads en la
primera plana tengan el quantum de 6. Con esto se logra que cuando se cambia de un proceso intenso a
uno nuevo, este ltimo recibe una porcin de CPU ms significativa que los procesos de segunda plana.
Escenarios de planificacin
Primero de ellos es cuando un thread libera voluntariamente el uso del CPU tras entrar en el estado de
espera mediante el llamado de una de las funciones de espera.
En este caso, cuando el thread actual pasa al estado de espera, en su lugar entra uno nuevo desde la cola
de procesos preparados.

El segundo es la expropiacin del CPU. En este caso, un thread de menor prioridad es expropiado y en
su lugar entra uno nuevo de mayor prioridad. Cuando esto sucede, el thread se coloca al principio de la
cola de procesos preparados de la prioridad en la que se ejecutaba.

El ltimo caso es por la terminacin del quantum. Si la prioridad del thread se reduce, entonces
Windows busca un nuevo thread para ser ejecutado que tenga una prioridad superior a la del thread
anterior. Si la prioridad no se reduce y hay otros threads en la cola de preparados de la misma prioridad,
entonces Windows selecciona al siguiente thread de la cola y mueve al thread anterior al final de la
misma cola.

El contexto de los threads y los procedimientos de cambio de contexto dependen de la arquitectura de


los procesadores. Un cambio tpico conlleva el almacenamiento y la carga de lo siguiente:
Puntero de instrucciones.
Punteros de la pila de usuario y de kernel.
Puntero al espacio de direcciones del thread actual.
Incremento de la prioridad
Hay cinco casos en los cuales es posible realizarlo:
Al finalizar las operaciones de entrada/salida.
Despus de esperar la ejecucin de eventos y semforos.
Despus de que los threads de primera plana completen la operacin de espera.
Cuando los threads de GUI despierten debido a la actividad de ventanas.
Cuando se produce inanicin.
1) Windows da un incremento temporal de prioridades tras la terminacin de alguna operacin de
espera para que los threads que estaban esperando por E/S tangan ms chances de ejecutarse enseguida.
El incremento siempre se aplica a la prioridad base del thread y no a la prioridad actual. El valor del
incremento vera segn el dispositivo de E/S:

Dispositivo

Incremento

Disco, CD-ROM, puerto paralelo, video

Red, puerto seria, casillero de mail, tubera

Teclado, mouse

Sonido

El incremento solo se aplica a los threads en el rango dinmico de prioridades (entre 0 y 15). Sin
importar cun grande sea el incremento, el thread nunca pasar a tener una prioridad superior a 15.
2) En los casos cuando una espera de la ejecucin de algn evento o algn semforo es satisfecha, el
thread recibe un incremento de 1.
3) Cuando un thread en primera plana complete la operacin espera en un objeto de kernel, la funcin
de kernel KiUnwaitThread incrementa su prioridad actual (y no base) al valor establecido en el
parmetro PsPrioritySeparation.
4) Los threads que poseen ventanas reciben un incremento adicional de 2 cuando despiertan tras su
actividad, por ejemplo cuando llega un mensaje.
5) Una vez por segundo el administrador de balance (thread del sistema que siempre existe para
realizar el manejo de funciones de memoria) escanea las colas de procesos preparados para encontrar
los threads que han estado en la cola de preparados (sin pasar a la ejecucin) por ms de 4 segundos. Si
los encuentra, les sube la prioridad a 15. En Windows 2000 y XP, el quantum del thread se establece en
2 veces ms grande que el quantum del proceso y en Windows Server 2003 se establece en 4 veces.
Una vez que el quantum expire, la prioridad del thread decae inmediatamente a su prioridad base
original. Si el thread no finaliz y hay un thread de mayor prioridad preparado para ser ejecutado, el
thread anterior vuelve a la cola de preparados donde otra vez estar esperando el incremento si pasen
ms de 4 segundos.
Sistemas multiprocesadores
En los sistemas multiprocesadores el cambio de contexto en ms complejo que en los sistemas de un
solo procesador debido a que Windows intenta planificar threads en el procesador ms ptimo para
cada thread, teniendo en cuenta tanto los procesadores preferidos y anteriores de los threads como la
propia configuracin del sistema multiprocesador.
En los sistemas Windows 2000 y XP multiprocesadores, las colas y el resumen de los procesos
preparados tienen la misma estructura que en los sistemas de un procesador. Pero en los sistemas
multiprocesadores tambin se agregan dos mscaras de bits que representan en estado de los
procesadores en el sistema y son las siguientes:
La mscara del proceso activo (KeActiveProcessors) que tiene seteado un bit por cada procesador
usable en el sistema.
Resumen ocioso (KiIdleSummary) en el cual el bit seteado representa a un procesador libre.
En Windows 2000 y XP se utilizan 2 bloqueos de kernel para sincronizar el acceso al despachador de
threads: el bloqueo del despachador (KiDespatcherLock) y el bloqueo del intercambio del contexto
(KiContextSwapLock).
En Windows Server 2003 multiprocesador, para mejorar la escalabilidad incluyendo la concurrencia de
la planificacin de los threads, tiene colas de procesos preparados del despachador por cada procesador.

En este caso, cada CPU chequea su propia cola de preparados por el siguiente thread a ejecutar sin la
necesidad de bloquear las colas de preparados globales.

Tanto las colas como los resmenes de procesos preparados de cada procesador son parte del bloque de
control del procesador (PRCB). Dado que en sistemas multiprocesadores un procesador puede necesitar
modificar la estructura de datos por CPU de otro procesador, estas estructuras se sincronizan mediante
un nuevo bloqueo encolado por PRCB que se encuentra en el IRQL SYNCH_LEVEL. A diferencia de
stas, las colas de procesos preparados diferidos de cada procesador no son sincronizadas por el
bloqueo de PRCB debido a que cada procesador manipula solo su propia cola de procesos preparados
diferidos.
Los sistemas Windows XP y Server 2003 soportan dos tipos de sistemas multiprocesadores
hyperthread:
Los procesadores lgicos no cuentan los lmites de licencia de procesadores fsicos.
Cuando se escoge un procesador para el thread, si es un procesador fsico con todos sus procesadores
lgicos disponibles, se selecciona un procesador lgico de ese fsico, a diferencia de seleccionar un
procesador lgico disponible en uno fsico en el cual se ejecuta un thread en otro de sus procesadores
lgicos.
Otro tipo de sistemas multiprocesadores soportados por Windows XP y Server 2003 es con la
arquitectura de acceso no uniforme a la memoria (NUMA). En el sistema NUMA los procesadores se
agrupan en pequeas unidades llamada nodos. Cada nodo tiene su propio procesador y memoria y se
conecta a un sistema ms grande a travs de un bus de cache coherente. El kernel almacena la
informacin de cada nodo en una estructura de datos llamada KNODE.
Cada thread tiene una mscara de afinidad en la cual se especifica los procesadores en los cuales un
thread pueda ejecutarse. La mscara de afinidad de los threads se hereda de la mscara de afinidad del
proceso. Para optimizar la carga de trabajo de los procesadores, las aplicaciones pueden cambiar esta
mscara para los threads mediante alguno de los siguientes mtodos:
Llamando la funcin SetThreadAffinityMask para establecer la afinidad de un thread en particular.

Llamando la funcin SetProcessAffinityMask para establecer la afinidad de todos los threads en un


proceso.
Llamando a la funcin SetInformationJobObject para hacer que un proceso sea miembro de un trabajo
(job) que tiene su propia mscara de afinidad.
Especificando la mscara de afinidad en el encabezado de la imagen.
Tambin es posible establecer la bandera de un procesador para la imagen. Con esto se logra que
cuando el sistema elige un procesador en el momento de la creacin del proceso y asignndolo como su
mscara de afinidad, empezando por el primer procesador y luego yendo de modo round-robin por
todos los procesadores.
Cada thread tiene dos nmeros de CPU almacenados en el KTHREAD:
Procesador ideal: procesador preferido en el cual los threads van a ejecutarse.
ltimo procesador: procesador en el cual thread se ejecut la ltima vez.
El procesador ideal se selecciona cuando se crea el thread usando un valor almacenado en el bloque del
proceso. Este valor se incrementa cada vez que se crea un thread logrando que el procesador ideal de
cada nuevo thread vaya rotando por todos los procesadores del sistema.
En los sistemas hyperthread, el nuevo procesador ideal ser el primer procesador lgico en el siguiente
procesador fsico.
En los sistemas NUMA, cuando un thread se crea se selecciona un nodo ideal. La asignacin comienza
por el nodo 0, luego sigue con el 1 y as sucesivamente. Luego se selecciona un procesador ideal para
cada nuevo thread en el proceso dentro de los procesadores del nodo actual.
Algoritmos multiprocesadores de planificacin de los threads
Bsicamente hay dos decisiones a tomar:
Elegir un procesador para el thread que quiere ejecutarse.
Elegir un thread en un procesador que necesita hacer algo.
Cuando hay un thread preparado para la ejecucin, Windows primero trata planificar la ejecucin del
thread en un procesador inactivo. Si hay varios procesadores inactivo, la preferencia se da al
procesador ideal, luego al ltimo procesador del thread o si no al procesador actual. En Windows 2000
si ninguno de esos procesadores es inactivo, se elige el primero de los procesadores inactivo en los
cuales el thread puede ejecutarse.
Si no hay procesadores inactivos cuando un thread quiere ejecutarse, Windows compara la prioridad
del thread en ejecucin en el procesador ideal del thread para determinar donde deber ser desalojado el
thread. En Windows 2000 la mscara de afinidad del thread puede excluir al procesador ideal. Si esto
sucede, Windows selecciona al procesador anterior. Si este procesador no est en la mscara de
afinidad del thread, se selecciona el procesador con el mayor nmero en el cual el thread puede
ejecutarse.

Trabajos
Un objeto de trabajo es un objeto de kernel que es numerable, reservable y compartible que permite
controlar uno o varios procesos como un grupo. El objetivo principal del trabajo es agrupar vario
procesos para manejarlos como una sola unidad. Un proceso puede ser miembro de un solo trabajo.
Tambin almacena una informacin bsica de la cantidad de los procesos pertenecientes al mismo y de
los procesos que pertenecan antes a l pero que se hayan terminado. Tambin se pueden poner lmites

de seguridad y de la interface de usuario sobre los procesos del trabajo.

Pila de un hilo
Todos los hilos comparten el mismo espacio de memoria, pero cada uno ha de tener su propia pila. A
continuacin se detallara el funcionamiento de la pila y como los hilos tienen obtienen su propia pila.

Introduccin
La pila es una de las estructuras ms importantes dentro del modelo de memoria de un proceso. Cada
vez que se ejecuta la funcin CreateProcess (ya sea iniciando un programa o haciendo una llamada
directa), se crea un espacio de direcciones virtuales de 4 Gb, pero otras de las operaciones que se hace
son:
Reservar un bloque de memoria auxiliar dentro del espacio de direcciones del proceso. Este espacio se
denomina Heap.
Crear el hilo principal de ejecucin a travs de la funcin CreateThread. Una de las operaciones que
hace esta funcin es reservar un espacio de memoria denominado Stack.
Los hilos comparten el mismo segmento de codigo y de datos. Esto permite que muchos hilos ejecuten
la misma rutina, llamen a las mismas funciones y hasta vayan a ejecutar alguna funcin de otro hilo.
Cada hilo tiene su propia pila, como la pila es un segmento en la memoria del mapa del proceso y como
los hilos pueden ver toda la memoria que posee el proceso, todos los hilos pueden ver las pilas de los
dems hilos y hasta modificarlas. Aqu se utiliza proteccin a nivel de PGINA por parte de la CPU.

La pila:
Una pila, como otras muchas estructuras de datos, se almacena internamente como un array o vector.
Ejemplo pila de enteros int DatosPila [100] esta pila podr albergar hasta 100 nmeros enteros, y
cuando se intente introducir el elemento 101, se producir un error. Este error se denomina
Desbordamiento de Pila, o Stack Overflow. La pila se va llenando de la posicin superior hacia la
inferior, es decir, el primer elemento residir en la posicin de memoria mayor y luego ir
descendiendo.
Para representar una pila, adems de un array, hace falta un puntero que indique en qu posicin se
sita el elemento superior (el decir, el ltimo introducido).
Agregamos el puntero a la pila anterior:
Int DatosPila [100]
Int *PunteroPila
Al meter elementos en la pila no estamos reservando ningn espacio, sino que simplemente ocupamos
un espacio ya reservado. De igual modo, al sacar elementos de la pila tampoco liberamos, sino que lo
dejamos en la misma situacin para poder ser utilizado con posterioridad. Ni siquiera se limpia el
contenido con ceros, sino que se deja con el valor de la ltima variable que ha ocupado esa posicin
(como luego veremos, esta es la razn por la que las variables locales pueden tomar valores correctos
cuando hemos olvidado inicializarlas).

Debido a que las operaciones de Push y Pop no reservan ni liberan memoria, podemos garantizar que
su ejecucin es muy rpida, porque simplemente se desplaza el puntero por el espacio de la pila.

Caractersticas de la pila para un hilo:


Su tamao es un atributo de creacin: Ejemplo de funciones que obtienen y setean el tamao para la
pila.
Int pthread_attr_getstack (const pthread_attr_t *restrict attr, void **restrict
stackaddr, size_t *restrict stacksize);
Int pthread_attr_setstack
stacksize);

(pthread_attr_t

attr,

void

*stackaddr,

size_t

Los atributos especifican el rea de almacenamiento para ser usado por la pila del hilo creado.
La base (direccin ms baja que sea direccionable) es en este ejemplo stackaddr y el tamao
de almacenamiento (tamao de la pila) es stacksize. Ambos parmetros estan expresados
en bytes. El tamao de la pila debe ser mayor que un mnimo definido por ejemplo en una
variable THREAD_STACK_MIN.
El tamao por omisin del atributo: Para procesadores de 32 bits suele ser de 1MB (0x00100000 en
hexadecimal) y 2MB para procesadores de 64 bits.
Hay que tener especial cuidado en cuanto al tamao, debe ser lo suficientemente grande como para que
las distintas pilas no se solapen unas con otras.
Tiene que estar ubicada dentro del espacio de direcciones virtuales del proceso.

Caractersticas de los atributos de un hilo


Pila privada
Copia privada de los registros de la CPU (incluyendo IP)
Estado de la CPU privado.
Datos de la CPU privado.
Recursos del Sistema privados.
Un proceso padre.
Prioridad de ejecucin y quantum de tiempo
Cola de sincronizacion

Uso de la Pila
Al crear un proceso, automticamente se crea el hilo principal de ejecucin a travs de la funcin
CreateThread. Esta funcin una de las tareas que hace es crear la pila. Evidentemente, si nuestra
aplicacin es multi-hilo, tendremos una pila por cada uno de los hilos de ejecucin que hayamos
creado.

La pila, al representarse en memoria como un vector, no ser ms que un bloque de memoria contigua.
As que la pila de un hilo no va a ser menos.
La pila, como cualquier estructura que reside en memoria, ocupar pginas (de 4KB cada una en
procesadores x86). As que una pila de 1MB ocupar 256 pginas de memoria.
Los datos almacenados en cada pila de ejecucin slo son accesibles por el thread propietario de dicha
pila. En cambio, los datos almacenados en el heap y los datos almacenados en forma esttica pueden
ser compartidos por todos los threads del proceso; razn por la cual, puede ser necesario establecer
mecanismos de sincronizacin que controlen el acceso a estos datos.

Otros manejos de la Pila


Al crearse la pila, se compromete el espacio indicado durante el enlazado, que como ya sabemos es por
defecto de 16 KB, es decir 4 pginas. La ltima pgina que se comprometa tendr una caracterstica
especial: se marcar con la bandera de proteccin PAGE_GUARD (indica el final de las paginas
comprometidas)
El aspecto de la pila de un hilo recin iniciado puede ser como el que aparece en la siguiente figura:
La pila completa est en estado reservado (pginas de color blanco), las 4
primeras pginas han sido comprometidas (en color gris) y la ltima pgina
comprometida ha sido marcada como pgina de guarda (borde en rojo). Como ya
hemos visto, el contenido de las pginas se marca con un interrogante porque
contendrn datos basura, posiblemente restos de las ltimas variables que han
residido en esas posiciones de memoria.
Bien, conforme va evolucionando la ejecucin de nuestro proceso, la pila se va
llenando (cuanto ms profundo sea el rbol de llamadas a funciones) o vaciando (segn estas funciones
van retornando). Puede ser que no sea necesario sobrepasar el almacenamiento de las 3 primeras
pginas (12 KB), as que en este caso tan slo habremos consumido 16 KB de memoria para almacenar
la pila. Pero en otros muchos casos, llegar un momento en que algn dato sea necesario guardarlo en
la cuarta pgina. En ese momento, al ser una pgina de guarda, se producir una excepcin de tipo
STATUS_GUARD_PAGE. El sistema es capaz de gestionar sus propias excepciones, as que la
capturar y realizar las siguientes operaciones:
Comprometer una pgina ms de memoria (en nuestro caso, la 5)
Marcar con PAGE_GUARD la nueva pgina comprometida.
Volver a guardar el dato que no ha podido ser guardado por la excepcin (recordad que la bandera
PAGE_GUARD desaparece despus del primer acceso).
El nuevo aspecto de la pila puede observarse en el siguiente esquema:
Como hemos visto, este mecanismo permite que la pila vaya creciendo conforme
necesita ms espacio. Si el rbol de llamadas disminuye, las pginas restantes de la
pila no se liberan, sino que permanecen comprometidas para acelerar su acceso en
un futuro.
Ahora supongamos que el rbol de llamadas crece hasta que es necesario acceder a

la pgina 8 (la penltima). Al ser una pgina de guarda, se producir una excepcin y el sistema la
capturar del mismo modo y realizar las mismas operaciones, excepto que si la nueva pgina
comprometida (la 9) es la ltima, no se marcar como pgina de guarda. El estado en que quedara la
pila sera el siguiente:

Si siguen producindose llamadas anidadas (y/o recursivas) y la pila intenta acceder


a la 9 pgina (que est reservada, pero no comprometida), se producir una
violacin de acceso, y para evitar males mayores el sistema elimina
automticamente el proceso padre del hilo.
Como hemos visto, el sistema es capaz, tanto de hacer que la pila crezca
automticamente, como de asegurarse de que no crece indefinidamente. Pero para realizar esta ltima
tarea, el tamao til de la pila se ve reducido en una pgina, ya que la pgina superior nunca ser
comprometida.
Esto se hace as para evitar sobrescribir pginas de memoria que estn por encima de la pila. Si
suponemos que la ltima pgina se compromete normalmente, el sistema podra continuar
almacenando datos en la pila hasta su lmite superior, y si al intentar acceder a la siguiente pgina (la
que est por encima de la 9, que ya no pertenece a la pila). Si adems se da la casualidad de que esa
pgina ha sido comprometida (porque en ese punto reside otra estructura de datos), no se producira
ninguna excepcin y todo parecera funcionar correctamente, por lo que el error sera difcilmente
detectable.

Tarea
Una tarea es una unidad de trabajo que puede ser despachada, ejecutada o suspendida por el
procesador, es decir, es un conjunto de segmentos u objetos ubicados en memoria, que, al ser
procesados por la CPU, producen un resultado final, que es el objetivo de la tarea. Esta puede servir
para ejecutar un programa, un servicio del sistema operativo, una rutina de interrupcin o excepcin o
incluso el kernel o ncleo. Cuando se tiene un sistema multitarea, el procesador puede atender varias
tareas como si se estuviesen ejecutando simultneamente.
Administracin de tareas
Lo primero: las facilidades de administracin de tareas de la arquitectura IA-32 slo estn disponibles
cuando el procesador est en modo protegido.
Una tarea es una unidad de trabajo que un procesador puede enviar, ejecutar, o suspender. Puede ser
usada para ejecutar un programa, una tarea o proceso, una utilidad de servicio del sistema operativo, un
administrador de interrupciones o de excepciones, o una utilidad ejecutable o del kernel.
La IA-32 proporciona mecanismos para guardar el estado de una tarea, para enviar tareas a ejecucin, y
para cambiar de una tarea a otra. Cuando se opera en modo protegido, todas las ejecuciones del
procesador ocurren desde una tarea. Incluso los sistemas simples deben definir como mnimo una tarea.
Los sistemas ms complejos pueden usar las facilidades de administracin de tareas del procesador
para soportar aplicaciones multitarea.

Estructura de la tarea
Una tarea est compuesta por dos partes: un espacio de ejecucin y un segmento de estado de tarea
(task-state segment - TSS). El espacio de ejecucin de tareas consiste en un segmento de cdigo, un
segmento de pila, y uno o ms segmentos de datos (Figura 1). Si un sistema operativo o un programa
usa el mecanismo de proteccin de niveles de privilegios del procesador, el espacio de ejecucin de
tareas proporciona tambin una pila aparte para cada nivel de privilegios.
El TSS especifica el segmento que compone al espacio de ejecucin de la tarea y proporciona un lugar
de almacenamiento para la informacin de estado de la tarea. En sistemas multitarea, la TSS
proporciona tambin un mecanismo para enlazarlos.
Una tarea se identifica por el selector de segmento para su TSS. Cuando se carga la tarea en el
procesador para su ejecucin, el selector de segmento, la base de direcciones, el lmite, y los atributos
del descriptor de segmento del TSS se cargan en el registro de tarea (task register - TR). Si est
activada la paginacin para la tarea, la direccin base del directorio de pginas usado por la tarea se
carga en el registro de control CR3.

Segmento

Segmento de
cdigo

de estado

Segmento de
datos

de tarea
(TSS)

Segmento de pila
(Nivel de
privilegio actual)
Segmento de
cdigo

Registro de tareas

Nivel Priv 1
Segmento de
datos
Nivel Priv 2

CR3

Segmento
de pila

Estructura de una tarea


Estado de la tarea
Los siguientes tems definen el estado de la actual tarea en ejecucin:

El espacio de la tarea actual en ejecucin, definida por el selector de segmento en los registros
de segmentos (CS, DS, SS, ES, FS y GS).
El estado de los registros de propsito general.
El estado del registro EFLAGS.
El estado del registro EIP.
El estado del registro de control CR3.
El estado del registro de tareas.
El estado del registro LDTR.
El mapa de memoria de E/S (contenidos en la TSS).

Los punteros a la pila de privilegios 0, 1 y 2 (contenidos en la TSS).


El puntero a la anterior tarea ejecutada (contenidos en la TSS).
En funcin de invocar una tarea, todos estos tems son contenidos en la TSS de la tarea, a excepcin del
estado del registro de tareas. Adems, el contenido completo del registro LDRT no esta contenidos en
la TSS, slo el selector de segmento para el LDT.

Ejecutando una tarea


El software del procesador puede invocar una tarea para ejecutarla de 5 formas:
Haciendo una llamada explcita a una tarea con una instruccin CALL.
Haciendo un salto explcito a una tarea con una instruccin JMP.
Haciendo una llamada implcita (por el procesador) a una tarea de administracin de interrupciones.
Haciendo una llamada implcita a una tarea de administracin de excepciones.
Haciendo un retorno (iniciada con una instruccin IRET) cuando la bandera NT del registro
EFLAGS se activa.
Todos estos mtodos de invocacin de una tarea identifican la tarea a ser invocada con un selector de
segmento que apunta a una puerta de la tarea o con la TSS de la tarea. Al invocar una tarea con un
CALL o una instruccin JMP, el selector en la instruccin puede seleccionar directamente la TSS o una
puerta de tarea que contiene el selector para la TSS. Cuando se invoca una tarea para manejar una
interrupcin o excepcin, el IDT para la interrupcin o excepcin debe contener una puerta de tarea que
contenga el selector para el manejador de la TSS de interrupcin o excepcin.

Cuando una tarea es invocada para la ejecucin, un intercambio de tareas ocurre entre la tarea que est
en ejecucin actualmente y la tarea invocada. Durante el intercambio, el ambiente de ejecucin de la
tarea actualmente en ejecucin (llamado estado de la tarea o contexto) es guardado en su TSS y la
ejecucin de la tarea es suspendida. El contexto para la tarea invocada es luego cargado dentro del
procesador y comienza su ejecucin con la instruccin apuntada por el recin cargado registro EIP. Si la
tarea no se ha ejecutado desde su inicializacin, la EIP apuntar a la primera instruccin del cdigo de
la tarea; de otra manera, apuntar a la siguiente instruccin de la que fue ejecutada cuando la tarea
estuvo activa.
Si la tarea actual en ejecucin (la tarea llamadora) llama a la tarea que va a ser invocada (la tarea
llamada), el selector del segmento TSS de la tarea llamada es resguardado en la TSS de la tarea llamada
para proveerle un enlace a la tarea llamadora.
En la arquitectura IA-32, las tareas no son recursivas; una tarea no se puede llamar a s misma.
Las interrupciones y excepciones pueden ser manejadas con un conmutador de tareas a travs de una
manejador de tareas. Aqu, el procesador realiza una conmutacin de tareas con el manejador de la
interrupcin o excepcin y automticamente conmuta a la tarea interrumpida de regreso. Este
mecanismo puede manejar tambin las interrupciones que se generan durante tareas de interrupcin.
Como parte de la conmutacin de tareas, el procesador puede tambin conmutar otro LDT, permitiendo
a cada tarea tener una direccin lgica-a-fsica diferente mapeada para el segmento LDT. El registro
base CR3 tambin es cargado en la conmutacin de tareas permitiendo a cada tarea tener su propio set
de tablas de pgina. Estas facilidades de proteccin ayudan a las tareas aisladas y previenen que
interfieran entre ellas.

Si el mecanismo de proteccin no es usado, el procesador no provee proteccin entre tareas. Esto


sucede incluso en sistemas operativos que usan mltiples niveles de privilegios como proteccin. Una
tarea que ejecuta con un nivel de privilegio 3 que usa la misma LDT y tablas de pginas que otra tarea
con el mismo privilegio puede acceder al cdigo y corromper los datos y pilas de otras tareas.
El uso de las comodidades de gestin de tareas para el manejo de las aplicaciones multitarea es
opcional.

Inicializacin de la TSS
El descriptor de la TSS necesita ser definido, los segmentos deben ser localizados en lugares sensibles
en el espacio de direcciones y la TSS debe ser inicializada.
Si la TSS es definida end-to-end en una memoria lineal, un alias del segmento de datos debera tener a
su cuidado todos ellos. Esto deriva en una buena idea y es crear un alias de la TSS con la misma
direccin base y lmite, de esta manera se hace menos peligrosa llamar a ms de una TSS a la vez. El
administrador de alias ser tambin fcil si se intercala el descriptor de la TSS con el alias descrito en la
GDT, lo cual es una forma de saber siempre si se corresponde con cada TSS y viceversa.
Despus que el alias es creado debemos cargar la TSS con los valores iniciales antes que la multitarea
comience. La misma tarea rutinaria se presenta cuando el 80386 est ya trabajando en multitarea y el
supervisor o sistema operativo quiere agregar una nueva tarea.
Hay dos maneras de hacer esto:

Se pueden escribir ambos manualmente, almacenando los valores iniciales para EAX, EBX (y as
sucesivamente).
Se puede cargar la TSS entera, de una vez, para hacer que el 80386 almacene el estado actual dentro de ella. Esto se puede realizar forzando un cambio de tarea, pero este mtodo tiene la desventaja de que en servicio de la salida del cambio de tarea (salvando el estado actual de la TSS) debemos
realizar un cambio de tarea en la nueva tarea (y cargar la informacin de estado para una diferente
TSS). De este modo, por lo tanto, alguna TSS debe ser cargada manualmente.
Los valores originales almacenados originalmente en la nueva TSS deben ser si o si no crticos. No
podemos guardar en la TSS campos globales que sern usados por ms de un proceso, con lo cual
se perderan las variaciones que los mismos experimenten.

Entre TIME SLICES la TSS guarda el contexto de la tarea en el punto en que fue sacada y esto normalmente no se modifica. Pero cuando la TSS se crea primero y la tarea es lanzada por primera vez, el
contenido inicial de la TSS puede afectar el comportamiento de los programas cuando comienzan por
primera vez su ejecucin. Obviamente el CS y el EIP deben apuntar al segmento y offset de la primera
instruccin del programa. El campo del segmento de datos probablemente debera ser cargado con el
selector del segmento de datos. El campo SS ciertamente deber ser inicializado con un selector vlido
con el correcto nivel de privilegio. Los 8 registros de propsito general almacenan en sus reas ceros, y
ser responsabilidad del programa en ejecucin colocar los valores correspondientes cuando hace su
primer ingreso al sistema. Los 3 segmentos de stack alternativos y sus correspondientes punteros deberan estar apuntando a sus respectivos stacks aunque se te*nga la total certeza de que solo se utilizar
un nivel de privilegio para esta tarea.

Estructura de datos de administracin de una tarea


El procesador define cinco estructuras de datos para las actividades de administracin relacionadas con
las
tareas:
- Segmento de estado de tarea (TSS): La informacin de estado del procesador necesaria para
restaurar una tarea es guardada en un segmento del sistema llamado segmento de estado de la tarea
(TSS). La figura 2 muestra el formato de una TSS para tareas diseado para una CPU de 32 bits. Los
campos del TSS estn divididos en dos categoras principales: campos dinmicos y campos estticos.
T S S T a s k S ta te S e g m e n t d e 3 2 b its d e l 8 0 3 8 6
31

T = B it d e D e b u g T ra p
I/O = D e s p la z a m ie n to d e l m a p a d e b its

00

I/O M A P B A S E

04

LDT

08

GS

D ire c c i n G e n e ra l

0C

FS

D ire c c i n G e n e ra l

10

DS

D a ta

14

SS

S ta c k - P ila

18

CS

C o d e - C d ig o (T X T )

1C

ES

D ire c c i n d e s tin o c a d e n a s

S e le cto r d e l L D T d e la ta re a

20

EDI

In d ic e D es tin o

24

E SI

In d ic e F u e n te

28

EB P

B as e d e la P ila

2C

ES P

A pu n t a d or d e P ila

30

EB X

In d ic e B a s e

34

E DX

D a to s

38

E CX

C o n ta d o r

3C

EA X

A cu m u la d o r

40

EFLA G S

44

E IP

48

CR 3

4C

54

5C

SS2

P ila p a r a n ive l 2

SS1

P ila p a ra n iv e l 1

S ta ck p o in te r n iv e l 2

S ta c k p o in te r n iv e l 1
SS0

P ila s p a ra
C P L 0 ,1 ,2

P ila p a r a n ive l 0
S ta c k p o in te r n iv e l 0

ES P0

60
64

In s tru c tio n p o in te r
B a s e d e l D ire c to rio o ta b la d e p g in a s

ES P1

58

R e g is tro s d e l
p ro c e sa d o r
(E st a d o d e la ta re a
a c tu a l)

B an d e r a s

ES P2

50

S e le c to re s d e
S e g m e n to

B a c k L in k

S e g m e n t o d e E s ta d o d e T a re a

P u n te ro a la T S S p r e via
N o ta : L o s c a m p o s m a rc a d o s co n X s o n R e s e rv a d o s IN T E L

Segmento de estado de tarea de 32 bits


El procesador actualiza los campos dinmicos cuando una tarea es suspendida durante una
conmutacin de tareas. Los siguientes son campos dinmicos:
Los campos de registros de uso general El estado de los registros EAX, ECX, EDX, EBX,
ESP, EBP, ESI y EDI antes de la conmutacin de tareas.
Los campos del selector de segmento Los selectores de segmento guardados en los registros
ES, CS, SS, DS, FS y GS antes de la conmutacin de tareas.
El campo del resgistro EFLAGS El estado del registro EFLAGS antes de la conmutacin de
tareas.
El campo EIP (puntero de instruccin) El estado del registro EIP antes de la conmutacin de
tareas.
El campo del enlace a la tarea previa Contiene el selector de segmento para la TSS de la tarea
previa (actualizado en una conmutacin de tareas iniciado por una llamada, una interrupcin o una

excepcin). Este campo (que suele llamarse campo de enlace de regreso) permite una conmutacin
a la tarea anterior utilizando la instruccin IRET.
El procesador lee los campos estticos pero normalmente no los cambia. Estos campos son
inicializados cuando la tarea es creada. Los siguientes son campos estticos:
El campo del selector de segmento de LDT Contiene el selector de segmento para la tarea
LDT.
El campo del registro de control CR3 Contiene la direccin de la base fsica del directorio de
pginas a ser usados por una tarea. El registro de control CR3 es tambin conocido como pagedirectory base register (PDBR).
Campos de puntero a la pila de privilegio 0, 1 y 2 Estos punteros a la pila consisten en una direccin lgica compuesta por el selector de segmento del segmento de la pila (SS0, SS1 y SS2) y
un Offset dentro de la pila (ESP0, ESP1 y ESP2). Los valores en estos campos son estticos para
cada tarea en particular; mientras que los valores del SS y el ESP cambiaran si un cambio de pila
ocurre dentro de la tarea.
Bandera T (Debug trap) Cuando esta seteada, la bandera T provoca que el procesador lance la
excepcin de depuracin cuando se genera una conmutacin de tarea hacia esta tarea.
El campo de direccin base del mapa de E/S Contiene un Offset de 16 bits desde la base de la
TSS hasta el bit... Cuando se presenta, estos mapas son guardados en las direcciones altas de la
TSS. La direccin de la base del mapa de E/S apunta al principio del mapeo de bits de permiso de
E/S y al final del mapa de bit de redireccin de las interrupciones.
Si se utiliza paginacin:
Evite establecer un lmite de pgina en la de la TSS que el procesador lee durante una conmutacin de tareas (los primeros 104 bytes). Si un lmite se establece en esta rea, el procesador puede
traducir incorrectamente las direcciones. Durante una conmutacin de tareas, el procesador lee y
escribe dentro de los primeros 104 bytes de cada TSS (usando direcciones fsicas contiguas comenzando con la direccin fsica del primer byte de la TSS). Por lo tanto, luego de que el acceso a
la TSS comienza, si parte de los 104 bytes nos son fsicamente contiguos, los procesadores accedern informacin incorrecta sin generar una excepcin por fallo de pgina.
Las pginas que se corresponden con la TSS de la tarea previa, la TSS de la tarea actual y las entradas de la tabla del descriptor deben ser marcadas como ledas/escritas.
Las conmutaciones de tareas son ms veloces si las pginas que contienen estas estructuras estn
presentes en memoria antes de que la conmutacin de tareas sea inicializada.
- Descriptor de puerta de tarea: Proporciona una referencia indirecta y protegida a una tarea (Figura
3). Se puede ubicar en la GDT, en una LDT o en la IDT. El campo de selector de segmento de TSS en
un descriptor de puertas de tarea apunta a un descriptor TSS en el GDT. El RPL en este segmento no se
usa.

El DPL de un descriptor de puerta de tarea controla el acceso al descriptor de la TSS durante la


conmutacin de tareas. Cuando un programa o procedimiento ejecuta una llamada o salto hacia otra
tarea a travs de una puerta de tarea, el valor de los campos CPL y RPL del selector de puerta
apuntando a la puerta de tarea debe ser menor o igual que el DPL del descriptor de la puerta de tarea.
Cuando la puerta de tarea es usada, el DPL del descriptor de TSS destinatario no es usado.

Descriptor de la puerta de tarea


Una tarea puede ser accedida tanto a travs de un descriptor de puerta de tarea como por un descriptor
de TSS. Ambas estructuras satisfacen las siguientes necesidades:
Necesidad de la tarea de tener slo una bandera de ocupado Dado que la bandera de ocupado
de una tarea es guardada en el descriptor de la TSS, cada tarea debera tener slo un descriptor
de TSS. Puede haber, sin embargo, varias puertas de tarea que reverencien el mismo descriptor
de TSS.
Necesidad de proveer acceso selectivo a las tareas Las puertas de tarea solucionan esta necesidad ya que pueden residir en un LDT y tener un DPL que es distinto al DPL del descriptor de
TSS. Un programa o procedimiento que no tiene suficientes privilegios para acceder al descriptor de TSS de una tarea en la GDT (que usualmente tiene un DPL en 0) podra acceder a la tarea
a travs de la puerta de tarea con un alto DPL.
Las puertas de tarea brindan al sistema operativo mayor amplitud para limitar el acceso de
tareas especficas.
Necesidad de una interrupcin o excepcin a ser manejada por una tarea independiente La
puerta de tarea puede tambin residir en la IDT, lo que permite que las interrupciones y excepciones sean manejadas por manejadores de tarea. Cuando un vector de interrupcin o excepcin
apunta a una puerta de tarea, el procesador conmuta a la tarea especificada.
La siguiente figura ilustra como una puerta de tarea en la GDT, en una LDT y en la IDT pueden apuntar
(todas) a la misma tarea.

Puertas de tarea referenciando la misma Tarea


- Descriptor de TSS: La TSS, como todos los otros segmentos, se define con un descriptor de
segmento. El descriptor TSS slo se puede guardar en el GDT, no se puede guardar en el LDT ni en el
IDT.
Un intento por acceder a la TSS usando un selector de segmento con la bandera IT seteada (que indica
el LDT actual) causa una excepcin de proteccin general (#GP) que se genera durante las
instrucciones CALL y JMP, esto causa una excepcin por TSS invlida (#TS) durante la instruccin
IRET. Una excepcin de proteccin general es generada tambin si se intenta cargar el selector de
segmento para una TSS dentro del registro del segmento.
La bandera de ocupado (B) en el campo de tipo indica si la tarea est ocupada. Una tarea ocupada est
actualmente corriendo o suspendida. El campo tipo con una valor 1001 B indica una tarea inactiva, un
valor 1011 B indica una tarea ocupada. Las tareas no son recursivas. El procesador usa la bandera de
ocupado para detectar intentos de llamadas a tareas cuya ejecucin ha sido interrumpida. Para
asegurarse que slo haya una bandera de ocupado asociada con una tarea, cada TSS debera tener slo
un descriptor de TSS que la apunte.

La base, lmite y campos DPL y la granularidad y banderas actuales tienen funciones similares a su uso
en los descriptores de segmento de datos. Cuando la bandera G es 0 en un descriptor TSS para una TSS
de 32 bits, el campo lmite debe tener un valor mayor o igual que 67 H, un byte menos que el tamao
mnimo de la TSS. Intentar conmutar a una tarea cuyo descriptor TSS tiene un lmite menor que 67 H
genera una excepcin de TSS invlido (#TS). Si se incluye el bit map de permiso de E/S o si el sistema
operativo almacena informacin adicional, el lmite debe ser mayor.
El procesador no chequea que el lmite sea mayor que 67H en la conmutacin de tareas, sin embargo, s
chequea que lo sea cuando se accede al bit map de permiso de E/S o al bit map de redireccin de
interrupciones.
Cualquier programa o procedimiento con acceso al descriptor de la TSS (cuyo CPL es numricamente
igual o menos que el DPL del descriptor TSS) puede invocar la tarea con un CALL o un JUMP.
En la mayora de los sistemas, los DPLs de los descriptores TSS se setean a valores menores que 3, de
manera que slo software privilegiados pueden realizar conmutaciones de tarea. Sin embargo, en
aplicaciones multitarea, los DPLs para algunos descriptores TSS pueden ser seteados a 3 para permitir
la conmutacin de tareas a un nivel de privilegio de aplicacin (o usuario).
Descriptor TSS en modo 64 bits
Cualquier programa o procedimiento con acceso al descriptor TSS puede ejecutar la tarea con un
CALL o con un JMP. En el modo de 64 bits el cambio de tarea no est soportado, pero los descriptores
TSS siguen existiendo (expandidos a 16 bytes).

Formato de descriptor TSS y LDT en modo 64 bits


- Registro de tarea: Contiene el selector de segmento de 16 bits y el descriptor de segmento completo
(direccin base de 32 bits, lmite del segmento de 16 bits y atributos del descriptor) para la TSS de la
tarea en ejecucin. Esta informacin se copia desde el descriptor TSS en el GDT a la tarea en
ejecucin. La figura 7 muestra la ruta que el procesador usa para acceder a la TSS (usando la
informacin del registro de tareas).
El registro de tarea tiene una parte 'visible' (que se puede leer y cambiar por software) y una parte
'invisible' (mantenida por el procesador e inaccesible por software). El selector de segmento en la
porcin visible apunta al descriptor de la TSS en la GDT. El procesador usa la porcin invisible del
registro de tareas para mantener en cache el descriptor de segmento de la TSS. Capturar estos valores
es un registro hace a la ejecucin de la tarea mas eficiente). Las instrucciones LTR (Registro de tareas
cargadas Load task register) y STR (Registro de tarea almacenados Store task register) cargan y
leen la porcin visible del registro de tareas:
La instruccin LTR carga un segmento selector (operando fuente) dentro del registro de tarea que
apunta al descriptor de la TSS en la GDT. Luego carga la porcin invisible del registro de tareas con
informacin del descriptor TSS. La LTR es una instruccin privilegiada que puede ser ejecutada slo
cuando el CPL es 0. Es utilizado durante la inicializacin del sistema para poner un valor inicial en el
registro de tareas. Despus de todo, los contenidos del registro de tareas son cambiados implcitamente
cuando una se realiza una conmutacin de tareas.
La instruccin STR almacena la porcin visible del registro de tareas en un registro de propsito

general en memoria. Esta instruccin puede ser ejecutada por cdigo ejecutable con cualquier nivel de
privilegio de manera de identificar la tarea actual en ejecucin. Sin embargo, es normalmente usado
slo por el software del sistema operativo.
Frente a subidas de tensin o reseteos del procesador, el selector de segmento y la direccin base se
setean a un valor por default igual a 0, y el lmite es iniciado en FFFFH.

Cdigo
Datos
Stack
Actual

Stack nivel 0

TSS

Stack nivel 1
Stack Nivel 2

Task Register
Selector
Parte visible

Base

Lmite
Parte invisible
Descriptor de TSS

GDT

Registro de tareas

- Bandera NT en el registro EFLAGS


Cambio de tarea
El procesador transfiere ejecuciones a otras tareas en uno de cuatro casos:
Cuando el programa en ejecucin, tarea, o procedimiento ejecuta un JMP o un CALL a un descriptor TSS en el GDT.
Cuando el programa en ejecucin, tarea, o procedimiento ejecuta un JMP o un CALL a un descriptor de puerta de tarea en el GDT o en la LDT actual.
Un vector de interrupcin o de excepcin apunta a un descriptor de puertas de tareas en el IDT.
La tarea actual ejecuta un IRET cuando la bandera NT en el registro EFLAGS se activa.
Las instrucciones JMP, CALL e IRET, al igual que las interrupciones y excepciones, son mecanismos
para redireccionar un programa. La referencia a un descriptor TSS o a una puerta de tarea (en la
llamada o salto a una tarea) o el estado de la bandera NT (al ejecutar la instruccin IRET) determinan si

un cambio de tarea ocurre o no.


El procesador ejecuta las siguientes operaciones al conmutar tareas:
1. Obtener el selector de segmento de TSS para la nueva tarea como operando de una instruccin
JMP o CALL, de una puerta de tarea, o desde el campo de enlace con la tarea anterior (por una
conmutacin de tarea inicializado con una instruccin IRET).
2. Verifica que a la tarea actual (la antigua) se le permita conmutarse con la nueva tarea. Las reglas
de privilegio de acceso a los datos se aplican a las instrucciones de JMP y CALL. El CPL de la
actual tarea (la antigua) y el RPL del selector de segmento para la nueva tarea deben ser menores o iguales que el DPL del descriptor TSS o que la puerta de tarea que es referenciada.
Est permitido que las excepciones, interrupciones (excepto por las interrupciones generadas
por la instruccin INT n) y las instrucciones IRET conmuten tareas sin tener en cuenta el DPL
de la puerta de la tarea destino o el descriptor TSS. Para interrupciones generadas por la
instruccin INT n el DPL s es chequeado.
3. Verifica que el descriptor TSS de la nueva tarea est marcado como actual y tiene un lmite vlido (mayor o igual a 67H.
4. Verifica que la nueva tarea est disponible (call, jump, excepciones o interrupciones) u ocupada
(IRET return).
5. Verifica que la TSS actual (la antigua), la nueva TSS y todos los descriptores de segmento usados en el cambio de tarea sean paginados en la memoria del sistema.
6. Si el cambio de tarea fue inicializado con un JMP o una instruccin IRET, el procesador limpia
la bandera de ocupado (B) en descriptor TSS de la tarea actual (la antigua). Si fue inicializado
con una instruccin CALL, una excepcin o una interrupcin, la bandera de ocupado (B) se deja seteada.
7. Si el cambio de tarea fue inicializado con una instruccin IRET, el procesador limpia la bandera
NT guardndolo en una imagen temporal en el registro EFLAGS. Si fue inicializado con una
instruccin CALL o JMP, una excepcin, o una interrupcin, la bandera NT se deja sin cambios
en la imagen guardada del EFLAGS.
8. Guarda el estado de la tarea actual (la antigua) en la TSS de la tarea actual. El procesador encuentra la direccin base de la TSS actual en el registro de tareas y copia el estado de los siguientes registros dentro de la actual TSS: todos los registros de propsito general, los selectores de segmento del registro de segmento, la imagen temporaria del registro EFLAGS, y el registro de puntero de instruccin (EIP).
9. Si el cambio de tarea fue inicializado con una instruccin CALL, una excepcin, o una interrupcin, el procesador setear la bandera NT en el EFLAGS cargado desde la nueva tarea. Si
fue inicializado con una instruccin IRET o una instruccin JMP, la bandera NT reflectar el estado de NT en el EFLAGS cargado desde la nueva tarea.
10. Si el cambio de tarea fue inicializado con una instruccin CALL, una instruccin JMP, una excepcin o una interrupcin el procesador setea la bandera de ocupado (B) en el descriptor TSS
de la nueva tarea. Si fue inicializado con una instruccin IRET, la bandera se deja seteada.
11. Carga el registro de tareas con el selector de segmento y descriptor para la TSS de la nueva tarea.
12. El estado de la TSS es cargado dentro del procesador. Esto incluye el registro LDTR, el PDBR
(el registro de control CR3), el registro EFLAGS, el registro EIP, los registros de propsito general y el selector de segmento. Un fallo durante la carga de este estado puede corromper el estado de la arquitectura.
13. Los descriptores asociados con los selectores de segmento son cargados y calificados. Cualquier
error asociado con la carga y calificacin ocurre en el contexto de la nueva tarea.

14. Comienza la ejecucin de la nueva tarea.

Anlisis del Caso SODIUM


En nuestra implementacin tomamos como base la versin estable de SODIUM de octubre de 2010.
Comenzamos investigando las caractersticas de la PCB y los datos que le eran propios. A partir de esta
investigacin y nuestro conocimiento de hilos decidimos implementar una estructura de bloque similar,
pero que contuviera una cantidad menor de datos de manera de poder ejecutar un context switch de
menor envergadura. Actualmente SODIUM trabaja correspondiendo la ejecucin de un proceso con
una sola tarea registrando sus datos en la TSS. Nuestro objetivo fue corresponder un proceso con un
nmero finito de hilos o tareas, manejando el resguardo de los datos de la TSS. Para ello creamos
dentro de la estructura PCB un vector de estructuras TCB que contiene el identificador del hilo y de su
proceso padre, el estado en el que se encuentra, datos del stack y los registros de la TSS que modifique.

PCB
ulId
iEstado
.
.
.
.
eip;
// id del hilo creado
TCB uivectorTCB[5]
ulTId; // id del hilo
ulPPTId; // id del proc. padre
ulPHTId;// id del hilo padre
iEstado; // ver estados

Dentro del planificador tuvimos que agregar la planificacin inherente a los hilos. A pesar de que
SODIUM posee distintos algoritmos de planificacin, el utilizado es Round Robin, por lo tanto
nuestros hilos se planifican siguiendo este algoritmo. Para ello utilizamos un token que indica quien
puede ejecutar y es entregado de hilo en hilo. Esto es realizado incluyendo el cambio de estado de los
hilos de Listo a Ejecutando y viceversa al momento de la ejecucin del proceso padre planificado, es
decir, primero se planifica por proceso y dentro por hilos pertenecientes a ese proceso. Cuando un hilo
entra en ejecucin se copian en la TSS los datos de la TCB, y una vez que finaliza se hace la copia
inversa, resguardando la informacin.

Implementaciones fallidas de hilos


1. Estructura TCB referenciada a travs de un puntero
El bloque TCB se referenciaba desde la PCB a travs de un puntero. Al ser la TCB externa al
segmento de cdigo en la que se quera utilizar, no logramos hacer referencia a travs de este
puntero a dicha estructura, como resultado obtenamos una direccin de memoria invlida y la
compilacin no se realizaba.
Nombre de la carpeta: Sodium TCB por puntero
Modificaciones realizadas:
/kernel/gdt.c:
Lneas: 37 - 100 - 115 - 544 - 639 - 1024 - 1441
/kernel/planif/rr.c:
Lneas: 80 - 86 - 115
/include/kernel/definiciones.h:
Lnea: 31
/include/kernel/gdt.h:
Lnea: 215
/include/kernel/pcb.h:
Lneas: 20 - 99 - 198
/include/kernel/sched.h:
Lnea: 32
2. Con todos los registros de la TSS
Esta implementacin intentaba al momento del context switch el intercambio de todos los
registros de la TSS a la TCB que estaba incluida en forma de estructura dentro de la PCB,
sabiendo que conceptualmente es una aproximacin errnea, ya que solo son necesarios algunos
de los registros de la TSS, lo que se quera lograr era evitar que datos de la TSS se modifiquen y
que no tuviramos en cuenta. El principal inconveniente en esta implementacin fue el espacio
necesario de memoria asignado para el almacenamiento de las estructuras de hilos dentro de las

de los procesos que posee Sodium, ya que el tamao de la PCB creca a tal punto que no caba
en el espacio asignado y como consecuencia el Sodium no ejecutaba.
Nombre de la carpeta: Sodium TSS Completa
Modificaciones realizadas:
/kernel/gdt.c:
Lneas: 37 - 105 - 534 - 666 - 1051 - 1468
/kernel/planif/rr.c:
Lneas: 80 - 86 - 115
/include/kernel/definiciones.h:
Lnea: 31
/include/kernel/gdt.h:
Lnea: 215
/include/kernel/pcb.h:
Lneas: 20 - 99 - 237
/include/kernel/sched.h:
Lnea: 32
3. N-hilos
Esta implementacin buscaba ejecutar N-hilos por proceso (luego de haber logrado un hilo por
proceso). Dicho proceso se corresponda con un archivo binario en el cual la ejecucin de su
main la llevaba a cabo el hilo 0 y cada una de sus funciones (vistas como tareas) iban a ser
ejecutadas por el resto de los hilos, los cuales son hijos del hilo 0. La ejecucin de las funciones
se realizaba utilizando el registro eip perteneciente a la TSS de manera de acceder a las
funciones a partir de su direccin, pero el valor obtenido nunca concord con la posicin real
que ocupaba.
Nombre de la carpeta: Sodium N-hilos
Modificaciones realizadas:
/kernel/gdt.c:
Lneas: 37 - 105 - 209 - 554 - 649 - 1033 - 1450
/kernel/syscall.c:
Lnea: 127
/kernel/system.c:
Lnea: 703
/kernel/planif/rr.c:

Lneas: 81 - 155
/usr/lib/libsodium.c:
Lnea: 240
/include/kernel/definiciones.h:
Lnea: 31
/include/kernel/gdt.h:
Lnea: 215
/include/kernel/pcb.h:
Lneas: 20 - 99 - 198
/include/kernel/sched.h:
Lnea: 32
/include/kernel/syscall.h:
Lnea: 29 - 262
Archivo agregado:
/usr/tPrueba.c

PRCTICA

Resumen de modificaciones

Sodium/include/kernel/definiciones.h

(lnea 31)
#define CANTMAXTHREADSPROCS 5 //Hilos maximos por procesos

Sodium/include/kernel/pcb.h

(lnea 21-27)
#define THREAD_NO_DEFINIDO -1 // Valor de hilo no definido
#define THREAD_EJECUTANDO 0 // Valor de hilo ejecutando
#define THREAD_LISTO

1 // Valor de hilo listo

#define THREAD_ESPERANDO

2 // Valor de hilo esperando (para el join_thread)

#define THREAD_DETENIDO

3 // Valor de hilo bloqueado

#define THREAD_TERMINADO

4 // Valor de hilo terminado (para el exit_thread)

#define THREAD_ELIMINADO

5 // Valor de hilo eliminado

(lnea 100-136)
/**
\brief Estructura de la TCB
*/
//todo lo comentado es para futuras aplicaciones
//typedef struct _stuAttrAdm_{
// unsigned long ulTiempoComienzo;
positivo empieza luego de ese tiempo */

/* si es negativo: error, si es 0 empieza si puede, si es

// int iPrioridad;
// unsigned long ulPlazo;

/* tiempo que tiene el hilo para cumplir con su tarea*/

//}stuAttrAdm;
typedef struct _stuTCB_{
unsigned long int ulTId;

// id del hilo

unsigned long int ulPPTId; // id del proceso padre


//unsigned long int ulPHTId;
unsigned int uiTamStackThread;
unsigned int uiBaseSS0Thread;
//char stAlias[25];

// Tamanio del Stack


// Base del stack ss0

// nombre solo para propositos de debugging

//void * pvInf;
a (void*)

// inf del momento de creacion, puede ser de cualquier tipo pero casteado

//stuAttrAdm *pstuAttrAdm;
//int iTipo;
int iEstado;

// id del hilo padre

// atributos del hilo

// indica si el hilo es de kernel o usuario


// ver estados mas arriba (HILO_XXX)

int iTokenRR;

// token del round robin

//unsigned long ulTHijos; // cantidad de hilos hijos


unsigned int eip;
unsigned int uiEBandera;
unsigned int eax;
unsigned int ecx;
unsigned int edx;
unsigned int ebx;
unsigned int esp;
unsigned int ebp;
unsigned int esi;
unsigned int edi;
}stuTCB;
(lnea 198)
stuTCB uiVectorTCB[5];

Sodium/include/kernel/gdt.h

(lnea 216)
void vFncrearTCB(int);

Sodium/include/kernel/sched.h

sched.h

(lnea 33-34)
void vFnThreadListoTSS(int);
void vFnThreadEjecutandoTSS(int);

Sodium/kernel/gdt.c

(lnea 38)
unsigned int uiUltimoTid = 0;//para los id de los hilos

(lnea 106-108)
int iM=0;
pstuPCB[iN].uiVectorTCB[iM].iEstado = THREAD_NO_DEFINIDO;
(lnea 533-549)
void vFncrearTCB(int iPosicion)
{
pstuPCB[iPosicion].uiVectorTCB[0].ulTId = uiUltimoTid++;
pstuPCB[iPosicion].uiVectorTCB[0].ulPPTId = pstuPCB[iPosicion].ulId;
pstuPCB[iPosicion].uiVectorTCB[0].iEstado = THREAD_LISTO;
pstuPCB[iPosicion].uiVectorTCB[0].eip = stuTSSTablaTareas[iPosicion].eip;
pstuPCB[iPosicion].uiVectorTCB[0].uiEBandera = stuTSSTablaTareas[iPosicion].uiEBandera;
pstuPCB[iPosicion].uiVectorTCB[0].eax = stuTSSTablaTareas[iPosicion].eax;
pstuPCB[iPosicion].uiVectorTCB[0].ecx = stuTSSTablaTareas[iPosicion].ecx;
pstuPCB[iPosicion].uiVectorTCB[0].edx = stuTSSTablaTareas[iPosicion].edx;
pstuPCB[iPosicion].uiVectorTCB[0].ebx = stuTSSTablaTareas[iPosicion].ebx;
pstuPCB[iPosicion].uiVectorTCB[0].esp = stuTSSTablaTareas[iPosicion].esp;
pstuPCB[iPosicion].uiVectorTCB[0].ebp = stuTSSTablaTareas[iPosicion].ebp;
pstuPCB[iPosicion].uiVectorTCB[0].esi = stuTSSTablaTareas[iPosicion].esi;
pstuPCB[iPosicion].uiVectorTCB[0].edi = stuTSSTablaTareas[iPosicion].edi;
}
(lnea 627)
vFncrearTCB(iPosicion);
(lnea 1012)
vFncrearTCB(iPosicion);
(lnea 1429)
vFncrearTCB(iPosicion);

Sodium/kernel/planif/rr.c

(lnea 81 - 83)
pstuPCB[staiProcesoAnterior].uiVectorTCB[0].iEstado = THREAD_LISTO;
vFnThreadListoTSS(staiProcesoAnterior);
}
(lnea 87 - 88)
pstuPCB[staiN].uiVectorTCB[0].iEstado = THREAD_EJECUTANDO;
vFnThreadEjecutandoTSS(staiN);
(lnea 116 - 142)
void vFnThreadListoTSS(int iN)
{
pstuPCB[iN].uiVectorTCB[0].eip = stuTSSTablaTareas[iN].eip;
pstuPCB[iN].uiVectorTCB[0].uiEBandera = stuTSSTablaTareas[iN].uiEBandera;
pstuPCB[iN].uiVectorTCB[0].eax = stuTSSTablaTareas[iN].eax;
pstuPCB[iN].uiVectorTCB[0].ecx = stuTSSTablaTareas[iN].ecx;
pstuPCB[iN].uiVectorTCB[0].edx = stuTSSTablaTareas[iN].edx;
pstuPCB[iN].uiVectorTCB[0].ebx = stuTSSTablaTareas[iN].ebx;
pstuPCB[iN].uiVectorTCB[0].esp = stuTSSTablaTareas[iN].esp;
pstuPCB[iN].uiVectorTCB[0].ebp = stuTSSTablaTareas[iN].ebp;
pstuPCB[iN].uiVectorTCB[0].esi = stuTSSTablaTareas[iN].esi;
pstuPCB[iN].uiVectorTCB[0].edi = stuTSSTablaTareas[iN].edi;
}
void vFnThreadEjecutandoTSS(int iN)
{

stuTSSTablaTareas[iN].eip = pstuPCB[iN].uiVectorTCB[0].eip;
stuTSSTablaTareas[iN].uiEBandera = pstuPCB[iN].uiVectorTCB[0].uiEBandera;
stuTSSTablaTareas[iN].eax = pstuPCB[iN].uiVectorTCB[0].eax;
stuTSSTablaTareas[iN].ecx = pstuPCB[iN].uiVectorTCB[0].ecx;
stuTSSTablaTareas[iN].edx = pstuPCB[iN].uiVectorTCB[0].edx;
stuTSSTablaTareas[iN].ebx = pstuPCB[iN].uiVectorTCB[0].ebx;
stuTSSTablaTareas[iN].esp = pstuPCB[iN].uiVectorTCB[0].esp;
stuTSSTablaTareas[iN].ebp = pstuPCB[iN].uiVectorTCB[0].ebp;
stuTSSTablaTareas[iN].esi = pstuPCB[iN].uiVectorTCB[0].esi;
stuTSSTablaTareas[iN].edi = pstuPCB[iN].uiVectorTCB[0].edi;
}

TEMAS A DESARROLLAR A FUTURO


Nuestro diseo implementacin abarca la relacin de muchos hilos de usuario a algunos hilos de
kernel. Nos basamos en el tamao de la estructura PCB y con un vector de 5 hilos contemplando esta
limitacin. El siguiente paso deber elevar el nmero de hilos de kernel de manera de generar mayor
nivel de paralelismo. De todas maneras se deber resolver a priori, el problema de asignacin de
memoria a cada proceso, ya que en este momento es muy limitado y no permite incluir un alto nmero
de hilos de kernel dentro de su estructura.
El algoritmo de planificacin utilizado es Round Robin, planificando primero el proceso y luego sus
hilos. La futura implementacin deber planificar directamente a nivel de hilos de kernel. Esto
permitir la ejecucin de hilos independientemente del proceso al que pertenezcan.
Por otro lado, la versin de SODIUM que entregamos con este documento contiene la creacin de
hilos. A futuro se debera realizar la eliminacin, comunicacin y sincronizacin de hilos mediante
alguna de las tcnicas investigadas. De esta manera se conseguira una implementacin de hilos
completa que pueda ser utilizada para continuar con el desarrollo del sistema operativo.

Posibles planificaciones
Planificacin por hilo
La planificacin de context switch se basaba en hilos en vez de en procesos. Al generarse un context
switch si el hilo a ejecutar perteneca al mismo proceso que el hilo en ejecucin se realizaba un context
switch liviano. De otra forma se efectuaba un context switch pesado.
Todos los procesos estaban divididos en hilos, pero al momento de la ejecucin eran hilos
independientes, es decir, que se planificaban los hilos y se realizaban context switch livianos si el
siguiente a ejecutar perteneca al proceso en ejecucin. De otra manera se realizaba un context switch
pesado, intercambiando todos los datos del proceso. Esto permita un aprovechamiento mayor de las
ventajas de los hilos al ejecutar una menor cantidad de context switchs pesados y un manejo de hilos
independientes del proceso.
Esta planificacin se encuentra planteada en la carpeta Sodium N-hilos.
Archivos modificados:
/kernel/planif/rr.c:
Lneas: 81 - 155
/include/kernel/sched.h:
Lnea: 32

Planificacin por proceso y luego por hilo


En esta versin se planifica primero por proceso y luego por hilos pertenecientes a ese proceso. Se
maneja utilizando un token por hilo, que en primera instancia se le asignaba por default al hilo cero.
Luego cada vez que el proceso entraba a ejecucin se iba pasando el token a los siguientes hilos que
estuvieran en estado listo para ejecutar.

token

Esta planificacin es ms sencilla que la anterior tanto en la lgica como en las estructuras de datos que
se manejan. Sin embargo, ninguna de estas dos alternativas funcion porque nunca se logr ejecutar
ms de un hilo por proceso.
Esta planificacin se encuentra planteada en la carpeta Planificacion por hilos.
Archivos modificados:
rr.c:
Lneas: 18 - 44
sched.h:
Lnea: 32

CONCLUSION
El diseo aqu presentado corresponde al modelo 1-1, un hilo de kernel se corresponde con un proceso.
Su planificacin es realizada por proceso considerando los correspondientes hilos.
Creamos una estructura TCB para poder generar una cantidad finita de hilos por proceso. Luego
agregamos al algoritmo de planificacin Round Robin del proceso, como lo hace SODIUM
actualmente, la planificacin de hilos. Esto permitira una planificacin ms sencilla, ya que se realiza
primero por procesos y luego por hilos.
Tambin creamos un archivo binario, el cual hemos utilizado para realizar una serie de pruebas sobre el
paralelismo entre hilos y la ejecucin de los mismos. Si bien fue a nivel terico nos sirvieron para
rechazar hiptesis y plantear nuevas ideas.
La memoria en nuestro sistema es un factor clave y que determina actualmente la cantidad mxima de
hilos de kernel en que podemos dividir a un proceso. Modificar la estructura de SODIUM para que
trabaje con diversos hilos por proceso y con punteros a la TCB permitira un mejor manejo de la
memoria y sera el prximo paso en la implementacin de hilos de kernel.

Anexo 1 Informe CACIC 2010

Conflictos de hilos de Kernel en un sistema operativo


didctico
Hugo Ryckeboer, Nicanor Casas, Graciela De Luca, Martn Cortina,
Gerardo Puyo, Waldo Valiente
{hugor,ncasas,gdeluca,mcortina,wvaliente}@unlam.edu.ar
Balaguer Cristian, del Rio Myrian, Grisolia Maria Laura, Herrera Maite
{balaguercristian,myriam.delrio,laura.grisolia,herrera.mai}@gmail.com
Universidad Nacional de la Matanza
Departamento de Ingeniera e Investigaciones Tecnolgicas
Direccin: Florencio Varela 1703 - Cdigo Postal: 1754 - Telfono:
4480-8900/8835
Abstract: The users threads implementation needs its compensation through the Kernel threads to
complement the necessary structure of any operative system, especially one with didactic features.
The imperious aim in the creation of an operative system is to determine if it can, or not, must, or not,
support threads because once generated it can only carry out patches, because, it is very hard to rewrite
all the Kernel.
The interspersion of threads users, generated under scheduler activations and/or under POSIX norms,
with Kernel threads, having in consideration their characteristics, is what we are showing in this
document.
The parameters used at the design and construction for the alternation among threads, taken in both
types of developments and the predictably of the threads are made evident in agreement with he
fertility and planning capacity.
Keywords: Scheduler Activations, POSIX, Kernel, HTR, wait, signal, primitives, scheduling|
Resumen: La implementacin de hilos de usuario necesita su contrapartida a travs de los hilos de
Kernel para complementar la estructura necesaria de cualquier sistema operativo y en especial uno de
caractersticas didcticas.
Lo imperioso en la creacin de un sistema operativo es determinar si el mismo puede, o no, debe, o no,
soportar hilos porque una vez generado solo se pueden realizar parches debido a que, en trminos

generales, reescribir todo el Kernel es una tarea tediosa. Intercalar los hilos de usuario, generados bajo
scheduler activations y/o bajo normas POSIX, con hilos de Kernel, considerando sus caractersticas es
lo que plasmamos en este documento. Los parmetros utilizados para el diseo y su construccin para
la alternancia entre hilos, tomadas en los dos tipos de desarrollos y la predictibilidad de los hilos es
puesta de manifiesto en concordancia con su fertilidad y su capacidad de planificacin
Palabras Claves: Scheduler Activations, POSIX, Kernel, HTR, espera, seal, primitivas, planificacin
Jerrquica
1. Introduccin
En muchos sistemas operativos, que no son en tiempo real, los hilos se han adoptado como modelo de
programacin. A diferencia del modelo de proceso, un modelo de hilo separa el espacio de direcciones
del flujo de ejecucin dentro del espacio de direcciones. [01]
Algunos intentos de desarrollar hilos en tiempo real se basan en modificaciones de ncleos, que no
trabajan en tiempo real, que soportan hilos, convirtiendo una problemtica en una propiedad clave de
los hilos: la predictibilidad. En este caso, el planificador se encarga de brindar la solucin integrada de
hilos en tiempo real [02], en lugar de que lo haga el Kernel.
Los Hilos de Tiempo Real (HTR) proveen un nivel-usuario capaz de sustituir al kernel en ejecucin,
siendo administrados mediante sus tiempos de comienzo, prioridades y plazos.
Todos los hilos, en particular en un entorno HTR, comparten el mismo espacio de direcciones.
Implementan administracin de hilos, sincronizacin, y funciones de comunicacin, incluyendo
comunicacin entre entornos HTR (con diferentes espacios de direccin, posiblemente en diferentes
mquinas y diferentes arquitecturas). Cada entorno HTR es designado para ser independiente, excepto
por el servicio de pasaje de mensajes.
Un entorno de HTR se caracteriza por ser cooperativo. Ningn hilo debe interferir con los recursos del
sistema ya suministrados a otro hilo, considerando que el sistema no tiene excepcin de manejo de
errores para usos inapropiados de los recursos utilizados por hilos individuales. Las llamadas generadas
por los HTR bloquean su propia ejecucin pero no la de otros hilos administrables. Sin embargo, las
llamadas al sistema que no son de HTR o de bibliotecas externas bloquean totalmente el entorno de los
HTR. Estas clases de llamados se hacen slo con extrema precaucin. [03]
Las aplicaciones multiproceso son algo comn y la planificacin tiene un rol importante.
Las decisiones de la ptima planificacin dependern del estado actual y el comportamiento de la
aplicacin. Cuando ocurren frecuentes fallos de pgina, el planificador puede usar muchos segmentos
de tiempo o suspender alguno de estos hilos momentneamente. [04]
Un planificador que implementa una ptima estrategia de planificacin debe ser capaz de observar el
comportamiento de una aplicacin en el sistema realizando el seguimiento de su estado y de las tareas
que los hilos cumplirn [05].
2. Diseo integrado de hilos
Para el diseo integrado de paquetes HTR nos apoyamos completamente en la especificacin de
propiedades claves mediante un lenguaje de programacin en tiempo real y un lenguaje de descripcin
del sistema.

Tomamos en cuenta las principales propiedades de los HTR que son la fertilidad, el desempeo, el
rendimiento y su nivel de interaccin con los otros hilos.
Cuando un hilo genera otro hilo en tiempo de ejecucin se lo considera frtil. Determinar si lo hace
dentro de su biblioteca o fuera de ella es una decisin importante para determinar el futuro de los
mismos. Al reconocer un hilo estril, el kernel realiza ciertas optimizaciones en comparacin con su
apoyo a los hilos frtiles. Estas comparaciones surgen de saber cules son los espacios de direcciones
que el mismo va a tener y cules son los atributos que se deben tener en cuenta para su planificacin.
Un hilo tiene mayor desempeo cuanto ms especfico es su objetivo de trabajo. El rendimiento se basa
en si el padre es planificado individualmente o en conjunto con todos sus hijos. La interaccin se
establece entre hilos en tiempo real e hilos existentes en un kernel que no trabaja en tiempo real.
El Kernel utiliza esta informacin con garantas dinmicas On-Line para asegurar la ejecucin del hilo.
El problema se presenta con la predicibilidad en la interaccin entre hilos. Se deben determinar
cuidadosamente las interacciones entre el tiempo real y el tiempo compartido, ya que pueden generarse
prdidas en los plazos o fechas lmite de HTR, si acciones como la creacin o planificacin de un hilo
toman ms tiempo de lo esperado. Tales acciones son consideradas predecibles si sus resultados y
duraciones se deducen antes de que las mismas se ejecuten. [01]
La solucin integrada de hilos en tiempo real que alcanza la predicibilidad se consigue mediante la
participacin de un lenguaje de programacin en tiempo real, las opciones del kernel durante el
arranque y el tiempo de ejecucin del kernel. Este paquete co-existe con una garanta basada en el
Planificador dinmico on-line.
Entre los beneficios del modelo de hilos se destacan su portabilidad, al contener un nmero de hilos
independiente del nmero de procesadores disponibles; la facilidad de desarrollo de programas
asncronos; y el rendimiento, que permite cambiar de un hilo a otro en un espacio de direcciones nico
sin reasignar el espacio de direcciones.
3. Mecanismos de administracin de hilos de tiempo real
Los hilos son administrados considerando su planificacin, su prioridad y sus plazos, establecidos en el
momento de su creacin. Un hilo no ser planificado si su tiempo de comienzo est estipulado en el
futuro. Estos son los hilos ms complejos de planificar porque los mismos son generados fuera del
tiempo de ejecucin inmediata y determina adems inconvenientes en la planificacin del padre. En
ms de una ocasin, y debido a deficiencias en sistemas operativos que no contemplan esa estructura,
se pide a los programadores que los mismos no sean generados hasta el momento de su uso. Esto se
hace para evitar tiempos de Kernel desperdiciados en detrimento de otros procesos o hilos. En caso
contrario se planificar, teniendo en cuenta los atributos y el estado de los otros hilos.
Si se desea que el hilo inicie inmediatamente, el tiempo de comienzo debe inicializarse a cero. Algunos
autores hablan de la estipulacin en el pasado es decir inicializacin negativa. Si bien en un principio se
considero la posibilidad de una inicializacin negativa en la ltima revisin, se decidi darlo como un
elemento de error y manejar la cola de listos solo con funciones positivas. Esta disciplina
administrativa es la primera en tenerse en cuenta.
El siguiente atributo considerado en los algoritmos de administracin es la prioridad, que indica cual de
los hilos involucrados tendr preferencia. En este caso el sistema operativo debe poder determinar
cules son los valores, o rango de valores que puede administrar una biblioteca de hilos para que no se
superpongan con valores propios de los procedimientos correspondientes al propio sistema operativo.

Por ltimo se considera el plazo, es decir, el tiempo esperado para el fin de la tarea. Si la tarea no ha
sido terminada en el plazo estipulado, sta continua corriendo. Considerando dos tareas dentro de un
mismo nivel de prioridad, tendr mayor prioridad aquella que no haya cumplido con su plazo, dado que
la otra an puede cumplir con el suyo. Esto puede provocar algunos errores de concepto porque se parte
de la base de que una tarea, siempre se ejecuta hasta el final pero en el caso del tiempo real la demora
en una tarea puede provocar la necesidad de que otra tarea reemplace a la que estaba en ejecucin y
haba demorado ms de lo previsto. En casos como este es el programador el que decide si la tarea
termina, contina. Como se dijo anteriormente el sistema operativo permite que la misma concluya.
Los atributos administrativos son obtenidos y modificados usando diferentes llamadas al sistema. Un
hilo puede acceder a sus propios atributos administrativos o a los de otro hilo utilizando dichas
llamadas. Cambiar los atributos de los hilos puede tener efectos inmediatos en la administracin.
4. Manejo de hilos de tiempo real
Los hilos son creados utilizando un indicador al nombre del hilo creado por referencia; un indicador a
una funcin que acta como indicador de entrada para el hilo creado; el tamao en bytes de la nueva
pila de hilos que varia de acuerdo al nmero y tamao de las variables locales y los parmetros, y la
profundidad de las llamadas a subrutinas; un alias que acta como identificador del hilo suministrado
por el usuario, que puede ser utilizado para propsitos de debugging y por cualquier nmero de hilos;
informacin del momento de creacin del hilo, transparente al mismo, de cualquier tipo pero casteado a
void*, que puede
no declararse si no es requerido en la creacin; atributos administrativos del hilo, mencionados
anteriormente; y un identificador que diferencia si el hilo creado es de nivel kernel o de nivel usuario
considerando que el entorno de los hilos de tiempo real terminar cuando no haya ms hilos de nivel
usuario, por lo que los hilos del servidor constantes deberan ser creados con nivel kernel (a menos que
su servicio sea requerido por otros entornos HTR, en ese caso es recomendable utilizar el nivel usuario)
[9].
Un hilo es eliminado utilizando una llamada de terminacin, que causa que deje el sistema
instantneamente; o cayendo en el final, lo que es equivalente a utilizar la llamada de terminacin en
la ltima declaracin de la subrutina; o siendo eliminado por algn otro hilo, el cual requiere el
identificador del hilo a eliminar.
Un entorno HTR termina cuando todos los hilos de nivel usuario terminaron, registrndose la
finalizacin.
Los hilos se sincronizan a travs de semforos.
Los atributos especificados por el usuario al asignar un nuevo semforo son el nombre del semforo y
un valor inicial que indica cuantas instancias del mismo se requieren, es decir, el nmero de veces que
la primitiva wait puede ser llamada antes de que un hilo sea bloqueado, asumiendo que no se harn
llamadas de la primitiva signal. [10]
La eliminacin del semforo se realiza slo con su nombre.
Para utilizar los semforos tambin se proveen las convencionales primitivas wait y signal y una forma
de obtener el valor actual del semforo, teniendo en cuenta que se necesita como referencia el nombre
del semforo.
Dado que la memoria es compartida dentro de un entorno HTR, los semforos pueden fcilmente
compartirse entre hilos. El sistema no asegura que los semforos eliminados no sean utilizados. Para

ayudar a detectar tal situacin, un intento de eliminar un semforo en el cual otro hilo est bloqueado
resultar en falla. En el caso que un hilo sea eliminado mientras era bloqueado por un semforo, el
estado del semforo ser automticamente modificado (su valor es incrementado).
5. Comunicacin de hilos
Los hilos de tiempo real proveen envos/recepciones/respuestas bloqueantes al estilo de primitivas de
comunicacin entre hilos del mismo espacio de direcciones. Un hilo que enva es bloqueado hasta que
el mensaje haya sido recibido y una respuesta haya sido efectuada. Un hilo que recibe es bloqueado
hasta que recibe el mensaje. Hay tambin un testeo no bloqueante que permite a un hilo comprobar si
hay un mensaje esperando para que l lo reciba.
Un envo requiere un identificador del hilo que recibir el mensaje y la longitud y direccin del
mensaje a enviar y a recibir.
Una recepcin requiere una referencia del hilo que enva; un indicador a un buffer dentro del cual el
mensaje ser recibido y cuya memoria ser asignada por la aplicacin; y un parmetro de entrada/salida
que servir para indicar la mxima longitud esperada para el mensaje recibido, de ser mayor ser
truncado.
Una respuesta requiere un identificador de hilo destinatario de la respuesta, un indicador al mensaje
respondido y la longitud del mensaje respondido.
Las capacidades descriptas en la seccin anterior tambin son realizadas para permitir comunicacin
entre hilos en diferentes espacios de direccin (incluyendo en diferentes mquinas). Los identificadores
de hilos se pasan a travs de espacios de direcciones como valores de retorno de llamadas a
procedimientos o en mensajes enviados por una aplicacin. Alternativamente, un servicio nombrado
puede ser establecido para registrar y buscar el identificador de hilo para hilos remotos. [11]
Cuando un entorno de hilos desea establecer un puerto de comunicacin de alguna manera con otro
espacio de direccin, la inicializacin de la direccin IP y el nmero de puerto a utilizar es esencial.
Los cruces de comunicacin de espacios de direcciones requieren una forma de determinar el
identificador de los hilos en otros entornos HTR. Esto se realiza a travs de un nombramiento del hilo
servidor creado por el usuario, que debe ser nico en cada entorno de hilos de tiempo real. El
identificador de hilo para el nombramiento de hilo servidor puede determinarse desde otro entorno de
hilos de tiempo real, pero requiere que la direccin IP y nmero de puerto del entorno objetivo sean
conocidos.
El nombramiento de hilo servidor mantendr un nombre de hilo mapeado y servicios requeridos
utilizando cruces de comunicacin de espacios de direcciones, retornando el identificador de hilo en la
respuesta.
Se puede enviar el identificador de hilo en un mensaje entre espacios de direcciones que pueda ser
codificado y decodificado utilizando XDR (external data representation). [01]
6. Planificacin Jerrquica (scheduling). Mecanismos.
Diferentes planificadores de implementaciones de usuario permiten adaptar las estrategias de
planificacin por hilos de aplicacin estructurada en forma de rbol, manteniendo el origen en el kernel
por razones de eficiencia y seguridad. Para cambiar entre aplicaciones y subsistemas del kernel se
utiliza un planificador. Cada aplicacin que necesita, para la implementacin de su propia estrategia de
planificacin, crea instancias de un planificador en su espacio de direcciones. Los hilos y planificadores

son administrados como otro planificador. En el espacio de usuario se localizan la aplicacin y los
planificadores de subsistemas. El usuario es el que implementa la estrategia de planificacin para sus
hilos.
Como la implementacin necesita hilos de Kernel, una parte de cada hilo es tomada como un objeto
para ser mantenido en el Kernel y otra parte en la pila que est en el espacio de usuario.
Cada Planificador maneja una lista de hilos y/o planificadores. Cuando es activado, se decide cual de
ellos va a ejecutar o correr y que intervalo de tiempo virtual toma cada uno.
El planificador toma nuevamente el procesador despus del intervalo de tiempo virtual especificado.
Cada planificador funciona con el intervalo de tiempo virtual que recibe del planificador ya
mencionado [06].
Cuando se activa un hilo a travs de un planificador, ste marca el hilo como corriendo o ejecutndose,
es decir, lo mueve desde la cola de listo a la funcin de ejecutando, es decir que este le entrega la CPU.
Mientras que est marcado como corriendo el planificador no vuelve a activarlo porque est fuera de su
rea de administracin.
El timer por procesador es la instancia principal para la activacin y la apropiacin. Es el que pregunta
al sistema planificador qu hilo o planificador tiene que ser activado (1), quien retorna una referencia al
hilo o planificador que desea activar y la divisin de tiempo que debe obtener. La interaccin entre el
timer y el planificador se hace por mtodos de invocaciones (invocaciones de puerta en caso de
llamadas entre dominios). El timer guarda la informacin de las divisiones de tiempo y activan al
objeto retornado. Si el mismo es un planificador, lo activa preguntando qu hilo o planificador debe
activar (2). Si es un hilo, lo activa por conmutacin (3). El timer primero almacena toda la informacin
de las divisiones de tiempo que obtiene de los planificadores y luego busca un hilo para conmutar (4).

El timer obtiene peticiones desde cada planificador que quiere implementar multitareas apropiativas,

siendo capaz de almacenar varias jerarquas de peticiones. En el caso de tener dos solicitudes, una de
una aplicacin planificadora y otra de un sistema planificador, el hilo activo es apropiado luego de
transcurrido el menor tiempo de una de las solicitudes. Su estado y el estado inferior del timer son
guardados en su objeto hilo y el sistema planificador se activar y notificar que la derivacin para la
aplicacin planificadora es apropiativa. As, el objeto hilo representa la totalidad de la derivacin [07].
Si el sistema planificador quiere reactivar la derivacin, lo hace directamente reponiendo la lista de
timer guardada y el contexto del hilo.
Un planificador contiene referencias a las derivaciones que puede activar. Si se activa una derivacin,
se notifica al timer cuantas ranuras de tiempo debe otorgarle. Luego de ser usadas, el planificador es
notificado y cuestionado por cual de estas derivaciones debe ser activada despus. Es transparente para
el planificador si ste o estos hilos hijos son asociados por un nivel superior de planificador. Cada
planificador puede elegir su divisin de tiempo individualmente. Si un hilo o un planificador se bloquea
o termina, sucede lo mismo que en el caso de apropiacin: el planificador padre es notificado y puede
decidir que derivacin quiere activar.
7. Seguridad
Un problema de seguridad es la llamada desde el timer, cuando ste pregunta a un planificador que hilo
va a activar. Esta puede ser una llamada dentro del nivel de usuario, por lo que el Kernel no est seguro
de que el planificador a nivel-usuario devuelva el control.
Mientras la conmutacin de hilos corre, puede haber una lista de timer de nivel-superior instalada. Si la
conmutacin de hilo es apropiativa o bloqueante dentro de la derivacin del administrador apropiativo.
Cuando el sistema planificador activa la derivacin nuevamente, la conmutacin de hilo es activada y
no es creado un nuevo hilo.
En la sincronizacin de las llamadas entre dominios existen dos tipos de objetos activos.
Tenemos los Transportadores (shuttles) los cuales son las entidades planificadoras que contienen
guardado el estado del procesador; y tenemos los hilos que contienen las partes por-dominio del
transporte. Si un hilo llama a otro dominio, un nuevo hilo en el destino del dominio es agregado al
transporte simple.
Este no es aceptado por muchas aplicaciones y servidores. Si un planificador puede apropiarse de un
hilo en otro dominio, puede afectar a la funcionalidad y la integridad del dominio.
Se resuelve este problema pasando la responsabilidad del transporte al dominio llamado.
Este mecanismo es especialmente importante si el usuario llama desde el Kernel: Una invocacin al
Kernel en el sistema operativo es normalmente una llamada entre dominios; nos aseguramos con este
mecanismo que un hilo que corre en el Kernel siempre ser planificado por el Kernel.
Una llamada entre dominios (puerta de llamada) se implementa eficientemente, porque es la base del
mecanismo de interaccin entre dominios en el sistema operativo. As, el overhead de los cuatro
mtodos de llamadas adicionales (agregar y quitar el hilo desde / hasta el planificador) no es aceptable.
Solucionamos este problema con un concepto que llamamos Planificacin perezosa (lazy
scheduling):
Mientras un hilo ejecuta no hacemos nada especial. Cuando el hilo es apropiado o bloqueado,
chequeamos si el hilo en ese momento est ejecutndose en otro dominio. Si es as, se notifica a ambos.
As, el planificador del dominio llamador conceptualmente planifica el hilo antes que sea inhabilitado o
bloqueado por alguien, mientras esta ejecutndose en otro dominio.

Si un planificador activa otro planificador, la derivacin activada es deshabilitada en el planificador


superior. As, el planificador activado no puede obtener ms de un procesador.
Esto es slo posible si tenemos un nico procesador o si el planificador slo tiene un hilo por ranura.
En multiprocesadores el planificador puede decir a sus planificadores padres, que ser capaz de
manejar n procesadores. Entonces el planificador puede activarlo n veces.[04]
8. Paralelismo con los hilos de usuario
El planificador del sistema programa una tarea en un procesador solamente si tiene acceso a los
recursos requeridos en sus modos de accesos especficos, tanto exclusivo como compartido.
La modificacin de un recurso desde un hilo afecta al entorno del resto de los hilos del mismo proceso.
Se necesita sincronizar la actividad de los distintos hilos para que no interfieran unos con otros ni se
corrompan las estructuras de datos.
El planificador elimina la espera asociada con el acceso a los recursos.
El contexto de un hilo reside en memoria fsica en el tablero del procesador que ejecuta el hilo. Si un
hilo se ejecuta en el procesador de un tablero que contiene el espacio de direcciones del proceso al que
pertenece el hilo, el acceso a datos en el espacio de direcciones no requiere el bus, por lo que los
accesos a memoria son ms rpidos y otro procesador no es discriminado. [01]
A fin de ejecutar un hilo en un procesador diferente, el segmento de cdigo del proceso se carga en el
arranque.
El planificador reconoce la diferencia de tiempo en el acceso a memoria e intenta construir un
planificador de tal manera que se maximice la utilizacin del procesador y se minimice el costo de
referencias a memoria.
El diseador de sistemas de tiempo real, establece un conjunto de acciones que el sistema puede
realizar para llevar a cabo su funcionalidad. Pueden existir mltiples acciones para el mismo evento,
difiriendo en la precisin, exactitud e integridad. La mejor eleccin de la accin, como respuesta a un
evento externo, puede depender de la situacin exacta en la que el evento ocurre. Disear mltiples
respuestas genera un sistema mucho ms robusto.
Dado que el kernel de Spring retiene una gran cantidad de informacin en tiempo de ejecucin, el
proceso de planificacin es capaz de proporcionar informacin en respuesta a pedidos de planificacin.
En la planificacin se debe tener en cuenta el tiempo de ejecucin del hilo que intentar generar otros
hilos. [01]
El concepto de hilos livianos o threads naci como un exitoso intento de utilizar memoria compartida
basada en sistemas paralelos para algoritmos paralelos detallados. Ms all de sus beneficios, los hilos
de kernel poseen ciertos problemas como el overhead en aplicaciones informticas de alto rendimiento.
La solucin a este problema en particular es la administracin de hilos de usuario de manera efectiva,
usando los hilos de kernel como procesadores virtuales. Pero esto conlleva otros problemas debido a la
falta de integracin del sistema con los hilos de usuario.
Los hilos durmientes (Sleeping threads) [08] son un mecanismo que utiliza la comunicacin entre el
kernel y el nivel usuario para abordar los problemas de hilos a nivel usuario bloqueados en kernel y las
interferencias entre en nivel usuario y la administracin del kernel. Este mecanismo implementa las
funcionalidades de hilos de repuesto en kernel, desplazando la toma de decisiones administrativas del
kernel al nivel usuario. La administracin de los hilos de repuesto debe ser realizada por la biblioteca
de hilos, as como todas las decisiones administrativas. Esto permite evitar la interferencia con la
planificacin del kernel.

Existen dos maneras extremas de implementar una nueva funcionalidad a nivel usuario que requiere de
modificaciones del kernel: Integrar tanto como sea posible en el kernel, ofreciendo una interfaz
comprensible al usuario; o integrar slo lo necesario como base a una implementacin a nivel de
usuario. La primer opcin tiene la ventaja de que la integracin en el kernel simplifica la
implementacin. Toda la informacin del kernel puede accederse y el estado del sistema es
mayormente controlado por el kernel como nica instancia. Las limitaciones de la integracin en el
kernel estn dadas por la eficiencia y la sobrecarga del kernel. La desventaja de esta opcin es la
necesidad de realizar modificaciones extensas al kernel. No es posible realizar modificaciones o
extensiones rpidas y cortas. La segunda opcin puede llevar a una implementacin ms compleja. Esto
se debe a la distribucin de la informacin de estado entre dos instancias. Pero la segunda opcin tiene
tambin importantes ventajas:
Separacin sencilla de los mecanismos y las estrategias (realizadas en las bibliotecas).
Intercambio sencillo de mdulos de estrategia.
Las partes realizadas en el nivel de usuario no deben ser revisadas para mantener la integridad
del sistema.
Buena portabilidad hacia otros sistemas.
Es sencillo conseguir interfaces uniformes sobre los lmites del sistema.
El mecanismo de Hilos durmientes propone que la biblioteca de hilos mantenga hilos de repuesto en el
kernel. De esta manera, en el supuesto de un bloqueo en el kernel, el mecanismo puede cambiar a uno
de los hilos de repuesto. Esto puede realizarse eficientemente utilizando pginas de memoria
compartidas entre el kernel y la biblioteca de usuario. De esta manera el propio kernel puede manipular
el estado de un hilo de usuario.
La estrategia debe mantener un seguimiento de los hilos de repuesto que reemplazan a los procesadores
virtuales, de manera de mantener constante la cantidad de procesadores virtuales en uso en todo
momento. Pero la creacin de hilos de repuesto genera un problema: el kernel no debe administrar el
nuevo hilo hasta que se necesite como hilo de repuesto. Para solucionarlo se utiliza un system call
especial para la creacin de hilos que encole los nuevos hilos como hilos de repuesto y todo el manejo
de excepciones es hecho en el mismo procesador.
9. Conclusiones
Se han obtenido resultados altamente satisfactorios en la administracin de las prioridades en las colas
de listos pero no as en la administracin de colas con algoritmos Round Robin debido a que generan
esperas ms largas de lo previsto con un importante overhead y hasta el momento, una variacin entre
hilos mayor de lo normal.
El pasaje de Kernel a usuario y de usuario a Kernel es satisfactorio y no se prev que en el transcurso
de este ao se realice alguna mejora.
Los scheduler activations tienen un gran comportamiento como hilos de usuario pero muy bajo
rendimiento como hilos de kernel.
Los hilos durmientes son un mecanismo que permite resolver algunos problemas en las bibliotecas de
hilos de usuario existentes. Reservando hilos de repuesto, la biblioteca de hilos es capaz de reaccionar a
un bloqueo de un hilo en kernel. El nmero de procesadores virtuales se mantiene fijo. Toda la
administracin dentro de una aplicacin es trasladada al nivel usuario, incluso en el caso de un hilo
bloqueado en el kernel. Esto permite una administracin a nivel usuario que respeta las caractersticas
de las computadoras modernas paralelizadas (ej. arquitecturas de memoria y cache) sin interferencia de
context switch del kernel. Con este mecanismo se consigue un buen sistema de integracin a travs de

una amplia comunicacin entre las bibliotecas de hilos y el kernel.


10. Referencias
[01] Humprey Marty, Gary Wallace and John A. Stancovick - Kernel-Level Threads for Dynamic, Hard
Real-Time Environments Department of Computer Science University of Massachusetts 1995
[02] Liedtke Jochen On Kernel Construction GMDGerman National Research Center for
Information Technology - Association for Computing Machinery, Inc. (ACM) 1995
[03] Finkelstein David, Norman C. Hutchinson, Dwight J. Makaroff, Roland Mechler and Gerald W.
Neufeld, Real Time Threads Interface, Department of Computer Science, University of British
Columbia, Canad
[04] Riechmann Thomas, Jrgen Kleinder - User-Level Scheduling with Kernel Threads - Computer
Science Department Operating Systems - IMMD IV Friedrich Alexander University Erlangen Nrnberg, Germany 1996
[05] Anderson Thomas E., Brian N. Bershad, Edward D. Lazowa, Henry M. Levy - Scheduler
activations: effective kernel support for the user-level management of parallelism ACM Transactions
on Computer Systems (TOCS) Pginas 53-79 - 1992
[06] Hans J. - Boehm Threads Cannot Be Implemented As a Library - HP Laboratories - PLDI 05,
June 1215, 2005, Chicago, Illinois, USA
[07] Gene Cooperman, Jason Ansel and Xiaoqin Ma. - Transparent adaptive library-based
checkpointing for master-worker style parallelism. In Proceedings of the 6th IEEE International
Symposium on ClusterComputing and the Grid (CCGrid06), Singapore, 2006. IEEE Press.
[08] Koppe Christoph - Sleeping Threads: A Kernel Mechanism for Support of efficient User Level
Threads Computer Science Department Operating Systems IMMD IV Friedrich Alexander
University Erlangen - Nrnberg, Germany 1995
[09] Bershad Brian Natan, Stefan R. Savage, Przemyslaw Pardyak, Emin Gun Sirer, Marc Eric
Fiuczynski, David Becker, Craig David Chambers, Susan Jane Eggers - Extensibility safety and
performance in the SPIN operating system ACM Transactions on Computer Systems (TOCS)
[10] Ulrich Drepper, Ingo Molnar - The Native POSIX Thread Library for Linux - Red Hat, Inc. 2003
[11] Brian D. Marsh, Michael L. Scott, Thomas J. LeBlanc, Evangelos P. Markatos Firstclass userlevel threads - Computer Science Department - University of Rochester ACM SIGOPS Operating
Systems Review Volume 25, Issue 5 - Pginas 110 -121 1991.
[12] Teora Hilos V2.pps. Apunte terico brindado por la ctedra. 2009
[13] Biblioteca de threads V3.pps. Apunte terico brindado por la ctedra
[14] Hilos_tips.doc. Apunte terico brindado por la ctedra.
[15] Procesos y Planificacin. Arquitectura de Ordenadores. Departamento de Ingeniera Telemtica,
UC3M. 2008.
[16] Hilos y su implementacin. Fundacin Universidad de Bogot. Jorge Tadeo Lozano. 2006
[17] TSS Apunte terico brindado por la ctedra. Ing. Nicanor Casas. 2004