viernes, 15 de junio de 2012

THREAD

CONCEPTO DE THREAD

Un Thread (que de una forma un poco 'basta' se puede traducir como hilo) es la unidad básica de ejecución de OS/2. Cualquier programa que se ejecute consta de, al menos, un thread.
Un thread se puede considerar como la agrupación de un trozo de programa junto con el conjunto de registros del procesador que utiliza y una pila de máquina. El conjunto de los registros y de la pila de cada thread se denomina contexto. Como sabemos, en un Sistema Operativo multitarea, la CPU se reparte entre cada programa a ejecutar. Para ser más precisos, el S.O. reparte la CPU entre todos los threads a ejecutar en cada momento (pues un programa puede contener varios threads), simplemente adueñandose de esta y saltando al siguiente. Sin embargo, esta conmutación no se puede hacer de cualquier manera. Cada vez que el S.O. se adueña de la CPU para cedersela a otro thread, los registros y la pila (o sea, el contexto del hilo) contienen unos valores determinados. Por eso, el S.O. guarda todos esos datos en cada cambio, de modo que al volver a conmutar al thread inicial, pueda restaurar el contexto inicial. No olvidemos que OS/2 es un S.O. con multitarea preemptiva, lo que significa que la CPU puede ser arrebatada en cualquier momento. Esto significa que un thread no puede saber cuando se le va a arrebatar la CPU, por lo que no puede guardar los registros ni la pila de forma 'voluntaria'.
Dado que la forma en que un programa funciona depende principalmente del contexto, dos threads distintos pueden compartir el código de ejecución. Esto significa que si queremos dos threads que hagan las mismas operaciones sobre dos grupos de datos distintos, no necesitamos duplicar el código en memoria. Dado que conmutamos el contexto cada vez, aunque el código sea el mismo, los resultados no lo son, pues los registros y la pila son diferentes. Sin embargo, esto tiene un pequeño problema: las zonas de datos son comunes para todos los threads de un mismo proceso (esto ocurre en cualquier S.O., no solo en OS/2). Eso implica que, en estos casos, es necesario que cada thread cree su propia zona de datos, esto es, usar memoria de asignación dinámica (en C se usa MALLOC para crear una zona de memoria dinámica, si bien OS/2 también ofrece servicios de este tipo más potentes).
Por otro lado, debemos recordar que cada thread se ejecuta de forma absolutamente independiente. De hecho, cada uno trabaja como si tuviese un microprocesador para el solo. Esto significa que si tenemos una zona de datos compartida entre varios threads de modo que puedan intercambiar información entre ellos, es necesario usar algún sistema de sincronización para evitar que uno de ellos acceda a un grupo de datos que pueden estar a medio actualizar por otro thread. Estos servicios se verán más adelante.
Un thread puede crear otro thread usando una llamada de OS/2. Dado que no existe relación del tipo padre-hijo entre threads, los nuevos alcanzan los mismos privilegios que sus hermanos.

DosCreateThread

Por último, un thread acaba cuando vuelve al repartidor de threads. Trabajando en código máquina, esto implica un FAR RET; trabajando en C, significa ejecutar una instrucción EXIT o bien llegar al fin del procedimiento MAIN. Cuando acaban todos los threads de un proceso, OS/2 lo mata, liberando la memoria que ocupaba y los distintos recursos, como ficheros de disco, etc. Existe otra forma de terminar un programa en OS/2, es mediante una llamada a DosExit. Esta llamada finaliza el thread actual.

DosExit

Un thread tiene control sobre otros threads, siempre que pertenezcan al mismo PROCESO, pudiendo terminarlos si es preciso. También puede sincronizarse con ellos si es preciso, esperando a que alguno en concreto termine su ejecucion, o bien dormirlo hasta que le interese ponerlo en ejecución de nuevo.