/** @file OSX_TAsk.c @brief Generic Purpose Task Template implementation. Copyright 2006~2010 Digital STREAM Technology, Inc. All Rights Reserved */ #include "DHL_OSAL.h" #include "DHL_DBG.h" #include "OSX_Task.h" //#include "DHL_DBG_Priv.h" //#include "DHL_OSAL_Config.h" //#include ////#include //#include "mmac/types.h" //#include "mmac/rtos.h" DHL_MODULE("osx", 0); #if COMMENT ____Config____(){} #endif #define USE_STRICT_CHECK 1 /* ¾ö°ÝÇÑ Ã¼Å© ¼öÇà. °³¹ß Áß¿¡¸¸ »ç¿ëÇÏ¸é µÉ °ÍÀ¸·Î º¸ÀÓ. */ #if COMMENT ____Types____(){} #endif /* ŽºÅ© À̸§ ÃÖ´ë ±æÀÌ. */ #define OSX_MAX_TASK_NAME 8 /* task command proc ¿¡¼­ »ç¿ëÇÒ argumentÀÇ ÃÖ´ë °¹¼ö. ³Ê¹« ¸¹À¸¸é send message¿¡¼­ memcpy overhead ¹®Á¦°¡ ÀÖÀ½. °æÇè»ó 4 Á¤µµ¸é ÃæºÐÇϸç, ´õ ¸¹Àº µ¥ÀÌÅ͸¦ Àü´ÞÇϰíÀÚ ÇÑ´Ù¸é pointer¸¦ Àü´ÞÇϰí synchronous callÀ» »ç¿ëÇØ¾ß ÇÑ´Ù. */ #define OSX_MAX_CMD_PARAMS OSX_MAX_USER_PARAMS /* ŽºÅ© msg queÀÇ µðÆúÆ® Å©±â. task start ÇÒ ¶§ caller°¡ ÁöÁ¤ÇÑ´Ù. ÁöÁ¤ÇÏÁö ¾ÊÀ» °æ¿ì µðÆúÆ®·Î ÀÌ °ªÀÌ Àû¿ëµÈ´Ù. */ #define OSX_DEFAULT_MSG_QUE_SIZE 20 /* osx task generation serial number type. value '0' means task is not valid. (not initialized, not created, ...) */ typedef UINT8 T_OSX_TASK_SN; // allocated ÀÓÀ» ³ªÅ¸³»´Â Áö½Ã¾î. typedef UINT8 T_OSX_TAS_MAGIC; // validity¸¦ ³ªÅ¸³»´Â Áö½Ã¾î. /* */ #define OSX_TASK_MAGIC 0xA6 /* Command schedule Á¤º¸¸¦ º¸°üÇÏ´Â ±¸Á¶Ã¼. */ typedef struct { T_OSX_TASK_CMD idCmd; // command id BOOLEAN used; // TRUE if this entry is used (and active) UINT32 period; // interval (if periodic execution), or delay (if delayed execution) // unit is in ms UINT32 start; // time of schedule registration. // if this cmd executed periodically, 'start' is reset to NOW at every execution. UINT16 flags; // flags F_OSX_TASK_PROC fn; // command execution function UINT32 params[OSX_MAX_CMD_PARAMS]; // command arguements } S_OSX_CMD_SCHED; struct S_OSX_TASK_t; // forward declare typedef struct { struct S_OSX_TASK_t *xt; // back link to parent osx task info //-------- OS handles -------- DHL_OS_TASK_ID tid; // OSAL task id (handle) DHL_OS_MSGQ_ID msgQue; // message queue of this task DHL_OS_SEMA_ID semAck; // binary semaphore for returning ACK. DHL_OS_SEMA_ID mutexAck; // mutex for guard semAck //-------- some params -------- int nCmdParam; // number of command parameter. copied from xt->setting->num_cmd_param. // OSX_MAX_CMD_PARAMS º¸´Ù Ŭ ¼ö ¾ø´Ù. } S_OSX_TASK_PUBLIC; typedef struct S_OSX_TASK_t { T_OSX_TAS_MAGIC magic; // validity indicator // OSX_TASK_MAGIC °ªÀ» °¡Áö¸é ÀÌ ±¸Á¶Ã¼ Á¤º¸´Â allocated µÇ¾úÀ¸¸ç valid ÇÔÀ» ÀǹÌ. T_OSX_TASK_SN serial; // ÃʱâÈ­ ÀϷùøÈ£. 0À̸é ÀÌ task Á¤º¸´Â ¹Ì»ç¿ë(not-allocated)À̶ó´Â ÀǹÌÀÓ. // ÀÌ serial ¹øÈ£´Â task°¡ »ý¼ºµÉ ¶§ °ªÀÌ ºÎ¿©µÇ°í, shutdownµÇ¸é 0ÀÌ µÈ´Ù. // ÀÌ serial ¹øÈ£´Â ÇöÀç µ¿ÀÛ ÁßÀÎ task µé°ú Áߺ¹µÇÁö ¾Ê´Â´Ù. /* ÇÒ´ç ¼ø¼­: serial = s#; magic = MAGIC_VALUE; see p_alloc_osx_task(), OSX_TaskStart() ÇØÁ¦ ¼ø¼­: magic = 0; serial = 0; see p_shutdown_task(), p_free_osx_task() */ UINT8 index; // task list ¿¡¼­ÀÇ ¼ø¼­ index. array ¶ó¸é array indexÀÓ. S_OSX_TASK_PUBLIC pti; // public task information. // ÀÌ Á¤º¸µéÀº ÀÓÀÇ task¿¡¼­ ÇÊ¿ä·Î ÇÏ´Â °ÍµéÀÌ´Ù. // ¿©±â¿¡ Á¢±ÙÇÏ·Á¸é mutex°¡ ÇÊ¿äÇÏ´Ù. //-------- state -------- /* task À̸§ */ char name[OSX_MAX_TASK_NAME+1]; /* task ÃʱâÈ­ ¼³Á¤ ÆÄ¶ó¹ÌÅÍ */ S_OSX_TASK_INIT_SETTING setting; // user settings parameter for task init int nMaxQueSize; // copied from setting->msg_que_size. T_OSX_TASK_CMD curServicedCmdId; // ÇöÀç task¿¡¼­ ¼­ºñ½º ÁßÀÎ cmd id. // task°¡ idle »óÅÂÀÏ °æ¿ì¿¡´Â 0ÀÌ µÈ´Ù. //struct OSX_TASK_t *next; // for management.. next task info.. //-------- ¿¹¾à ¸í·É Áö¿ø ÄÚµå -------- int nMaxSlot; // maximum number of element of sclist. (size of sclist) int nScheduledCmd; // ÇöÀç µî·ÏµÈ ¿¹¾à ¸í·É °¹¼ö. // nMaxSlot º¸´Ù Ŭ ¼ö ¾ø´Ù. int maxActiveIndex; // ¿¹¾à ¸í·É ¸®½ºÆ®¿¡¼­ ÇöÀç active ÇÑ cmdÀÇ ¹è¿­ À妽º °ªÀÇ ÃÖ´ë°ª. // list Áß°£¿¡ ÀÖ´Â cmd ¸¦ stop ½ÃÄÑ ¾ø¾Ö¸é ¹è¿­ °¡¿îµ¥°¡ ºó »óŰ¡ µÇ´Âµ¥, // ÀÌ °æ¿ì nActiveTimer¿Í ¹«°üÇÑ °ªÀÌ µÉ ¼ö ÀÖ´Ù. // main task¿¡¼­ ÀÌ °ªÀ» ¾Ë°í ÀÖÀ¸¸é loop ¿À¹öÇìµå¸¦ ¾à°£ ÁÙÀÏ ¼ö ÀÖ´Ù. S_OSX_CMD_SCHED *sclist; // ¿¹¾à ¸í·É (scheduled command) ¸®½ºÆ® Á¤º¸. } S_OSX_TASK; /* internal task command id. S_OSX_TASK_CMD::idCmd ¿¡¼­ »ç¿ëÀÚ command ¿Í °°ÀÌ »ç¿ëµÈ´Ù. ¿©±âÀÇ °ªµéÀº »ç¿ëÀÚ°¡ user command id·Î »ç¿ëÇÒ ¼ö ¾ø´Ù. »ç¿ëÇÏ·Á°í Çϸé API ¾È¿¡¼­ ¿¡·¯°¡ ¹ß»ýÇÑ´Ù. */ typedef enum //E_OSX_TASK_CMD_t { eTASK_CMD_BEGIN = OSX_CMD_RESERVED, // this is just marker. eTASK_CMD_DELETE, // Timer entry Çϳª¸¦ »èÁ¦ÇÑ´Ù. // »èÁ¦(Ãë¼Ò)ÇÒ command id´Â params[0]À» ÅëÇØ Àü´ÞÇÑ´Ù. eTASK_CMD_DELETE_ALL, // ¸ðµç ¿¹¾à cmd entry »èÁ¦. // eTASK_CMD_SHOW, eTASK_CMD_QUERY, eTASK_CMD_SYNC, // ƯÁ¤ ¸í·ÉÀÌ wait ¸ðµå(blocking mode, synchronous mode)·Î µ¿ÀÛÇØ¾ßÇÑ ÇÏ´Â °æ¿ì // ÀÌ command¸¦ »ç¿ëÇϸé task ½ÇÇà°ú µ¿±âÈ­°¡ µÇ¾î // wait ¸ðµåÀÇ È¿°ú°¡ ³­´Ù. // app ¿¡¼­ Á÷Á¢ semaphore, mutex µîÀ» °ü¸®ÇÏ´Â °ÍÀÌ ¹ø°Å·Î¿ï °æ¿ì // °£´ÜÇÏ°Ô ÀÌ ¸í·ÉÀ» Ȱ¿ëÇÏ¸é µÈ´Ù. eTASK_CMD_SHUTDOWN, } E_OSX_TASK_CMD; /* task ¸í·É ¸Þ½ÃÁö ±¸Á¶Ã¼. ½ÇÁ¦·Î OSÀÇ SendMessage¸¦ ÅëÇØ Àü´ÞµÇ´Â ¸Þ½ÃÁöÀÌ´Ù. ÀÌ ±¸Á¶Ã¼ Å©±â°¡ Ä¿Áú ¼ö·Ï SendMessage ³»ÀÇ ºÎÇϰ¡ ºñ·ÊÇÏ¿© Ä¿Áø´Ù. µû¶ó¼­ ºÒÇÊ¿äÇÑ Çʵå´Â Ãß°¡ÇÏÁö ¾Êµµ·Ï ½Å°æÀ» ½á¾ß ÇÑ´Ù. */ typedef struct { T_OSX_TASK_CMD idCmd; // Command ID // this command ID should be unique in S_OSX_TASK. // ¿©±â¿¡ »ç¿ëµÇ´Â °ªµéÀº ÀÏ¹Ý ¼ýÀÚ °ªÀ̰ųª E_OSX_TASK_CMD ³»ºÎ ¸í·ÉÀÌ »ç¿ëµÈ´Ù. T_OSX_TASK_SN snTask; // task serial number UINT16 flags; // °¢Á¾ flag. UINT32 nDelayMs; // timer expire ÁÖ±â. // eTASK_CMD_DELETE ÀÎ °æ¿ì pResult ¿ªÇÒÀ» ÇÑ´Ù. F_OSX_TASK_PROC func; // ÀÌ command id¿¡ ÀÇÇØ ½ÇÇàµÉ ¸í·É ÇÔ¼ö. UINT32 params[OSX_MAX_CMD_PARAMS]; // cmd parameter (func argument) // ÀÌ params´Â °¡º¯ ±æÀÌ ¹è¿­ÀÌ´Ù. // task ÃʱâÈ­ °úÁ¤¿¡¼­ ƯÁ¤ size(°¹¼ö)·Î °íÁ¤µÈ´Ù. // µû¶ó¼­ params Çʵ尡 ÀÌ S_OSX_TASK_CMD ±¸Á¶Ã¼ÀÇ ¸Ç µÚ¿¡ À§Ä¡ÇØ¾ß ÇÑ´Ù. } S_OSX_TASK_CMD; /** S_OSX_TASK_CMD ÀÇ Å©±â´Â °¡º¯ÀÌ´Ù. Á¤È®ÇÑ size´Â nCmdParam °ª¿¡ µû¶ó ´Þ¶óÁø´Ù. SendMessage ÇÒ ¶§ ±×³É ÃÖ´ë Áö¿ø °¹¼öÀÎ OSX_MAX_CMD_PARAMS ¸¦ »ç¿ëÇÏÁö ¾Ê´Â ÀÌÀ¯´Â ºÒÇÊ¿äÇÑ memcopy overhead¸¦ ÁÙÀ̱â À§ÇÔÀÌ´Ù. */ #define OSX_COMMAND_SIZE(num_param) (\ sizeof(S_OSX_TASK_CMD) \ - sizeof(UINT32)*OSX_MAX_CMD_PARAMS \ + sizeof(UINT32)*(num_param) \ ) #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif /* H_OSX_TASK ÇÚµé ±¸¼º. task listÀÇ index¿Í serial number·Î ±¸¼ºÇÑ´Ù. ÃÖ´ë task °¹¼ö´Â 256 À¸·Î ÇÑÁ¤. 8 ºñÆ®¸é µÊ. serial ¹øÈ£´Â 0~0xFF ¸é ÃæºÐ. 8ºñÆ®¸é µÊ. MSB 16 bits: osx task list index | 0x100 LSB 16 bits: osx task generation serial */ #define MAKE_OSX_HANDLE(index, serial) (0x10000 | (((index)&0xff)<<8UL) | ((serial)&0xff)) #define INDEX_FROM_HANDLE(handle) ( ((handle)>>8) & 0xff ) #define SERIAL_FROM_HANDLE(handle) ( (handle)&0xff ) #if COMMENT ____Variables____(){} #endif /* »ý¼ºµÈ ¸ðµç osx task ¸®½ºÆ®. S_OSX_TASK *s_osx_task_list; */ /* osx task list Á¤º¸. */ S_OSX_TASK s_osx_tasks[OSX_MAX_TASK]; /* task serial ¹øÈ£ ¹ß±Þ ¿ë º¯¼ö. ÀÌ º¯¼öÀÇ °ªÀº °¡Àå ¸¶Áö¸·¿¡ ¹ß±ÞÇÑ ¹øÈ£ÀÓ. serial 0 Àº ¹ß±ÞÇÏ¸é ¾ÈµÈ´Ù. '¹Ì»ç¿ë'ÀÇ Àǹ̷Π»ç¿ëµÇ¹Ç·Î. */ T_OSX_TASK_SN s_osx_serial; /* osx task Á¤º¸¿¡ ´ëÇÑ mutex. »ç¿ëµÇ´Â °÷: 1. ÃÖÃÊ¿¡ task start ÇÏ´Â ½ÃÁ¡¿¡¼­¸¸ »ç¿ëµÇ¸ç, (called in arbitrary task) ±× ÀÌÈÄ¿¡´Â »ý¼ºµÈ task ¿¡¼­¸¸ »ç¿ëÇÏ´Â °ÍÀ¸·Î ÇÑ´Ù. 2. ÀÓÀÇ task¿¡¼­ task public Á¤º¸¸¦ °¡Á®¿Ã ¶§ »ç¿ëµÈ´Ù. */ DHL_OS_SEMA_ID s_osx_mutex; S_OSX_TASK *s_osx_traced; // trace ÇϰíÀÚ ÇÏ´Â task handle. // Àüü task ¸®½ºÆ®¸¦ È®ÀÎÇÑ ÈÄ¿¡ ÇÚµé °ªÀ» ÁöÁ¤ÇØ ÁÖ¸é µÈ´Ù. /* ÀÌ ÇÔ¼ö´Â ÀÓÀÇ task¿¡¼­ È£ÃâµÈ´Ù. */ static S_OSX_TASK *p_alloc_osx_task(void) { int i; S_OSX_TASK *xt = NULL; // ¸Ç ¸ÕÀú serialÀ» µî·ÏÇÏ´Â task°¡ owner°¡ µÈ´Ù. DHL_OS_TakeSemaphore(s_osx_mutex, DHL_TIMEOUT_FOREVER); for (i=0; s_osx_tasks[i].serial==0 && imagic = 0; xt->serial = 0; DHL_OS_GiveSemaphore(s_osx_mutex); } static void p_validate_osx_task(S_OSX_TASK *xt) { DHL_OS_TakeSemaphore(s_osx_mutex, DHL_TIMEOUT_FOREVER); xt->magic = OSX_TASK_MAGIC; DHL_OS_GiveSemaphore(s_osx_mutex); } static void p_invalidate_osx_task(S_OSX_TASK *xt) { DHL_OS_TakeSemaphore(s_osx_mutex, DHL_TIMEOUT_FOREVER); xt->magic = 0; DHL_OS_GiveSemaphore(s_osx_mutex); } #if COMMENT ______Func____(){} #endif static BOOL s_module_init; static void osx_module_init(void); static int p_list_all_osx_task(H_OSX_TASK *list) { int i; int n_task = 0; DHL_OS_TakeSemaphore(s_osx_mutex, DHL_TIMEOUT_FOREVER); for (i=0; i= OSX_MAX_TASK) { dprint(0, "!! invalid osx task handle 0x%x\n", handle); goto end; } xt = &s_osx_tasks[index]; if (xt->serial != SERIAL_FROM_HANDLE(handle) || xt->magic != OSX_TASK_MAGIC) { dprint(0, "!! wrong osx task info: handle %x, serial %x magic %x\n", handle, xt->serial, xt->magic); goto end; } if (xt->pti.tid == 0) { dprint(0, "!! task not initialized!\n"); goto end; } *pti = xt->pti; ret = pti; // return pointer of caller's pti copy, NOT &xt->pti. end: DHL_OS_GiveSemaphore(s_osx_mutex); return ret; } #if USE_STRICT_CHECK static void p_assert_in_task(S_OSX_TASK *xt, const char *fn) { DHL_OS_TASK_ID tid = DHL_OS_GetTaskID(); if (!xt || tid != xt->pti.tid) { dprint(0, "!! %s should be called inside task! xt %x, tid %x != xt's %x\n", fn, xt, tid, xt?xt->pti.tid:0); DHL_ASSERT(FALSE, ""); } } #endif #if COMMENT ______TaskMethod____(){} #endif /* add one scheduled command */ static DHL_RESULT p_add_scheduled_cmd(S_OSX_TASK *xt, S_OSX_TASK_CMD *cmd) { int i; int iSelected, iEmpty; #if USE_STRICT_CHECK p_assert_in_task(xt, __func__); #endif if (cmd->nDelayMs == 0) { // ¿¡·¯. dprint(0, "!! task %s: schedule cmd with zero delay\n", xt->name); return DHL_FAIL_INVALID_PARAM; } if ((cmd->flags & eTASK_FLAG_Repeat) && (cmd->nDelayMs <= 2)) { dprint(0, "!! task %s: too short period %d\n", xt->name, cmd->nDelayMs); // ÀÏ´Ü ±×´ë·Î ÁøÇà. } // id¸¦ °Ë»öÇϸ鼭, µ¿½Ã¿¡ empty slotµµ ã´Â´Ù. // ÇØ´ç ID°¡ ÀÌ¹Ì »ç¿ëÁßÀ̶ó¸é °»½Å¸ðµå.. iSelected = -1; iEmpty = -1; for (i=0; inMaxSlot; i++) { if (xt->sclist[i].used && xt->sclist[i].idCmd == cmd->idCmd) { // ÀÌ¹Ì »ç¿ëÁßÀÌ´Ù.. // »õ·Î¿î parameter·Î updateÇϰí ÇÔ¼ö Á¾·á.. if (s_osx_traced == xt) dprint(0, "!! cmd (id 0x%x) already scheduled. updated..\n", cmd->idCmd); iSelected = i; break; } else if (xt->sclist[i].used == 0) { // ºñ¾îÀÖ´Â slotÀ» ã´Â´Ù.. if (iEmpty < 0) iEmpty = i; } } if (iSelected < 0) // µ¿ÀÏÇÑ iSelected = iEmpty; if (iSelected >= 0) { S_OSX_CMD_SCHED *psc = &xt->sclist[iSelected]; if (psc->used == FALSE) { xt->nScheduledCmd++; } psc->idCmd = cmd->idCmd; psc->period = cmd->nDelayMs; psc->fn = cmd->func; for (i=0; ipti.nCmdParam; i++) psc->params[i] = cmd->params[i]; for (; iparams[i] = 0; psc->flags = cmd->flags; psc->start = DHL_OS_GetMsCount(); psc->used = TRUE; // maxActiveIndex¸¦ ¾Ë¾ÆµÎ¸é TimerTask¿¡¼­ loop¸¦ µ¹¶§ µµ¿òÀÌ µÈ´Ù. if (xt->maxActiveIndex < iSelected) xt->maxActiveIndex = iSelected; if (s_osx_traced == xt) dprint(0, " add: cmd[%d] id 0x%x, total %d active\n", iSelected, cmd->idCmd, xt->nScheduledCmd); } else { //if (s_osx_traced == xt) dprint(0, "!! task %s: no more cmd slot for cmd 0x%x\n", xt->name, cmd->idCmd); // it may be available some time later because oneshot timer will die.. } return iSelected >= 0 ? DHL_OK : DHL_FAIL_NOT_AVAILABLE; } /* delete one timer entry. this function should be called in timer task. */ static DHL_RESULT p_del_scheduled_cmd(S_OSX_TASK *xt, T_OSX_TASK_CMD idCmd) { int i; DHL_RESULT dhr = DHL_FAIL_NOT_FOUND; int maxActiveIndex = -1; #if USE_STRICT_CHECK p_assert_in_task(xt, __func__); #endif if (idCmd == (T_OSX_TASK_CMD)-1) { // delete all.. if (s_osx_traced == xt) dprint(0, "delete all sch.cmd\n"); memset(&xt->sclist, 0, xt->nMaxSlot*sizeof(S_OSX_CMD_SCHED)); xt->nScheduledCmd = 0; xt->maxActiveIndex = -1; dhr = DHL_OK; } for (i=0;i<=xt->maxActiveIndex;i++) { if (xt->sclist[i].used == FALSE) continue; if (xt->sclist[i].idCmd == idCmd) { // delete ´ë»ó command. memset(&xt->sclist[i], 0, sizeof(S_OSX_CMD_SCHED)); xt->nScheduledCmd--; if (s_osx_traced == xt) dprint(0, "delcmd: index: %d, ID: %d\n", i, idCmd); dhr = DHL_OK; } else { maxActiveIndex = i; } } xt->maxActiveIndex = maxActiveIndex; return dhr; } /* show timer sclist */ static void p_show_scheduled_cmd(S_OSX_TASK *xt, S_OSX_TASK_CMD *cmd) { DHL_RESULT dhlResult; int i, k; char buf[80]; #if USE_STRICT_CHECK p_assert_in_task(xt, __func__); #endif DHL_OS_Printf("----- Task %x, handle %x -----\n", xt, MAKE_OSX_HANDLE(xt->index, xt->serial)); DHL_OS_Printf(" '%s', prio %d, max slot %d\n", xt->name, xt->setting.priority, xt->nMaxSlot); for (i=0; i<=xt->maxActiveIndex; i++) { char *fname = NULL; if (!xt->sclist[i].used) continue; // dhl_dbg_find_sym_by_addr((UINT32)xt->sclist[i].fn, &fname); for (buf[0]=0, k=0; kpti.nCmdParam); k++) sprintf(buf+strlen(buf), "%x ", xt->sclist[i].params[k]); DHL_OS_Printf(" (%02d) ID %d, fn %x(%s) arg (%s), %d ms, f%x %s%s\n", i, xt->sclist[i].idCmd, xt->sclist[i].fn, fname ? fname : "?", buf, xt->sclist[i].period, //xt->sclist[i].period, xt->sclist[i].flags, xt->sclist[i].flags & eTASK_FLAG_Delayed ? "delayed " : "", xt->sclist[i].flags & eTASK_FLAG_Repeat ? "repeat " : ""); } DHL_OS_Printf("\n"); } /* »ç¿ëÀÚ ¸í·ÉÀ» È£ÃâÇÑ´Ù. ¹Ù·Î ¼öÇà ¸í·ÉÀÏ ¼öµµ ÀÖ°í, ¿¹¾à ¸í·ÉÀÏ ¼öµµ ÀÖÀ½. */ void p_callback_user_func(S_OSX_TASK *xt, T_OSX_TASK_CMD idCmd, UINT16 flags, F_OSX_TASK_PROC pFn, UINT32 *params) { // task callbackÀÌ ºÒ¸®´Â µ¿¾È¿¡´Â ¾î¶² task id°¡ service ÁßÀÎÁö ±â·ÏÀ» ³²°ÜµÎÀÚ. xt->curServicedCmdId = idCmd; if (s_osx_traced == xt) dprint(0, "\n---------- ExecBegin: %x, cmd 0x%x, fn 0x%x, param[0] 0x%x \n", xt, idCmd, pFn, params[0]); if (xt->pti.nCmdParam <= 2) pFn(idCmd, params[0], params[1]); else if (xt->pti.nCmdParam <= 4) pFn(idCmd, params[0], params[1], params[2], params[3]); else // OSX_MAX_USER_PARAMS ¸¸Å­ Áö¿øÇØ¾ß ÇÑ´Ù. À̰ÍÀº programmatic ÇÏ°Ô ±¸Çö ¾î·Á¿ò. pFn(idCmd, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]); if (s_osx_traced == xt) dprint(0, "---------- ExecEnd: %x, ID %d \n\n", xt, idCmd); xt->curServicedCmdId = 0; // idCmd 0Àº ¿©±â¼­ ó·³ Ưº°ÇÑ Àǹ̷Π»ç¿ëÇϹǷÎ, ÀÏ¹Ý command ID·Î´Â reserve ÇØ¾ß ÇÑ´Ù. } void p_shutdown_task(S_OSX_TASK *xt) { #if USE_STRICT_CHECK p_assert_in_task(xt, __func__); #endif dprint(2, "task stop requested..\n"); // ´õ ÀÌ»ó »õ·Î¿î task ¸í·ÉÀÌ Àü´ÞµÇÁö ¾Êµµ·Ï ¼± Á¶Ä¡. invalidate. //xt->magic = 0; p_validate_osx_task(xt); DHL_OS_DeleteSemaphore(xt->pti.semAck); xt->pti.semAck = 0; DHL_OS_DeleteSemaphore(xt->pti.mutexAck); xt->pti.mutexAck = 0; DHL_OS_DeleteMessageQueue(xt->pti.msgQue); xt->pti.msgQue = 0; dprint(2, "task about to shutdown..\n"); xt->pti.tid = 0; // osx task ±¸Á¶Ã¼¸¦ empty ÇÏ¿© ´Ù¸¥ task¿¡ ÇÒ´çµÉ ¼ö ÀÖµµ·Ï Á¶Ä¡. p_free_osx_task(xt); DHL_OS_SelfDeleteTask(); } #if COMMENT ____Task____() {} #endif /* task main. */ static void p_task_main(S_OSX_TASK *xt) { int i; DHL_RESULT result; S_OSX_TASK_CMD cmd; int nMinRemainingMs; // °¡Àå ¸ÕÀú ½ÇÇà µÉ ¿¹¾à ¸í·É¾î ±îÁöÀÇ ½Ã°£. UINT32 uNow; while(xt->pti.tid == 0) // wait until creator returns DHL_OS_CreateTask api. DHL_OS_Delay(10); dprint(1, "osx task start, xt %x, s# %x, name '%s', handle %x\n", xt, xt->serial, xt->name, MAKE_OSX_HANDLE(xt->index, xt->serial)); while (TRUE) { nMinRemainingMs = 0x7fffffff; // signed INT32 valueÀÇ ÃÖ´ë°ª.. //--------- timer expiration timeout üũ ------------ // ÇöÀç °¡Àå °¡±î¿î ½Ã°£ ³»¿¡ expire µÉ timer¸¦ ã´Â´Ù.. uNow = DHL_OS_GetMsCount(); for (i=0; i<=xt->maxActiveIndex; i++) { int nRemainMs; if (xt->sclist[i].used == 0) continue; nRemainMs = (int) (xt->sclist[i].start + xt->sclist[i].period - uNow); // ÀÌ¹Ì expire µÈ timer¶ó¸é remainÀº negative °ªÀ» °¡Áú °ÍÀÓ.. if (nMinRemainingMs > nRemainMs) { nMinRemainingMs = nRemainMs; } } //--------- wait message with/without timeout ------------ /* nMinRemainingMs°¡ 0À̶ó¸é ¹Ù·Î ½ÇÇàÇØ¾ß ÇÒ ¿¹¾à ¸í·ÉÀÌ ÀÖ´Ù´Â ÀǹÌÀÌ´Ù. ÀÌ °ªÀº <0 ÀÏ ¼öµµ ÀÖ´Ù. (ÀÌ¹Ì ½ÇÇàÇØ¾ß ÇÒ ½Ã°£ÀÌ °æ°úÇÑ °æ¿ì) ¼³·É ÀÌ¹Ì expire µÈ entry°¡ ÀÖ´Ù°í ÇÏ´õ¶óµµ taskÀÇ ½ÇÇà ºÎÇϰ¡ ¸¹¾Æ¼­ command¸¦ ¾Æ¿¹ ¸ø¹Þ´Â »óȲÀÌ µÇÁö ¾Êµµ·Ï, msgque ´Â ¹Ýµå½Ã ÇѹøÀº üũ¸¦ ¼öÇàÇÏ°í ³ª¼­ ¿¹¾à ¸í·É ó¸®ÇØ ÁØ´Ù. ÀÌ °æ¿ì ReceiveMessage´Â No-wait ¸ðµå·Î ½ÇÇàµÈ´Ù. */ // it can be negative. so adjust required. if (nMinRemainingMs < 0) nMinRemainingMs = 0; // ¾ÆÁ÷ ³²Àº ½Ã°£ÀÌ ¸¹±â ¶§¹®¿¡ SleepÀ» ÇÑ´Ù. if (nMinRemainingMs < 0x7fffffff) { if (s_osx_traced == xt) dprint(2, "task enter sleep for %d ms..\n", nMinRemainingMs); result = DHL_OS_ReceiveMessage(xt->pti.msgQue, &cmd, nMinRemainingMs); } else { // ó¸®ÇØ¾ß ÇÒ ³²Àº timer°¡ ¾ø´Ù¸é active µÉ¶§±îÁö ¹«ÇÑÁ¤ ±â´Ù¸®±â¸¸ ÇÏ¸é µÈ´Ù. // if (s_osx_traced == xt) dprint(2, "task wait msg..\n"); result = DHL_OS_ReceiveMessage(xt->pti.msgQue, &cmd, DHL_TIMEOUT_FOREVER); } //--------- process message if we got new one ------------ if (result == DHL_OK) // we got command { // check task serial number. if (cmd.snTask != xt->serial) { dprint(0, "!! cmd %x (sn %x) is not for our task (sn %x)\n", cmd.idCmd, cmd.snTask, xt->serial); // shutdown µÇ±â Àü¿¡ send µÈ command°¡ ÀÌÁ¦¼­¾ß 󸮵Ǵ °ÍÀÏ ¼ö ÀÖÀ½. // ÀÌ ¸í·ÉÀº ±×³É Á¶¿ëÈ÷ ignore ÇÑ´Ù. } // add / delete / query / shutdown else if (cmd.idCmd < eTASK_CMD_BEGIN) { // ³»ºÎ ¸í·ÉÀÌ ¾Æ´Ï¸é ½ÇÇà ¸í·ÉÀÓ. // delay°¡ ¾Æ´Ï¶ó¸é ¹Ù·Î ½ÇÇà. if (!(cmd.flags & eTASK_FLAG_Delayed)) { // ÇØ´ç case: // eTASK_FLAG_Normal, eTASK_FLAG_NowAndRepeat p_callback_user_func(xt, cmd.idCmd, cmd.flags, cmd.func, cmd.params); } // delay ¶Ç´Â repeat ¿É¼ÇÀÎ °æ¿ì list¿¡ µî·ÏÇØ¾ß ÇÑ´Ù. // ´Ü ÀÌ °æ¿ì¿¡´Â nDelayMs°¡ 0ÀÌ ¾Æ´Ï¾î¾ß ÇÔ. if ((cmd.flags & eTASK_FLAG_Repeat) || (cmd.flags & eTASK_FLAG_Delayed)) { // ÇØ´ç case: // eTASK_FLAG_Delayed, eTASK_FLAG_WaitAndRepeat, eTASK_FLAG_NowAndRepeat result = p_add_scheduled_cmd(xt, &cmd); if (s_osx_traced == xt) OSX_TaskShow(MAKE_OSX_HANDLE(xt->index, xt->serial)); } } else if (cmd.idCmd == eTASK_CMD_DELETE) { // delete ÀÎ °æ¿ì´Â »èÁ¦ÇÒ cmd id°¡ params[0]À» ÅëÇØ Àü´Þ µÈ´Ù. result = p_del_scheduled_cmd(xt, (T_OSX_TASK_CMD)cmd.params[0]); } else if (cmd.idCmd == eTASK_CMD_DELETE_ALL) { result = p_del_scheduled_cmd(xt, (T_OSX_TASK_CMD)eTASK_CMD_DELETE_ALL); } else if (cmd.idCmd == eTASK_CMD_SYNC) { ; // Ưº°È÷ ó¸®ÇÒ °Í ¾øÀ½. ±×³É ¾Æ·¡¿¡¼­ ack¸¸ ÁÖ¸é µÊ. } else if (cmd.idCmd == eTASK_CMD_SHOW) { p_show_scheduled_cmd(xt, &cmd); } else if (cmd.idCmd == eTASK_CMD_QUERY) { // not yet.. } else if (cmd.idCmd == eTASK_CMD_SHUTDOWN) { break; } if (cmd.idCmd == eTASK_CMD_SYNC) { DHL_OS_GiveSemaphore(xt->pti.semAck); } } else if (result == DHL_FAIL_TIMEOUT) { // À̰ÍÀº ¿¡·¯°¡ ¾Æ´Ï´Ù. ¿¹¾à ¸í·É Áß Çϳª¸¦ ½ÇÇàÇÒ ¶§°¡ µÇ¾úÀ½À» ³ªÅ¸³½´Ù. } else { dprint(0, "!! task rx msg result 0x%x\a\n", result); } //-------- scheduled cmd list ó¸® --------------- /* ¿¹¾à ¸í·É ¸®½ºÆ®¸¦ ¸ðµÎ üũÇÏ¿© ½Ã°£ °æ°ú µÈ ¸í·ÉµéÀ» ¸ðµÎ ó¸®ÇØ ÁØ´Ù. */ for (i=0; i<=xt->maxActiveIndex; i++) { S_OSX_CMD_SCHED *psc = &xt->sclist[i]; if (psc->used == FALSE) continue; // ÁöÁ¤ ½Ã°£ÀÌ °æ°úµÇ¾ú´ÂÁö üũ. Timeout µÇ¾úÀ¸¸é TimerÇÔ¼ö ¼öÇà. // if (DHL_OS_GetMsCount() - psc->start > psc->period) // Timer expired.. { S_OSX_CMD_SCHED schcmd = *psc; BOOL bOneShot = (schcmd.flags & eTASK_FLAG_Repeat) ? 0 : 1; if (bOneShot) { // 1ȸ ½ÇÇà ¸í·É. ÀÌ entry¸¦ »èÁ¦ ÇÑ´Ù. memset(psc, 0, sizeof(S_OSX_CMD_SCHED)); xt->nScheduledCmd--; } else { // ¹Ýº¹ ½ÇÇà ¸í·É. timer counter¸¦ ¸®¼Â½ÃŲ´Ù. psc->start = DHL_OS_GetMsCount(); } p_callback_user_func(xt, schcmd.idCmd, schcmd.flags, schcmd.fn, schcmd.params); if (bOneShot) if (s_osx_traced == xt) dprint(0, "oneshot cmd %x serviced\n", schcmd.idCmd); } } // end for (sch cmd list) } p_shutdown_task(xt); } #if COMMENT ____API____(){} #endif DHL_RESULT OSX_TaskRegisterCmdV(H_OSX_TASK handle, T_OSX_TASK_CMD nIdCmd, UINT32 nDelayMs, UINT16 flags, F_OSX_TASK_PROC func, va_list param) { DHL_RESULT dhr; S_OSX_TASK_PUBLIC pti0, *pti; S_OSX_TASK_CMD cmd; DHL_OS_TASK_ID tid = DHL_OS_GetTaskID(); va_list arg; int i; pti = p_get_osx_task(handle, &pti0); // get public task info if (pti == NULL) return DHL_FAIL_INVALID_HANDLE; if (func == NULL) { dprint(0, "!! func is null [cmd %x]!\n", nIdCmd); return DHL_FAIL_INVALID_PARAM; } if (nIdCmd >= eTASK_CMD_BEGIN || nIdCmd == 0) { dprint(0, "!! cmd id 0x%x is in reserved range.\n", nIdCmd); DHL_ASSERT(FALSE, ""); return DHL_FAIL_INVALID_PARAM; } if (nDelayMs == 0 && (flags & eTASK_FLAG_Repeat)) { dprint(0, "!! interval timer should have period.\n"); DHL_ASSERT(FALSE, ""); return DHL_FAIL_INVALID_PARAM; } dprint(2, "%s: (cmd 0x%x, period %d, flags 0x%x)\n", __func__, nIdCmd, nDelayMs, flags); memset(&cmd, 0, sizeof(S_OSX_TASK_CMD)); cmd.idCmd = nIdCmd; cmd.snTask = SERIAL_FROM_HANDLE(handle); cmd.nDelayMs = nDelayMs; cmd.func = func; cmd.flags = flags; for (i=0; inCmdParam; i++) cmd.params[i] = va_arg(param, UINT32); if (tid != pti->tid) { // cmd ÀÚü´Â ÃÖ´ë °¹¼öÀÇ user paramÀ» Æ÷ÇÔÇϰí ÀÖÁö¸¸ // OSAL ³»ºÎ¿¡¼­ ÇÊ¿äÇÑ ¸¸Å­¸¸ º¹»ç¸¦ ÇØ °¥ °ÍÀÌ´Ù. dhr = DHL_OS_SendMessage(pti->msgQue, &cmd, sizeof(cmd)); // error check.. if (dhr == DHL_FAIL_BUSY) { dprint(0, "!! %s queue full\a\n", __func__); // 0x18: DHL_FAIL_BUSY ´Â queue full ³ª¸é ¹ß»ýÇÔ. } else if (dhr) { dprint(0, "!! %s send cmd err %x\a\n", __func__, dhr); } } else { // current task is THE Task that we can add. // so, we can directly modify task variable. // dhr = p_add_scheduled_cmd(pti->xt, &cmd); } return dhr; } /* Task¿¡ ¸í·É ¿¹¾à. ¹Ýº¹ ¼³Á¤ °¡´É. */ DHL_RESULT OSX_TaskScheduleCmd(H_OSX_TASK handle, T_OSX_TASK_CMD nIdCmd, UINT32 nDelayMs, UINT16 flags, F_OSX_TASK_PROC func, ...) { DHL_RESULT dhr; va_list ap; va_start(ap, func); dhr = OSX_TaskRegisterCmdV(handle, nIdCmd, nDelayMs, flags, func, ap); va_end(ap); return dhr; } /* Task¿¡¼­ ¸í·É ½ÇÇà. */ DHL_RESULT OSX_TaskRunCmd(H_OSX_TASK handle, T_OSX_TASK_CMD nIdCmd, UINT16 flags, F_OSX_TASK_PROC func, ...) { DHL_RESULT dhr; va_list ap; // Áö¿¬, ¹Ýº¹ ¿É¼ÇÀº Á¦°Å. flags &= ~(eTASK_FLAG_Delayed | eTASK_FLAG_Repeat); va_start(ap, func); dhr = OSX_TaskRegisterCmdV(handle, nIdCmd, 0/* no delay */, flags, func, ap); va_end(ap); return dhr; } /* ¹Ýº¹ ¼³Á¤ µÈ (¶Ç´Â Áö¿¬ ½ÇÇà µî·ÏµÇ°í ¾ÆÁ÷ ½ÇÇàÀº ¾ÈµÈ) ¸í·ÉÀÇ Ãë¼Ò. */ DHL_RESULT OSX_TaskStopCmd(H_OSX_TASK handle, T_OSX_TASK_CMD nIdCmd) { DHL_RESULT dhr; S_OSX_TASK_PUBLIC pti0, *pti; S_OSX_TASK_CMD cmd; DHL_OS_TASK_ID tid = DHL_OS_GetTaskID(); pti = p_get_osx_task(handle, &pti0); if (pti == NULL) return DHL_FAIL_INVALID_HANDLE; if (nIdCmd == 0 || nIdCmd >= eTASK_CMD_BEGIN) { dprint(0, "!! invalid cmd %x\n", nIdCmd); return DHL_FAIL_INVALID_PARAM; } memset(&cmd, 0, sizeof(S_OSX_TASK_CMD)); cmd.idCmd = eTASK_CMD_DELETE; cmd.snTask = SERIAL_FROM_HANDLE(handle); cmd.params[0] = nIdCmd; if (tid != pti->tid) { dhr = DHL_OS_SendMessage(pti->msgQue, &cmd, sizeof(cmd)); if (dhr == DHL_FAIL_BUSY) { dprint(0, "!! %s queue full\a\n", __func__); // 0x18: DHL_FAIL_BUSY ´Â queue full ³ª¸é ¹ß»ýÇÔ. } else if (dhr) { dprint(0, "!! %s send cmd err %x\a\n", __func__, dhr); } } else { // current task is THE TIMER task that we can add. // so, we can directly modify timer variable. // dhr = p_del_scheduled_cmd(pti->xt, nIdCmd); } return dhr; } DHL_RESULT OSX_TaskSync(H_OSX_TASK handle) { DHL_RESULT dhr; S_OSX_TASK_PUBLIC pti0, *pti; S_OSX_TASK_CMD cmd; DHL_OS_TASK_ID tid = DHL_OS_GetTaskID(); pti = p_get_osx_task(handle, &pti0); if (pti == NULL) return DHL_FAIL_INVALID_HANDLE; memset(&cmd, 0, sizeof(S_OSX_TASK_CMD)); cmd.idCmd = eTASK_CMD_SYNC; cmd.snTask = SERIAL_FROM_HANDLE(handle); if (tid != pti->tid) { int wait_count; // need ack mechanism.. DHL_OS_TakeSemaphore(pti->mutexAck, DHL_TIMEOUT_FOREVER); // mutex wait µµÁß¿¡ task°¡ shutdown µÇ¾úÀ» ¼ö ÀÖ´Ù. pti = p_get_osx_task(handle, &pti0); if (pti == NULL) { dprint(0, "!! task stop while wait sync..\n"); dhr = DHL_FAIL; goto end_mutex; } DHL_OS_TakeSemaphore(pti->semAck, 0); // reset to none dhr = DHL_OS_SendMessage(pti->msgQue, &cmd, sizeof(cmd)); if (dhr == DHL_FAIL_BUSY) { dprint(0, "!! %s queue full\a\n", __func__); // 0x18: DHL_FAIL_BUSY ´Â queue full ³ª¸é ¹ß»ýÇÔ. goto end_mutex; } else if (dhr) { dprint(0, "!! %s send cmd err %x\a\n", __func__, dhr); // ¿¡·¯°¡ ¹ß»ýÇß´Ù¸é wait ÇÏ´Â °ÍÀº Àǹ̰¡ ¾ø°Ô µÈ´Ù. ¿¡·¯ ¾ø´Â °æ¿ì¿¡¸¸ ÁøÇà. goto end_mutex; } /* ÀÌ sync ¸í·É º¸´Ù ¸ÕÀú shutdown ¸í·ÉÀÌ ÀÖ´ø °æ¿ì¶ó¸é ack ÀÀ´äÀº ¾È ¿Ã ¼ö ÀÖÀ½. */ for (wait_count=0 ; wait_count<5; wait_count++) { if (wait_count) dprint(0, "!! task (handle %x) not responding.. wait %d..\n", handle, wait_count); dhr = DHL_OS_TakeSemaphore(pti->semAck, 1000); if (dhr == DHL_OK) break; } end_mutex: DHL_OS_GiveSemaphore(pti->mutexAck); } else { dprint(0, "!! sync called inside task\n"); //DHL_ASSERT(FALSE, "invalid usage\n"); } return dhr; } /* taskÀÇ °£´ÜÇÑ Á¤º¸ ¹× ¿¹¾à µÈ ¸í·Éµé È­¸é Ãâ·Â. */ void OSX_TaskShow(H_OSX_TASK handle) { DHL_RESULT dhr; S_OSX_TASK_PUBLIC pti0, *pti; S_OSX_TASK_CMD cmd; DHL_OS_TASK_ID tid = DHL_OS_GetTaskID(); if (handle == 0) { // ÇöÀç µ¿ÀÛÁßÀÎ ¸ðµç task list¸¸ Ãâ·Â. H_OSX_TASK list[OSX_MAX_TASK]; int i, n_task; n_task = p_list_all_osx_task(list); for(i=0; itid) { // send command asynchronously.. dhr = DHL_OS_SendMessage(pti->msgQue, &cmd, sizeof(cmd)); if (dhr) { // error check.. dprint(0, "!! %s send cmd err %x\a\n", __func__, dhr); } } else { p_show_scheduled_cmd(pti->xt, &cmd); } if (handle) // show only specified task. break; if (tid != pti->tid) { //DHL_OS_Delay(100); // wait for timer tasks to print information } }while (0); } /* */ void OSX_TaskGetInfo(H_OSX_TASK handle, S_OSX_TASK_INFO *pinfo) { S_OSX_TASK_PUBLIC pti0, *pti; pti = p_get_osx_task(handle, &pti0); // get public task info if (pinfo) { pinfo->tid = pti ? pti->tid : 0; } } #if COMMENT ____API____(){} #endif void OSX_TaskGetDefaultInitSetting(S_OSX_TASK_INIT_SETTING *setting) { if (setting) { memset(setting, 0, sizeof(*setting)); setting->name = ""; setting->max_scheduled_cmd = 4; setting->priority = 32; setting->stack_size = 8192; //setting->num_cmd_param = 1; setting->msg_que_size = 2; } } /* */ DHL_RESULT OSX_TaskStart(S_OSX_TASK_INIT_SETTING *setting, H_OSX_TASK *pHandle) { DHL_RESULT dhlResult = DHL_OK; char buf[20]; S_OSX_TASK *xt; H_OSX_TASK handle = 0; DHL_OS_TASK_ID tid = 0; osx_module_init(); dprint(2, "%s: '%s', prio %d, stack %d, qsize %d, #param %d, max delayed cmd %d\n", __func__, setting->name, setting->priority, setting->stack_size, setting->msg_que_size, setting->num_cmd_param, setting->max_scheduled_cmd, 0); *pHandle = 0; // initialize first.. //------- check settings parameter if (setting->max_scheduled_cmd <= 0) { dprint(0, "!! max sched cmd %d invalid.\n", setting->max_scheduled_cmd); dhlResult = DHL_FAIL_INVALID_PARAM; //DHL_ASSERT(FALSE, ""); goto label_end; } if (setting->num_cmd_param < 0 || setting->num_cmd_param > OSX_MAX_CMD_PARAMS) { dprint(0, "!! num user param %d invalid.\n", setting->num_cmd_param); dhlResult = DHL_FAIL_INVALID_PARAM; //DHL_ASSERT(FALSE, ""); goto label_end; } if (setting->msg_que_size < 0) { dprint(0, "!! que size %d invalid.\n", setting->msg_que_size); dhlResult = DHL_FAIL_INVALID_PARAM; goto label_end; } //------- allocate osx task xt = p_alloc_osx_task(); if (!xt) { dprint(0, "!! no more available osx task\n"); dhlResult = DHL_FAIL_OUT_OF_RESOURCE; goto label_end; } //------- initialize task variables //memset(xt, 0, sizeof(*xt)); // done in alloc_osx_task(). // name of timers strncpy(xt->name, setting->name, OSX_MAX_TASK_NAME); xt->name[OSX_MAX_TASK_NAME] = 0; // max timer slots xt->nMaxSlot = setting->max_scheduled_cmd; // no active timer now. xt->maxActiveIndex = -1; xt->sclist = (S_OSX_CMD_SCHED *) DHL_OS_Malloc( setting->max_scheduled_cmd* sizeof(S_OSX_CMD_SCHED) + 4); // 4 is margin. if (xt->sclist == NULL) { dhlResult = DHL_FAIL_OUT_OF_MEMORY; goto label_end; } // message que size if (setting->msg_que_size == 0) xt->nMaxQueSize = OSX_DEFAULT_MSG_QUE_SIZE; // for backward compatibility else if (setting->msg_que_size > 0) xt->nMaxQueSize = setting->msg_que_size; //------ preprare public task info ------ // num user param if (setting->num_cmd_param <= 0) // ÃÖ¼ÒÇÑ 1°³ÀÇ ÆÄ¶ó¹ÌÅÍ °ø°£Àº ÇÊ¿äÇÏ´Ù. ³»ºÎ ¸í·É Áß¿¡ ÀÌ ¿µ¿ªÀ» »ç¿ëÇÏ´Â °ÍµéÀÌ ÀÖÀ½. xt->pti.nCmdParam = 1; else xt->pti.nCmdParam = setting->num_cmd_param; // task´Â ¸Ç ¸¶Áö¸·¿¡ »ý¼ºÇÏ´Â °Ô ÁÁ´Ù. priority °ü·ÃÇÏ¿© ¸ÕÀú ½ÇÇà °¡´É¼ºÀÌ ÀÖÀ¸¹Ç·Î.. // memset(buf, 0, sizeof(buf)); strcpy(buf, "TS"); // task ack sem strncpy(buf+2, xt->name, 6); xt->pti.semAck = DHL_OS_CreateBinarySemaphore(buf, 0, 0); if (xt->pti.semAck == 0) { dprint(0, "!! Creating sem err\n"); dhlResult = DHL_FAIL_OUT_OF_RESOURCE; goto label_end; } memset(buf, 0, sizeof(buf)); strcpy(buf, "TM"); // task ack mutex strncpy(buf+2, xt->name, 6); xt->pti.mutexAck = DHL_OS_CreateMutexSemaphore(buf); if (xt->pti.mutexAck == 0) { dprint(0, "!! Creating mutex err\n"); dhlResult = DHL_FAIL_OUT_OF_RESOURCE; goto label_end; } memset(buf, 0, sizeof(buf)); strcpy(buf, "TQ"); // task cmd que strncpy(buf+2, xt->name, 6); xt->pti.msgQue = DHL_OS_CreateMessageQueue(buf, 0, xt->nMaxQueSize, OSX_COMMAND_SIZE(xt->pti.nCmdParam)); if (xt->pti.msgQue == 0) { dprint(0, "!! Creating msgq err\n"); dhlResult = DHL_FAIL_OUT_OF_RESOURCE; goto label_end; } xt->pti.xt = xt; // self. xt->setting = *setting; xt->setting.name = xt->name; //------- launch task handle = MAKE_OSX_HANDLE(xt->index, xt->serial); /* task priority°¡ ³ôÀ» °æ¿ì ÀÌ ÇÔ¼ö°¡ Á¾·áµÇÁö Àü¿¡µµ ¹Ù·Î task°¡ ½ÇÇà µÉ ¼ö ÀÖÀ½¿¡ À¯ÀÇÇÒ °Í. */ tid = DHL_OS_CreateTask((DHL_OS_TASKFUNCTION) p_task_main, xt->name, setting->priority, setting->stack_size, (UINT32)xt); if (tid == (DHL_OS_TASK_ID) 0) { dprint(0, "!! osx task create err\n"); dhlResult = DHL_FAIL_OUT_OF_RESOURCE; goto label_end; } p_validate_osx_task(xt); // now, xt is "VALID" xt->pti.tid = tid; // now, task is running. if (pHandle) *pHandle = handle; xt = 0; label_end: if (xt) { // clean up! dprint(0, "!! err occurred in task init. clean up!\n"); if (xt->sclist) DHL_OS_Free((void **)&xt->sclist); if (xt->pti.semAck) DHL_OS_DeleteSemaphore(xt->pti.semAck); if (xt->pti.mutexAck) DHL_OS_DeleteSemaphore(xt->pti.mutexAck); if (xt->pti.msgQue) DHL_OS_DeleteMessageQueue(xt->pti.msgQue); p_free_osx_task(xt); } return dhlResult; } /** @todo Task Á¾·á OSAL API°¡ ¾ø´Ù¸é internal ¿ëµµÀÇ functionÀ» ¸¸µé¾î¼­ OSAL_Priv.h ¿¡ µî·ÏÇØ ³õ°í »ç¿ëÇÏ¸é µÉ °Í °°À½. */ void OSX_TaskShutdown(H_OSX_TASK handle) { DHL_RESULT dhlResult; S_OSX_TASK_PUBLIC pti0, *pti; UINT32 i; S_OSX_TASK_CMD cmd; DHL_OS_TASK_ID tid = DHL_OS_GetTaskID(); osx_module_init(); // TimerTask°¡ ÀÚµ¿À¸·Î Á×À»¶§±îÁö ±â´Ù¸± ½Ã°£.. #define WAIT_TIME 1 // second. #define CHECK_PER_SECOND 10 // times. pti = p_get_osx_task(handle, &pti0); if (pti == NULL) { dprint(0, "!! invalid osx task handle %x\n", handle); return; } if (tid == pti->tid) { dprint(0, "!! %s: cannot shutdown timer in itself\n", __func__); return; } memset(&cmd, 0, sizeof(S_OSX_TASK_CMD)); cmd.idCmd = eTASK_CMD_SHUTDOWN; dhlResult = DHL_OS_SendMessage(pti->msgQue, &cmd, sizeof(cmd)); if (dhlResult) { // error check.. dprint(0, "!! %s send cmd err %x\n", __func__, dhlResult); } else { for (i = 0; i < WAIT_TIME*CHECK_PER_SECOND; ++i) { if (pti->tid == 0) { break; } DHL_OS_Delay(1000/CHECK_PER_SECOND); } // ÃæºÐÈ÷ ±â´Ù·È°Ç¸¸, Self Delete°¡ µÇÁö ¾Ê¾ÒÀ» °æ¿ì ¿¡·¯ ¸Þ½ÃÁö. // if (pti->tid != 0) { dprint(0, "!! osx task shutdown timeout!\n"); } } pti->tid = 0; } #if COMMENT ____Symbol____(){} #endif #if DHL_REGISTER_DEUBG_SYMBOLS static DHL_SymbolTable _symbols[] = { //---- functions //DHL_FNC_SYM_ENTRY(xxx), //---- variables DHL_VAR_SYM_ENTRY(s_osx_traced), }; #endif // DHL_REGISTER_DEBUG_SYMBOL #if COMMENT ____Init____(){} #endif void osx_module_init(void) { if (s_module_init) return; s_osx_mutex = DHL_OS_CreateMutexSemaphore("OSX"); DHL_ASSERT(s_osx_mutex != 0, ""); #if DHL_REGISTER_DEUBG_SYMBOLS DHL_DBG_RegisterSymbols(_symbols, DHL_NUMSYMBOLS(_symbols)); #endif s_module_init = TRUE; } void osx_trace(UINT32 handle) { S_OSX_TASK_PUBLIC pti0, *pti; pti = p_get_osx_task(handle, &pti0); if (!pti) { dprint(0, "!! invalid handle %x\n", handle); return; } dprint(0, "trace osx task handle %x, task %x\n", handle, pti->xt); s_osx_traced = pti->xt; } #if COMMENT ____Test____(){} #endif #if 1 // test #define printf DHL_OS_Printf H_OSX_TASK s_osx_test_handle; void osx_test_init(void) { DHL_RESULT dhr; S_OSX_TASK_INIT_SETTING stg; if (s_osx_test_handle) { printf("already run\n"); return; } OSX_TaskGetDefaultInitSetting(&stg); stg.num_cmd_param = 2; dhr = OSX_TaskStart(&stg, &s_osx_test_handle); if (dhr) printf("!! task start err %x\n", dhr); else printf("task handle %x\n", s_osx_test_handle); } void osx_test_uninit(void) { if (s_osx_test_handle == 0) return; OSX_TaskShutdown(s_osx_test_handle); s_osx_test_handle = 0; } static void osx_cmd_1(int cmd, int arg1, int arg2) { printf("**** cmd %x, arg %x %x\n", cmd, arg1, arg2); } static void osx_cmd_4(int cmd, int arg1, int arg2) { printf("**** cmd %x, wait %d sec..\n", cmd, arg1); DHL_OS_Delay(arg1*1000); printf("---- cmd exec end\n"); } void osx_test_stop(int cmd) { OSX_TaskStopCmd(s_osx_test_handle, cmd); } void osx_test_run1(int arg1, int arg2) { OSX_TaskRunCmd (s_osx_test_handle, 1, 0, (F_OSX_TASK_PROC)osx_cmd_1, arg1, arg2); } void osx_test_run2(int wait) // delayed { OSX_TaskScheduleCmd(s_osx_test_handle, 2, wait*1000, eTASK_FLAG_Delayed, (F_OSX_TASK_PROC)osx_cmd_1, 0, 0); } void osx_test_run3(int period) // repeat { OSX_TaskScheduleCmd(s_osx_test_handle, 3, period*1000, eTASK_FLAG_Repeat, (F_OSX_TASK_PROC)osx_cmd_1, 0, 0); } void osx_test_run4(int arg1, int arg2) // { OSX_TaskRunCmd (s_osx_test_handle, 4, 0, (F_OSX_TASK_PROC)osx_cmd_4, arg1, arg2); } /* sml osx 3 osx_test_init osx_trace 0x10001 OSX_TaskShow OSX_TaskShow 0x10001 // basic dpc test osx_test_run1 0x33 0x44 // delayed exec test osx_test_run2 1 osx_test_run2 2 osx_test_run2 5 osx_test_stop 2 // repeat exec test osx_test_run3 1 osx_test_stop 3 // queue full test osx_test_run4 5 osx_test_run1 osx_test_run1 osx_test_run1 !! OSX_TaskRegisterCmdV send cmd err 18 osx_test_run1 */ #endif // test /* end of file */