Professional Documents
Culture Documents
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
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.
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
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:
A continuacin se detallan las funciones ms usadas a la hora de trabajar con los procesos:
Funcin
Descripcin
CreateProcess
CreateProcessAsUser
CreateProcessWithLogonW
CreateProcessWithTokenW
OpenProcess
ExitProcess
TerminateProcess
FlushlnstructionCache
GetProcessTimes
GetExitCodeProcess
GetCommandUne
GetCurrentProcess
GetCurrentProcessId
GetProcess Version
GetStartuplnfo
GetEnvironmentStrings
GetEnvironmentVariable
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:
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.
Estructura de ETHREAD
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.
Dispositivo
Incremento
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.
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
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.
(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.
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.
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:
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
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).
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.
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.
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
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.
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).
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
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.
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
#define THREAD_ESPERANDO
#define THREAD_DETENIDO
#define THREAD_TERMINADO
#define THREAD_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 */
// int iPrioridad;
// unsigned long ulPlazo;
//}stuAttrAdm;
typedef struct _stuTCB_{
unsigned long int ulTId;
// id del hilo
//void * pvInf;
a (void*)
// inf del momento de creacion, puede ser de cualquier tipo pero casteado
//stuAttrAdm *pstuAttrAdm;
//int iTipo;
int iEstado;
int iTokenRR;
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;
}
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
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.
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.
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