1# Operating system and interrupts 2 3LVGL is **not thread-safe** by default. 4 5However, in the following conditions it's valid to call LVGL related functions: 6- In *events*. Learn more in [Events](/overview/event). 7- In *lv_timer*. Learn more in [Timers](/overview/timer). 8 9 10## Tasks and threads 11If you need to use real tasks or threads, you need a mutex which should be invoked before the call of `lv_timer_handler` and released after it. 12Also, you have to use the same mutex in other tasks and threads around every LVGL (`lv_...`) related function call and code. 13This way you can use LVGL in a real multitasking environment. Just make use of a mutex to avoid the concurrent calling of LVGL functions. 14 15Here is some pseudocode to illustrate the concept: 16 17```c 18static mutex_t lvgl_mutex; 19 20void lvgl_thread(void) 21{ 22 while(1) { 23 mutex_lock(&lvgl_mutex); 24 lv_task_handler(); 25 mutex_unlock(&lvgl_mutex); 26 thread_sleep(10); /* sleep for 10 ms */ 27 } 28} 29 30void other_thread(void) 31{ 32 /* You must always hold the mutex while using LVGL APIs */ 33 mutex_lock(&lvgl_mutex); 34 lv_obj_t *img = lv_img_create(lv_scr_act()); 35 mutex_unlock(&lvgl_mutex); 36 37 while(1) { 38 mutex_lock(&lvgl_mutex); 39 /* change to the next image */ 40 lv_img_set_src(img, next_image); 41 mutex_unlock(&lvgl_mutex); 42 thread_sleep(2000); 43 } 44} 45``` 46 47## Interrupts 48Try to avoid calling LVGL functions from interrupt handlers (except `lv_tick_inc()` and `lv_disp_flush_ready()`). But if you need to do this you have to disable the interrupt which uses LVGL functions while `lv_timer_handler` is running. 49 50It's a better approach to simply set a flag or some value in the interrupt, and periodically check it in an LVGL timer (which is run by `lv_timer_handler`). 51