http://vincent.blog.chinaunix.net最近在阅读关于电池充电的驱动代码,芯片是PM8606和PM8607,大概的原理就是主控芯片通过I2C总线和PM860x芯片通信,然后linux驱动挂接一个IRQ响应PM860x的中断信息,然后在IRQ的相应代码里通过I2C总线去读PM860x的中断寄存器状态(3个),然后根据指定的不同位置位来区别不同的事件,根据不同的事件去抛出一个工作给内核的工作队列去执行相关任务,这任务的主要内容是根据不同的事件去跑一个有穷状态机的流程,状态机主要工作就是自己设定PM860x的一些电压,电流,温度的门槛,当充电到一定程序越过这些门槛就进入下一个状态,然后重新设定相关门槛。然后还有一个定时器驱动的工作也定时的抛出任务给工作队列,主要是读取当前PM860x一些电压,电流,温度信息,然后根据这些信息做安全保护的作用。
其中我对里面的工作队列实现比较有兴趣,就自己用线程池模拟多cpu的情况实现了一个,不过区别还是蛮大的,还有就是实现时,我调试了一个很久的问题,就是我仿照linux的内核调用去INITWORK(work,func)时,发现work是静态的,然后插入到队列,后来发现这样是有问题,因为当我连续插入相同多个静态work时,work的链表指针已经被修改了,引起问题,还有就是多线程的同步时,由于多个锁,经常在退出时,忘记把相关的其它锁也释放,引起死锁。。。反正就是多联系,多调试。。。
下面是我实现的原理图:
代码如下:
- /**
-
* file: main.c
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* @2011-11-06: initial
-
* @2011-11-13: add the notifier to register
-
*/
-
-
#include "threadpool.h"
-
#include "stdio.h"
-
#include "workqueuex.h"
-
#include <stdlib.h>
-
#include <time.h>
-
-
static lock_t lock;
-
-
void fwork_1(struct work_s *pwork)
-
{
-
/* need to deleted by it self */
-
__lockx(lock);
-
printf("function: %s[thread_id:%08x] running ...\n", "fwork_1", gettidx());
-
fflush(stdout);
-
__unlockx(lock);
-
FREE_WORK(pwork);
-
}
-
-
void fwork_2(struct work_s *pwork)
-
{
-
/* need to deleted by it self */
-
__lockx(lock);
-
printf("function: %s[thread_id:%08x] running ...\n", "fwork_2", gettidx());
-
fflush(stdout);
-
__unlockx(lock);
-
FREE_WORK(pwork);
-
}
-
void fwork_3(struct work_s *pwork)
-
{
-
/* need to deleted by it self */
-
__lockx(lock);
-
printf("function: %s[thread_id:%08x] running ...\n", "fwork_3", gettidx());
-
fflush(stdout);
-
__unlockx(lock);
-
FREE_WORK(pwork);
-
}
-
void fwork_4(struct work_s *pwork)
-
{
-
/* need to deleted by it self */
-
__lockx(lock);
-
printf("function: %s[thread_id:%08x] running ...\n", "fwork_4", gettidx());
-
fflush(stdout);
-
__unlockx(lock);
-
FREE_WORK(pwork);
-
}
-
-
static fwork_t fworks[] = {
-
fwork_1,
-
fwork_2,
-
fwork_3,
-
fwork_4,
-
};
-
-
void main()
-
{
-
int count = 100;
-
work_t *pnew=null;
-
tasks_sched_t *pts = get_tasks_sched();
-
__assert(pts);
-
__lockx_init(lock,0);
-
-
srand ((unsigned)time(NULL));
-
-
init_tasks_sched();
-
-
while (count--)
-
{
-
int n = rand()%ARRAY_SIZE(fworks);
-
NEW_WORK(pnew,fworks[n]);
-
schedule_work(pnew);
-
}
-
//while (1);
-
sleep(5000);
-
exit_tasks_sched();
-
__lockx_exit(lock,0);
-
}
- /**
-
* file: notifierx.c
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* initial @ 2011-11-13
-
*/
-
-
#include "notifierx.h"
-
-
-
int notifierx_chain_register(struct notifierx_head *pnh,
-
struct notifierx_block *pnb)
-
{
-
__assert(pnh&&pnb);
-
__lockx(pnh->cslock);
-
list_add(&pnb->list, &pnh->head);
-
__unlockx(pnh->cslock);
-
return 0;
-
}
-
-
int notifierx_chain_all_unregister(struct notifierx_head *pnh)
-
{
-
struct list_head *list_p;
-
notifierx_block_t* pnb_it=null;
-
notifierx_block_t* pnb_temp=null;
-
__assert(pnh);
-
-
__lockx(pnh->cslock);
-
list_for_each_safe(list_p, pnb_temp, &(pnh->head))
-
{
-
pnb_it = list_entry(list_p, notifierx_block_t, list);
-
list_del(&pnb_it->list);
-
}
-
-
__unlockx(pnh->cslock);
-
-
return 0;
-
}
-
-
int notifierx_chain_unregister(struct notifierx_head *pnh,
-
struct notifierx_block *pnb)
-
{
-
struct list_head *list_p;
-
struct notifierx_block *pnb_it;
-
__assert(pnh&&pnb);
-
-
__lockx(pnh->cslock);
-
list_for_each(list_p, &(pnh->head))
-
{
-
pnb_it = list_entry(list_p, notifierx_block_t, list);
-
if (pnb_it->notifierx_call == pnb->notifierx_call)
-
{
-
list_del(&pnb_it->list);
-
__unlockx(pnh->cslock);
-
return 0;
-
}
-
}
-
__unlockx(pnh->cslock);
-
return -1;
-
}
-
-
int notifierx_call_chain(struct notifierx_head *pnh, unsigned long nlen, void *pdata)
-
{
-
struct list_head *list_p;
-
notifierx_block_t* pnb_it=null;
-
-
__assert(pnh);
-
-
__lockx(pnh->cslock);
-
list_for_each(list_p, &(pnh->head))
-
{
-
pnb_it = list_entry(list_p, notifierx_block_t, list);
-
pnb_it->notifierx_call(pnb_it, nlen, pdata);
-
}
-
__unlockx(pnh->cslock);
-
-
return 0;
-
}
- /**
-
* file: notifierx.h
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* initial @ 2011-11-13
-
*/
-
-
#ifndef _NOTIFIERX_H_
-
#define _NOTIFIERX_H_
-
-
#include "list.h"
-
#include "platform.h"
-
-
typedef struct notifierx_block {
-
int (*notifierx_call)(struct notifierx_block *pnb, unsigned long nlen, const void *pdata);
-
struct list_head list;
-
}notifierx_block_t;
-
-
struct notifierx_head {
-
lock_t cslock;
-
attr_t attr;
-
struct list_head head;
-
};
-
-
#define INIT_NOTIFIERX_HEAD(name) do { \
-
__lockx_init((name).cslock,(name).attr); \
-
INIT_LIST_HEAD(&(name).head); \
-
} while (0)
-
-
-
#define EXIT_NOTIFIERX_HEAD(name) do { \
-
notifierx_chain_all_unregister(&(name)); \
-
__lockx_exit((name).cslock, (name).attr); \
-
} while (0)
-
-
extern int notifierx_chain_register(struct notifierx_head *pnh, struct notifierx_block *pnb);
-
extern int notifierx_chain_all_unregister(struct notifierx_head *pnh);
-
extern int notifierx_chain_unregister(struct notifierx_head *pnh, struct notifierx_block *pnb);
-
extern int notifierx_call_chain(struct notifierx_head *pnh, unsigned long nlen, void *pdata);
-
-
#endif
- /**
-
* file: platform.h
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* @2011-11-15: initial
-
*/
-
-
#ifndef _PLATFORM_H_
-
#define _PLATFORM_H_
-
-
#ifdef WIN32
-
# include "windows.h"
-
#else
-
# include <pthread.h>
-
#endif
-
-
#ifndef null
-
#define null (void*)0
-
#endif
-
-
#ifndef NULL
-
#define NULL (void*)0
-
#endif
-
-
#ifndef __assert
-
#define __assert(x)
-
#endif
-
-
-
#ifdef WIN32
-
#define sleep Sleep
-
#define gettidx() GetCurrentThreadId()
-
#else
-
#define gettidx() pthread_self()
-
#endif
-
-
#ifdef WIN32
-
# define thrd_handle HANDLE
-
# define event_t HANDLE
-
# define lock_t CRITICAL_SECTION
-
# define attr_t void*
-
#else
-
# define thrd_handle pthread_t
-
# define event_t pthread_cond_t
-
# define lock_t pthread_mutex_t
-
# define attr_t pthread_mutexattr_t
-
#endif
-
-
#ifdef WIN32
-
-
#ifndef hnull
-
#define hnull INVALID_HANDLE_VALUE
-
#endif
-
#ifndef null
-
#define null NULL
-
#endif
-
#define __lockx(lock) EnterCriticalSection(&(lock))
-
#define __unlockx(lock) LeaveCriticalSection(&(lock))
-
#define __lockx_init(lock,attr) InitializeCriticalSection(&(lock))
-
#define __lockx_exit(lock,attr) DeleteCriticalSection(&(lock));
-
-
#else
-
-
#ifndef hnull
-
#define hnull (void*)0
-
#endif
-
#ifndef null
-
#define null (void*)0
-
#endif
-
#define __lockx(lock) pthread_mutex_lock(&(lock))
-
#define __unlockx(lock) pthread_mutex_unlock(&(lock))
-
#define __lockx_init(lock,attr) \
-
pthread_mutexattr_init(&(attr)); \
-
pthread_mutexattr_settype(&(attr),PTHREAD_MUTEX_RECURSIVE); \
-
pthread_mutex_init(&(lock),&(attr)); \
-
-
#define __lockx_exit(attr,attr) \
-
pthread_mutex_destroy(&(lock)); \
-
pthread_mutexattr_destroy(&(attr)); \
-
-
#endif
-
-
-
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-
#endif
- /**
-
* file: threadpool.c
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* @2011-11-06: initial
-
* @2011-11-13: add the notifier to register
-
*/
-
-
#include "threadpool.h"
-
-
#ifdef WIN32
-
static DWORD WINAPI thread_proc(LPVOID pvoid)
-
#else
-
static void *thread_proc(void *pvoid)
-
#endif
-
{
-
thrdpool_t* pthrdpool = thrdpool();
-
thrd_desc_t* pthrd_desc=(thrd_desc_t*)pvoid;
-
-
thrd_msg_t thrd_msg;
-
-
__assert(pthrd_desc&&pthrdpool);
-
-
INIT_THRD_MSG(thrd_msg, pthrd_desc->h);
-
-
while (1)
-
{
-
# ifdef WIN32
-
if (WaitForSingleObject((HANDLE)(pthrd_desc->hevent_go), INFINITE) == WAIT_OBJECT_0)
-
# else
-
int ret=0;
-
__lockx(pthrd_desc->cslock);
-
ret = pthread_cond_wait(&pthrd_desc->hevent_go, &pthrd_desc->cslock);
-
__unlockx(pthrd_desc->cslock);
-
if (ret == 0)
-
# endif
-
{
-
call_chain(pthrdpool->thrdpool_chain,thrd_msg,stat_busy);
-
__lockx(pthrd_desc->cslock);
-
while(pthrd_desc->ref_cnts>0) {
-
if (pthrd_desc->thrd_hook)
-
pthrd_desc->thrd_hook(pthrd_desc->pthrd_data);
-
pthrd_desc->ref_cnts--;
-
}
-
# ifdef WIN32
-
RESET_EVENT(pthrd_desc->hevent_go);
-
# endif
-
if (pthrd_desc&&pthrdpool->mod)
-
CLEAN_THRD_HOOK(*pthrd_desc);
-
__unlockx(pthrd_desc->cslock);
-
-
}
-
# ifdef WIN32
-
if (WaitForSingleObject(pthrd_desc->hevent_exit, 0) == WAIT_OBJECT_0)
-
break;
-
# endif
-
-
call_chain(pthrdpool->thrdpool_chain,thrd_msg,stat_free);
-
} /* while(1) */
-
return 0;
-
}
-
-
static thrd_handle __thrd_alloc(thrd_hook_t thrd_hook, void* pdata)
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
__lockx(pthrdpool->cslock);
-
list_for_each(list_p, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
if (!pthrd_desc->thrd_hook)
-
{
-
__lockx(pthrd_desc->cslock);
-
SET_HANDLER_THRD_DESC(*pthrd_desc, thrd_hook, pdata);
-
__unlockx(pthrd_desc->cslock);
-
__unlockx(pthrdpool->cslock);
-
return pthrd_desc->h;
-
}
-
}
-
__unlockx(pthrdpool->cslock);
-
return 0;
-
}
-
-
static int __has_free_thrds()
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
__lockx(pthrdpool->cslock);
-
list_for_each(list_p, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
if (0==pthrd_desc->ref_cnts) {
-
__unlockx(pthrdpool->cslock);
-
return 1;
-
}
-
}
-
__unlockx(pthrdpool->cslock);
-
return 0;
-
}
-
-
static void __thrd_free(thrd_handle h)
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
__lockx(pthrdpool->cslock);
-
list_for_each(list_p, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
if (h == pthrd_desc->h) {
-
__lockx(pthrd_desc->cslock);
-
CLEAR_THRD_DESC(*pthrd_desc);
-
__unlockx(pthrd_desc->cslock);
-
}
-
}
-
__unlockx(pthrdpool->cslock);
-
}
-
-
static int __wakeup(thrd_handle h)
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
__lockx(pthrdpool->cslock);
-
list_for_each(list_p, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
if (h==pthrd_desc->h)
-
{
-
__lockx(pthrd_desc->cslock);
-
if (hnull != pthrd_desc->hevent_go)
-
{
-
SET_EVENT(pthrd_desc->hevent_go);
-
pthrd_desc->ref_cnts++;
-
}
-
__unlockx(pthrd_desc->cslock);
-
__unlockx(pthrdpool->cslock);
-
return 0;
-
}
-
}
-
__unlockx(pthrdpool->cslock);
-
return -1;
-
}
-
-
static int __thrd_add()
-
{
-
thrdpool_t* pthrdpool = thrdpool();
-
thrd_desc_t* pthrd_desc=null;
-
__assert(pthrdpool);
-
-
pthrd_desc=(thrd_desc_t*)malloc(sizeof(thrd_desc_t));
-
__assert(pthrd_desc);
-
-
INIT_THRD_DESC(*pthrd_desc);
-
-
__lockx_init(pthrd_desc->cslock,pthrd_desc->attr);
-
-
# ifdef WIN32
-
pthrd_desc->h = CreateThread(
-
null, // default security attributes
-
0, // use default stack size
-
thread_proc,// thread function
-
pthrd_desc, // argument to thread function
-
0, // use default creation flags
-
0);
-
if(NULL == pthrd_desc->h)
-
goto __err;
-
# else
-
if(pthread_create(&pthrd_desc->h, null, thread_proc, null)!=0)
-
goto __err;
-
# endif
-
-
__lockx(pthrdpool->cslock);
-
list_add(&pthrd_desc->list, &pthrdpool->list);
-
__unlockx(pthrdpool->cslock);
-
return 0;
-
-
__err:
-
__lockx_exit(pthrd_desc->cslock, pthrd_desc->attr);
-
free(pthrd_desc);
-
-
return -1;
-
}
-
-
static int __thrd_del(thrd_handle h)
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
-
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
__lockx(pthrdpool->cslock);
-
list_for_each(list_p, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
if (h==pthrd_desc->h) {
-
-
# ifdef WIN32
-
SET_EVENT(pthrd_desc->hevent_exit);
-
SET_EVENT(pthrd_desc->hevent_go);
-
# else
-
SET_EVENT(pthrd_desc->hevent_go);
-
sleep(1);
-
pthread_cancel(pthrd_desc->h);
-
# endif
-
-
/* wait the thread exit */
-
if (hnull != pthrd_desc->h)
-
{
-
# ifdef WIN32
-
/* terminal the log server thread until 1 second over */
-
unsigned long state = WaitForSingleObject (pthrd_desc->h, 2000);
-
switch (state)
-
{
-
case WAIT_TIMEOUT:
-
{
-
unsigned long exit_code = 0;
-
if (0 != TerminateThread(pthrd_desc->h, exit_code))
-
; /* terminate the server thread */
-
else
-
; /* terminate the LogSrv thread failed */
-
break;
-
}
-
case WAIT_ABANDONED: break; /* the Thread abandoned */
-
case WAIT_OBJECT_0: break; /* exit the server thread */
-
default: break;
-
}
-
CloseHandle(pthrd_desc->h);
-
# else
-
int state = pthread_join(pthrd_desc->h, null);
-
# endif
-
pthrd_desc->h=hnull;
-
}
-
-
__lockx_exit(pthrd_desc->cslock,pthrd_desc->attr);
-
-
# ifdef WIN32
-
EXIT_EVENT(pthrd_desc->hevent_exit);
-
# endif
-
-
EXIT_EVENT(pthrd_desc->hevent_go);
-
-
/* remove itself from the list */
-
list_del(&pthrd_desc->list);
-
/* free the memory from the malloc of the thread descript struct */
-
free(pthrd_desc);
-
-
break;
-
} // if (h==pthrd_desc->h)
-
}
-
__unlockx(pthrdpool->cslock);
-
return 0;
-
}
-
-
static void __display(const thrd_desc_t* pthrd_desc)
-
{
-
__assert(pthrd_desc);
-
printf("handle:%08x, hook: %s\n",
-
pthrd_desc->h, pthrd_desc->thrd_hook ? "installed":"uninstalled");
-
}
-
-
static int __query()
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
__lockx(pthrdpool->cslock);
-
list_for_each(list_p, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
__display(pthrd_desc);
-
}
-
printf("------------------------------\n");
-
__unlockx(pthrdpool->cslock);
-
return 0;
-
}
-
-
static int __reg_notifier(struct notifierx_block *pnb)
-
{
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool&&pnb);
-
return notifierx_chain_register(&pthrdpool->thrdpool_chain, pnb);
-
}
-
-
static int __unreg_notifier(struct notifierx_block *pnb)
-
{
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pnb);
-
return notifierx_chain_unregister(&pthrdpool->thrdpool_chain, pnb);
-
}
-
-
thrdpool_t* thrdpool()
-
{
-
static thrdpool_t s_thrdpool;
-
return &s_thrdpool;
-
}
-
-
int thrdpool_init(int nthrds, int mod)
-
{
-
thrdpool_t* pthrdpool = thrdpool();
-
int ret=0, count=0;
-
__assert(pthrdpool);
-
-
INIT_NOTIFIERX_HEAD(pthrdpool->thrdpool_chain);
-
__lockx_init(pthrdpool->cslock,pthrdpool->attr);
-
-
pthrdpool->mod=mod;
-
-
pthrdpool->list.next=&pthrdpool->list;
-
pthrdpool->list.prev=&pthrdpool->list;
-
-
pthrdpool->ops.thrd_alloc =__thrd_alloc;
-
pthrdpool->ops.thrd_free =__thrd_free;
-
pthrdpool->ops.wakeup =__wakeup;
-
pthrdpool->ops.thrd_add =__thrd_add;
-
pthrdpool->ops.thrd_del =__thrd_del;
-
pthrdpool->ops.query =__query;
-
pthrdpool->ops.reg_notifier = __reg_notifier;
-
pthrdpool->ops.unreg_notifier = __unreg_notifier;
-
pthrdpool->ops.has_free_thrds = __has_free_thrds;
-
-
while (count<nthrds) {
-
ret=__thrd_add();
-
__assert(-1!=ret);
-
count++;
-
}
-
return 0;
-
}
-
-
int thrdpool_exit()
-
{
-
struct list_head *list_p;
-
thrd_desc_t* pthrd_desc=null;
-
thrd_desc_t* pthrd_temp=null;
-
thrdpool_t* pthrdpool = thrdpool();
-
__assert(pthrdpool);
-
-
list_for_each_safe(list_p, pthrd_temp, &(pthrdpool->list))
-
{
-
pthrd_desc = list_entry(list_p, thrd_desc_t, list);
-
if (hnull!=pthrd_desc->h)
-
__thrd_del(pthrd_desc->h);
-
}
-
__lockx_exit(pthrdpool->cslock,pthrdpool->attr);
-
EXIT_NOTIFIERX_HEAD(pthrdpool->thrdpool_chain);
-
-
return 0;
-
}
- /**
-
* file: threadpool.h
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* @2011-11-06: initial
-
* @2011-11-13: add the notifier to register
-
*/
-
-
#ifndef _THREADPOOL_H_
-
#define _THREADPOOL_H_
-
-
#include "list.h"
-
#include "notifierx.h"
-
#include "platform.h"
-
-
-
typedef void (*thrd_hook_t)(void *pdata);
-
-
#define stat_busy 1
-
#define stat_free 2
-
-
typedef struct thrd_msg_s{
-
thrd_handle h;
-
int stat;
-
void* v;
-
}thrd_msg_t;
-
-
#define INIT_THRD_MSG(st,hdl) \
-
{\
-
(st).h=(hdl); \
-
(st).stat=stat_free;\
-
}
-
#define SET_THRD_STAT(st,s) \
-
{\
-
(st).stat=(s);\
-
}
-
#define ST_SIZE_AND_VAL(st) sizeof(st),&(st)
-
-
#define call_chain(chain,st,s) \
-
{ \
-
SET_THRD_STAT((st), (s)); \
-
notifierx_call_chain(&(chain), ST_SIZE_AND_VAL(st)); \
-
}
-
-
#define reg_thread_notifierx(tp,fn) { \
-
static struct notifierx_block fn##_nb; \
-
(fn##_nb).notifierx_call=(fn); \
-
notifierx_chain_register(&(tp).thrdpool_chain, &(fn##_nb)); \
-
}
-
-
typedef struct thrd_desc_s{
-
thrd_handle h;
-
thrd_hook_t thrd_hook;
-
void *pthrd_data;
-
event_t hevent_go;
-
event_t hevent_exit;
-
struct list_head list;
-
unsigned int ref_cnts;
-
lock_t cslock;
-
attr_t attr;
-
}thrd_desc_t;
-
-
-
#ifdef WIN32
-
#define INIT_EVENT(h) { h=CreateEvent(NULL, TRUE, FALSE, NULL); }
-
#define EXIT_EVENT(h) { if (hnull != (h)) CloseHandle(h); }
-
#define SET_EVENT(h) { if (hnull != (h)) SetEvent(h); }
-
#define RESET_EVENT(h) {if (hnull != (h)) ResetEvent(h); }
-
#else
-
#define INIT_EVENT(h) { pthread_cond_init(&(h), null); }
-
#define EXIT_EVENT(h) { pthread_cond_destroy(&(h); }
-
#define SET_EVENT(h) { pthread_cond_signal(&(h)); }
-
#endif
-
-
#define INIT_THRD_DESC(td) \
-
{ \
-
(td).h = 0; \
-
(td).thrd_hook = (thrd_hook_t)0; \
-
(td).pthrd_data = 0; \
-
INIT_EVENT((td).hevent_go); \
-
INIT_EVENT((td).hevent_exit); \
-
(td).list.prev=&(td).list; \
-
(td).list.next=&(td).list; \
-
(td).ref_cnts=0; \
-
}
-
-
#define CLEAN_THRD_HOOK(td) \
-
{ \
-
(td).thrd_hook = (thrd_hook_t)0; \
-
}
-
-
#define CLEAR_THRD_DESC(td) \
-
{ \
-
(td).thrd_hook = (thrd_hook_t)0; \
-
(td).pthrd_data = 0; \
-
}
-
-
#define SET_HANDLER_THRD_DESC(td,h,p) \
-
{ \
-
(td).thrd_hook = h; \
-
(td).pthrd_data = p; \
-
}
-
-
#define mod_tp_normal 0 /*mod==0: hook need NOT auto reset; */
-
#define mod_tp_reset 1 /*mod==1: hook need to reset when next invoked */
-
-
typedef struct thrdpool_ops{
-
thrd_handle (*thrd_alloc)(thrd_hook_t thrd_hook, void* pdata);
-
void (*thrd_free)(thrd_handle h);
-
-
int (*wakeup)(thrd_handle h);
-
-
int (*thrd_add)();
-
int (*thrd_del)(thrd_handle h);
-
-
int (*query)();
-
-
int (*has_free_thrds)();
-
-
int (*reg_notifier)(struct notifierx_block *pnb);
-
int (*unreg_notifier)(struct notifierx_block *pnb);
-
}thrdpool_ops_t;
-
-
typedef struct thrdpool_s{
-
struct thrdpool_ops ops;
-
struct list_head list;
-
struct notifierx_head thrdpool_chain;
-
lock_t cslock;
-
attr_t attr;
-
int mod; /*mod==0: hook need NOT auto reset;
-
mod==1: hook need to reset when next invoked */
-
}thrdpool_t;
-
-
extern thrdpool_t* thrdpool();
-
-
extern int thrdpool_init(int nthrds, int mod);
-
extern int thrdpool_exit();
-
-
-
-
-
#endif
- /**
-
* file: workqueuex.c
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* @2011-11-15: initial
-
*/
-
-
#include "workqueuex.h"
-
#include "threadpool.h"
-
-
static struct workqueue_s *keventd_wq;
-
-
tasks_sched_t *get_tasks_sched()
-
{
-
static tasks_sched_t s_tasks_sched;
-
return &s_tasks_sched;
-
}
-
-
static struct workqueue_s* __create_wq(const char *name)
-
{
-
struct workqueue_s *pnew_wq;
-
tasks_sched_t *pts = get_tasks_sched();
-
__assert(pts);
-
-
pnew_wq=malloc(sizeof(*pnew_wq));
-
__assert(pnew_wq);
-
-
INIT_WORKQUEUE(*pnew_wq,name,*pts);
-
-
return pnew_wq;
-
}
-
-
static void __destroy_wq(struct workqueue_s *pwq)
-
{
-
if (pwq) {
-
list_del(&pwq->list);
-
__lockx_exit(pwq->cslock, pwq->attr);
-
free(pwq);
-
}
-
}
-
-
static int __work_empty()
-
{
-
struct list_head *wqlist_p;
-
struct workqueue_s *pwq_it;
-
// struct work_s *pwork_it;
-
-
tasks_sched_t *pts=get_tasks_sched();
-
__assert(pts);
-
-
list_for_each(wqlist_p, &(pts->wq_head))
-
{
-
pwq_it = list_entry(wqlist_p, workqueue_t, list);
-
__lockx(pwq_it->cslock);
-
if(!list_empty(&pwq_it->head)){
-
__unlockx(pwq_it->cslock);
-
return 0;
-
}
-
__unlockx(pwq_it->cslock);
-
}
-
return 1;
-
}
-
-
static struct work_s* __get_work()
-
{
-
struct list_head *wqlist_p, *worklist_p;
-
struct workqueue_s *pwq_it;
-
struct work_s *pwork_it;
-
-
tasks_sched_t *pts=get_tasks_sched();
-
__assert(pts);
-
-
list_for_each(wqlist_p, &(pts->wq_head))
-
{
-
pwq_it = list_entry(wqlist_p, workqueue_t, list);
-
__lockx(pwq_it->cslock);
-
-
list_for_each(worklist_p, &(pwq_it->head))
-
{
-
pwork_it = list_entry(worklist_p, work_t, list);
-
/* printf("[self:%08x,prev:%08x,next:%08x]\n",
-
pwork_it, pwork_it->list.prev, pwork_it->list.next); */
-
list_del(&pwork_it->list);
-
__unlockx(pwq_it->cslock);
-
return pwork_it;
-
}
-
__unlockx(pwq_it->cslock);
-
}
-
return null;
-
}
-
-
static void __run(void)
-
{
-
thrd_handle h=0;
-
thrdpool_t *ptp=thrdpool();
-
__assert(ptp);
-
-
if (ptp->ops.has_free_thrds()&&!__work_empty())
-
{
-
struct work_s* pnew_work=__get_work();
-
if(pnew_work) {
-
h=ptp->ops.thrd_alloc(pnew_work->fwork, pnew_work);
-
if (-1!=h) ptp->ops.wakeup(h);
-
}
-
}
-
}
-
-
int queue_work(struct workqueue_s *pwq, struct work_s *pwork)
-
{
-
__assert(pwq&&pwork);
-
-
__lockx(pwq->cslock);
-
-
list_add(&pwork->list, &pwq->head);
-
-
__unlockx(pwq->cslock);
-
return 0;
-
}
-
-
int schedule_work(struct work_s *pwork)
-
{
-
__assert(pwork);
-
queue_work(keventd_wq, pwork);
-
__run();
-
return 0;
-
}
-
-
-
static int __workqueue_thrd_callback(struct notifierx_block *pnb,
-
unsigned long nlen, const void *pdata)
-
{
-
thrd_msg_t *pmsg=(thrd_msg_t*)pdata;
-
__assert(pnb);
-
-
if (!pmsg) return 0;
-
switch(pmsg->stat) {
-
case stat_busy:
-
break;
-
case stat_free:
-
if(!__work_empty())
-
__run();
-
break;
-
default:
-
break;
-
}
-
return 0;
-
}
-
-
-
void init_tasks_sched(void)
-
{
-
tasks_sched_t *pts=get_tasks_sched();
-
thrdpool_t *ptp=thrdpool();
-
-
thrdpool_init(threads_number,mod_tp_reset);
-
-
__assert(pts&&ptp);
-
pts->pthrd_pool = ptp;
-
INIT_LIST_HEAD(&pts->wq_head);
-
pts->run == __run;
-
-
reg_thread_notifierx(*ptp,__workqueue_thrd_callback);
-
keventd_wq = __create_wq("events");
-
-
}
-
-
void exit_tasks_sched(void)
-
{
-
struct list_head *wqlist_p;
-
struct workqueue_s *pwq_it, *pwq_temp;
-
-
tasks_sched_t *pts = get_tasks_sched();
-
__assert(pts);
-
-
list_for_each_safe(wqlist_p, pwq_temp, &(pts->wq_head))
-
{
-
pwq_it = list_entry(wqlist_p, workqueue_t, list);
-
__destroy_wq(pwq_it);
-
}
-
-
thrdpool_exit();
-
}
- /**
-
* file: workqueuex.h
-
* author: vincent.cws2008@gmail.com
-
* history:
-
* @2011-11-15: initial
-
*/
-
-
#ifndef _WORKQUEUE_H_
-
#define _WORKQUEUE_H_
-
-
#include "workqueuex.h"
-
-
#include "list.h"
-
-
#include "platform.h"
-
-
#define threads_number 1
-
-
extern struct workqueue_s;
-
-
extern struct work_s;
-
typedef void (*fwork_t)(struct work_s *pwork);
-
-
typedef struct tasks_sched{
-
struct thrdpool_s *pthrd_pool;
-
void (*run)(void);
-
struct list_head wq_head;
-
}tasks_sched_t;
-
-
-
typedef struct workqueue_s {
-
struct list_head list; /* list member of the workqueues */
-
struct list_head head; /* head of the sub-list */
-
const char *name;
-
int nthread; /* -1 for any thread, else thread_number=nthread%numbers */
-
lock_t cslock;
-
attr_t attr;
-
}workqueue_t;
-
-
#define INIT_WORKQUEUE(wq,pname,ts) { \
-
(name)=(pname); \
-
__lockx_init((wq).cslock,(wq).attr); \
-
INIT_LIST_HEAD(&(wq).head); \
-
list_add(&(wq).list, &(ts).wq_head); \
-
(wq).nthread = 0; \
-
}
-
-
typedef struct work_s {
-
// void *pdata;
-
fwork_t fwork;
-
struct list_head list;
-
}work_t;
-
-
#define INIT_WORK(w,f) { \
-
(w).fwork=(f); \
-
INIT_LIST_HEAD(&(w).list); \
-
}
-
-
#define DECLARE_WORK(w, f) \
-
struct work_s w = __WORK_INITIALIZER(n, f)
-
-
#define NEW_WORK(pnew,f) {\
-
pnew=(work_t*)malloc(sizeof(work_t)); \
-
__assert(pnew); \
-
INIT_WORK(*pnew, (f)); \
-
}
-
-
#define FREE_WORK(pnew) {if(pnew) free(pnew);}
-
-
-
extern int queue_work(struct workqueue_s *pwq, struct work_s *pwork);
-
extern int schedule_work(struct work_s *pwork);
-
-
extern tasks_sched_t *get_tasks_sched();
-
-
extern void init_tasks_sched(void);
-
extern void exit_tasks_sched(void);
-
-
#endif
附件如下:
workqueue.rar ---- 代码一点一点积累,问题一点一点解决,莫浮躁,切记!
阅读(1978) | 评论(0) | 转发(0) |