/************************************************************************ * AUTHOR: NiuJiuRu * FILENAME: swthrd.c * DESCRIPTION: 线程操作 * NOTE: * HISTORY: * 1, [2010-12-18] created by NiuJiuRu * 2, [2014-05-13] 修改"sw_thrd_delay()"函数, 当延时时间为负数时, 线程将 * 无限等待; 修改"ThrdProc()"函数,去除不必要的信号检测函 * 数, 提高用户回调函数的调用性能. ***********************************************************************/ #include "swapi.h" #include "swstring.h" #include "swsignal.h" #include "swmem.h" #include "swthrd.h" // 线程的调度策略(1 - "SCHED_FIFO"实时调度策略,先到先服务; 2 - "SCHED_RR"实时调度策略,时间片轮转) #define MY_SCHEDPOLICY SCHED_RR typedef struct { // 线程的名称 char name[32]; // 线程的ID号 pthread_t nThrdID; // 线程的控制事件 void *hCtlEvent; // 线程的退出信号灯 void *hEndSignal; // 线程的(用户)回调函数 PThrdProc proc; unsigned long wParam; unsigned long lParam; // 线程是否暂停运行 volatile bool bPause; // 线程是否正在执行(用户)回调函数还没有返回 volatile bool bBusy; // 线程是否已退出 volatile bool bQuit; } SThrdInfo; // 匿名线程计数器 static int s_nameless_thrd_counter = 0; // 线程的执行函数 static void ThrdProc(void *lpParameter); /* 创建线程, 成功后默认处于暂停状态 */ void *sw_thrd_create(const char *name, int priority, int stack_size, PThrdProc proc, unsigned long wParam, unsigned long lParam) { SThrdInfo *pInfo = NULL; pthread_attr_t attr; // 线程的属性对象 int policy = 0; // 调度策略 pInfo = (SThrdInfo *)sw_heap_malloc(sizeof(SThrdInfo)); if(!pInfo) goto ErrorP; memset(pInfo, 0, sizeof(SThrdInfo)); // 设置线程的名称 if(name) strncpy(pInfo->name, name, sizeof(pInfo->name)-1); else snprintf(pInfo->name, sizeof(pInfo->name)-1, "nameless%d thread", s_nameless_thrd_counter++); // 产生线程的控制事件 pInfo->hCtlEvent = sw_signal_create(); if(!pInfo->hCtlEvent) goto ErrorP; // 创建线程的退出信号灯 pInfo->hEndSignal = sw_signal_create(); if(!pInfo->hEndSignal) goto ErrorP; // 设置线程的(用户)回调函数 pInfo->proc = proc; pInfo->wParam = wParam; pInfo->lParam = lParam; // 初始化线程属性对象 pthread_attr_init(&attr); // 设置线程的调度策略 if(priority > 0) { pthread_attr_getschedpolicy(&attr, &policy); if(policy != MY_SCHEDPOLICY) { policy = MY_SCHEDPOLICY; if(pthread_attr_setschedpolicy(&attr, policy) != 0) goto ErrorP; } } else pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); // 绑定的, 此线程将与系统中的所有线程进行竞争 // 堆栈大小 if(pthread_attr_setstacksize(&attr, stack_size) != 0) goto ErrorP; // 创建线程, 成功后线程默认处于暂停状态 pInfo->bPause = true; pInfo->bBusy = false; pInfo->bQuit = false; if(pthread_create(&pInfo->nThrdID, &attr, (void *)ThrdProc, (void *)pInfo) != 0) goto ErrorP; // 销毁线程属性对象 pthread_attr_destroy(&attr); // 设置线程的优先级 sw_thrd_setPriority(pInfo, priority); // 等待线程状态稳定 sw_thrd_delay(THRDWAIT_DELAY); return pInfo; ErrorP: pthread_attr_destroy(&attr); // 销毁线程属性对象 sw_thrd_destroy(pInfo, 0); return NULL; } /* 销毁线程, 在"wait time <= timout(ms)"前尝试安全的关闭线程, "wait time > timout"后则强制关闭 */ void sw_thrd_destroy(void *hThrd, int timeout) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return; if(pInfo->nThrdID != 0) { pInfo->bQuit = true; sw_thrd_resume(pInfo); if(sw_signal_wait(pInfo->hEndSignal, timeout) == 0) ; // 尝试安全的关闭线程 else if(pthread_cancel(pInfo->nThrdID) != 0) // 强制关闭线程 { sw_log_error("terminate %s error(errno=%d)!!", pInfo->name, errno); } pthread_join(pInfo->nThrdID, NULL); pInfo->nThrdID = 0; } if(pInfo->hCtlEvent) { sw_signal_destroy(pInfo->hCtlEvent); pInfo->hCtlEvent = NULL; } if(pInfo->hEndSignal) { sw_signal_destroy(pInfo->hEndSignal); pInfo->hEndSignal = NULL; } sw_heap_free(pInfo); } /* 暂停运行线程 */ void sw_thrd_pause(void *hThrd) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return; while(sw_signal_wait(pInfo->hCtlEvent, 0) == 0) sw_thrd_delay(1); pInfo->bPause = true; } /* 继续运行线程 */ void sw_thrd_resume(void *hThrd) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return; pInfo->bPause = false; sw_signal_give(pInfo->hCtlEvent); } /* 延时(毫秒) */ void sw_thrd_delay(int ms) { if(ms < 0) select(0, NULL, NULL, NULL, NULL); else { struct timeval tv = { 0 }; tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; select(0, NULL, NULL, NULL, &tv); } } /* 检查线程是否还存在 */ bool sw_thrd_isAlive(void *hThrd) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return false; return (pInfo->nThrdID != 0 && pInfo->bQuit == false); } /* 检查线程是否正在运行: true = 是, false = 否 */ bool sw_thrd_isRunning(void *hThrd) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return false; return (pInfo->nThrdID != 0 && pInfo->bQuit == false && pInfo->bPause == false); } /* 检查线程是否正在执行(用户)回调函数还没有返回: true = 是, false = 否 */ bool sw_thrd_isBusy(void *hThrd) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return false; return pInfo->bBusy; } /* 设置线程名称 */ bool sw_thrd_setName(void *hThrd, const char *name) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo || !name) return false; memset(pInfo->name, 0, sizeof(pInfo->name)); strncpy(pInfo->name, name, sizeof(pInfo->name)-1); return true; } /* 取得线程名称 */ char *sw_thrd_getName(void *hThrd, char *name) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo || !name) return NULL; strcpy(name, pInfo->name); return name; } /* 设置线程优先级 */ bool sw_thrd_setPriority(void *hThrd, int priority) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; struct sched_param sparam = { 0 }; if(!pInfo) return false; sparam.__sched_priority = priority; if(pthread_setschedparam(pInfo->nThrdID, MY_SCHEDPOLICY, &sparam) == 0) return true; else return false; } /* 取得线程优先级 */ int sw_thrd_getPriority(void *hThrd) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; struct sched_param sparam = { 0 }; int policy; if(!pInfo) return -1; if(pthread_getschedparam(pInfo->nThrdID, &policy, &sparam) == 0) return sparam.__sched_priority; else return -1; } /* 设置线程执行的(用户)回调函数 */ bool sw_thrd_setProc(void *hThrd, PThrdProc proc, unsigned long wParam, unsigned long lParam) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return false; pInfo->proc = proc; pInfo->wParam = wParam; pInfo->lParam = lParam; return true; } /* 取得线程执行的(用户)回调函数 */ void sw_thrd_getProc(void *hThrd, PThrdProc *proc, unsigned long *wParam, unsigned long *lParam) { SThrdInfo *pInfo = (SThrdInfo *)hThrd; if(!pInfo) return; if(proc) *proc = pInfo->proc; if(wParam) *wParam = pInfo->wParam; if(lParam) *lParam = pInfo->lParam; } // 线程的执行函数 static void ThrdProc(void *lpParameter) { SThrdInfo *pInfo = (SThrdInfo *)lpParameter; int delay = 0; while(pInfo->bQuit == false) { if(pInfo->bPause) sw_signal_wait(pInfo->hCtlEvent, WAIT_FOREVER); if(pInfo->proc) { pInfo->bBusy = true; delay = pInfo->proc(pInfo->wParam, pInfo->lParam); pInfo->bBusy = false; } else delay = 1; if(delay < 0) pInfo->bQuit = true; else if(delay > 0) sw_signal_wait(pInfo->hCtlEvent, delay); } pInfo->proc = NULL; pInfo->wParam = pInfo->lParam = 0; sw_signal_give(pInfo->hEndSignal); // 点亮"退出信号灯", 表明线程已正常结束 pthread_exit("thread normal exit."); }