// This module keeps track of ML tasks. // It also displays info about DryOS tasks, and requests ML tasks to return at shutdown. // // Credits: // * Indy for task information: http://groups.google.com/group/ml-devel/browse_thread/thread/26cb46acd262b953 // * AJ for the idea of shutting down ML tasks manually, rather than letting DryOS do this job #define _TASKS_C #include "dryos.h" #include "property.h" #include "bmp.h" struct task_attr_str { unsigned int entry; unsigned int args; unsigned int stack; unsigned int size; unsigned int used; // 0x10 void* name; unsigned int off_18; unsigned int flags; unsigned char wait_id; unsigned char pri; unsigned char state; unsigned char fpu; unsigned int id; }; // size = 0x28 extern int is_taskid_valid(int, int, void*); extern int get_obj_attr(void*, unsigned char*, int, int); char* get_task_name_from_id(int id) { #ifdef CONFIG_5DC return "?"; #endif char* name = "?"; int c = id & 0xFF; struct task_attr_str task_attr; int r = is_taskid_valid(1, c, &task_attr); // ok if (r==0) { //~ r = get_obj_attr( &(task_attr.args), &(task_attr.fpu), 0, 0); // buggy ? if (task_attr.name!=0) name=task_attr.name; else name="?"; } return name; } int what_tasks_to_show=2; void tasks_print(void* priv, int x0, int y0, int selected) { #ifndef CONFIG_5DC if (selected) { menu_draw_icon(x0, y0, -1, 0); bmp_fill(38, 0, 0, 720, 430); } int c; unsigned int r; struct task_attr_str task_attr; char *name; extern unsigned int task_max; // wait_id: 0=sleep, 1=sem, 2=flg/event, 3=sendmq, 4=recvmq, 5=mutex // state: 0=ready, 1=wait, 2=susp, other=wait+s int x = 5; int y = 10; bmp_printf(FONT_MED, x, y, what_tasks_to_show == 1 ? "Canon tasks" : "ML tasks"); y += font_med.height; //~ int k = 0; c = 1; bmp_printf(FONT_SMALL, x, y, "task_max=%d", task_max); y += font_small.height; for (c=1; c<(int)task_max; c++) { r = is_taskid_valid(1, c, &task_attr); // ok if (r==0) { r = get_obj_attr( &(task_attr.args), &(task_attr.fpu), 0, 0); // buggy ? if (task_attr.name!=0) name=task_attr.name; else name="?"; // Canon tasks are named in uppercase (exception: idle); ML tasks are named in lowercase. int is_canon_task = (name[0] < 'a' || name[0] > 'z' || streq(name, "idle") || streq(name, "systemtask")); if (what_tasks_to_show==1 && !is_canon_task) continue; if (what_tasks_to_show!=1 && is_canon_task) continue; char short_name[] = " "; my_memcpy(short_name, name, MIN(sizeof(short_name)-1, strlen(name))); int mem_percent = task_attr.used * 100 / task_attr.size; bmp_printf(SHADOW_FONT(FONT(FONT_SMALL, mem_percent < 50 ? COLOR_WHITE : mem_percent < 90 ? COLOR_YELLOW : COLOR_RED, 38)), x, y, "%02d %s: p=%2x w=%2x m=%2d%% %d\n", c, short_name, task_attr.pri, task_attr.wait_id, mem_percent, 0, task_attr.state); #if defined(CONFIG_5D3) || defined(CONFIG_60D) y += font_small.height - (what_tasks_to_show==1 ? 2 : 0); // too many tasks - they don't fit on the screen :) #else y += font_small.height; #endif if (y > 410) { x += 360; y = 10; } } } #endif } void ml_shutdown() { ml_shutdown_requested = 1; info_led_on(); _card_led_on(); config_save_at_shutdown(); info_led_on(); _card_led_on(); } PROP_HANDLER(PROP_TERMINATE_SHUT_REQ) { //bmp_printf(FONT_MED, 0, 0, "SHUT REQ %d ", buf[0]); if (buf[0] == 0) ml_shutdown(); } PROP_HANDLER(PROP_CARD_COVER) { if (buf[0] == 1) ml_shutdown(); } static int task_holding_bmp_lock = 0; static int line_holding_bmp_lock = 0; static char func_holding_bmp_lock[50] = ""; int CheckBmpAcquireRecursiveLock(void* lock, int line, const char* func) { char* task_name = get_task_name_from_id((int)get_current_task()); // just a warning, sometimes we can't get without it (e.g. at redraw), but it's best to avoid /* if (streq(task_name, "GuiMainTask")) { int x = 100; bmp_puts(FONT_MED, &x, &x, "BMP_LOCK GMT"); }*/ // this is really bad - don't ever try to block property handling task! if (streq(task_name, "PropMgr")) { extern int current_prop_handler; char msg[50]; snprintf(msg, sizeof(msg), "BMP_LOCK PROP %x!!!", current_prop_handler); int x = 100; bmp_puts(FONT_MED, (unsigned int *)&x, (unsigned int *)&x, msg); beep(); info_led_blink(20,50,50); ASSERT(0); } int wait = 2000; int r; while ((r = (int)AcquireRecursiveLock(lock, wait))) { char msg[100]; snprintf(msg, sizeof(msg), "%s:%s:%d:\nRLock held by %s:%s:%d ", get_task_name_from_id((int)get_current_task()), func, line, get_task_name_from_id(task_holding_bmp_lock), func_holding_bmp_lock, line_holding_bmp_lock);//, get_task_name_from_id(task_holding_bmp_lock)); int x = 100; bmp_puts(FONT_MED, (unsigned int *)&x, (unsigned int *)&x, msg); ml_assert_handler(msg, __FILE__, __LINE__, __func__); wait = 0; } task_holding_bmp_lock = ((int)get_current_task()) & 0xFF; line_holding_bmp_lock = line; snprintf(func_holding_bmp_lock, sizeof(func_holding_bmp_lock), func); return r; } int CheckBmpReleaseRecursiveLock(void* lock) { int r = (int)ReleaseRecursiveLock(lock); //~ task_holding_bmp_lock = -1; //~ char msg[50] = " "; //~ int x = 100; //~ bmp_puts(FONT_LARGE, &x, &x, msg); return r; }