Ejecución concurrente con threads del RTOS
Comenzar arrow_downwardComprender la diferencia entre programación secuencial y multitarea.
Estado de la CPU guardado al cambiar de thread
Memoria separada para variables locales
Determina cuando puede ejecutarse
Cada cambio de thread requiere guardar/restaurar registros y cambiar el stack pointer. En un Cortex-M4 @ 64 MHz esto toma aproximadamente ~2-5 µs.
Un thread puede estar en uno de tres estados en cualquier momento.
El thread está ejecutándose actualmente en la CPU. Solo un thread puede estar en este estado a la vez (en sistemas single-core).
El thread está listo para ejecutarse, pero espera a que el scheduler le asigne la CPU. Todos los threads listos están en una cola de prioridad.
El thread está bloqueado esperando algo: un timeout (k_msleep), un semáforo, un mensaje, etc. No consume tiempo de CPU.
Haz clic en cada estado para ver sus transiciones validas y descripcion. Usa el modo simulacion para ver un escenario en vivo.
Escenario: Thread A ejecuta, duerme con k_sleep(), el scheduler asigna Thread B. Un semaforo despierta a Thread A.
Zephyr distingue entre threads del sistema y threads de usuario.
Punto de entrada de la aplicación. Ejecuta la función main(). Prioridad configurable (por defecto 0).
Se ejecuta cuando ningún otro thread está listo. Tiene la prioridad más baja posible. Puede poner la CPU en modo de bajo consumo.
Threads creados por la aplicación usando K_THREAD_DEFINE o k_thread_create(). ¡Tu código!
Threads especiales que procesan elementos de trabajo (work items) de una cola. Zephyr incluye un system workqueue por defecto.
Cola global del sistema. Útil para tareas diferidas desde ISRs o callbacks.
Colas personalizadas con prioridad y stack propios. Mejor control.
La macro K_THREAD_DEFINE crea threads en tiempo de compilacion.
K_THREAD_DEFINE crea el thread en tiempo de compilacion. Para creacion en tiempo de ejecucion, usa k_thread_create().
name
Identificador del thread (usado internamente)
stack_size
Bytes de stack para el thread (tipico: 512-2048)
entry
Funcion que ejecuta el thread
p1, p2, p3
Argumentos pasados a la funcion de entrada
prio
Prioridad (menor numero = mayor prioridad)
delay
Milisegundos antes de iniciar (0 = inmediato)
CONFIG_THREAD_ANALYZER para verificar uso real.
Las prioridades determinan que thread se ejecuta cuando hay varios listos.
prioridad < 0
prioridad >= 0
-5 tiene más prioridad que uno con 0, y éste más que uno con 5.
El scheduler decide qué thread se ejecuta y cuándo cambia de contexto.
k_yield()
Cede CPU voluntariamente
k_msleep()
Duerme N milisegundos
k_sem_take()
Espera semáforo
k_msgq_get()
Espera mensaje
k_yield() o k_msleep() bloqueará todo el sistema.
k_msleep() o k_yield() en los bucles infinitos de tus threads.
Dos formas de ceder la CPU con comportamientos diferentes.
Como afecta cada funcion al flujo de ejecucion de los threads.
k_msleep() para tareas periodicas. Usa k_yield() solo cuando necesitas dar oportunidad a otros threads sin esperar.
Permite que threads de igual prioridad compartan la CPU de forma equitativa.
CONFIG_TIMESLICE_PRIORITY.
Un thread puede monopolizar la CPU si no cede voluntariamente
Threads de igual prioridad se turnan cada 10ms
Alternativa a crear threads para ejecutar tareas diferidas.
Un workqueue es un thread especial que procesa elementos de trabajo (work items) de una cola. Los work items se pueden enviar desde cualquier contexto, incluyendo ISRs.
Usando el workqueue del sistema para tareas diferidas.
k_work_submit() envia al workqueue del sistema. Para un workqueue personalizado, usa k_work_submit_to_queue().
Crear tu propia cola de trabajo con prioridad y stack propios.
Conceptos fundamentales de multithreading en Zephyr.
Unidades de ejecucion con contexto propio (registros, stack, prioridad)
Running, Runnable, Non-runnable. El scheduler gestiona las transiciones
Cooperativos (negativas) y preemptivos (no negativas). Menor = mayor prioridad
Ejecuta en puntos de replanificacion: yield, sleep, bloqueo, preempcion
Reparto equitativo de CPU entre threads de igual prioridad
Colas de trabajo para tareas diferidas. Alternativa eficiente a crear threads
"Multithreading permite dividir la aplicacion en tareas independientes que se ejecutan de forma concurrente."
Usa prioridades y puntos de sincronizacion para controlar el flujo de ejecucion.
Aprenderemos a coordinar threads usando semaforos, mutexes y colas de mensajes.