Files
刘可亮 3e10f578d3 v1.2.2
2025-10-21 13:59:50 +08:00

715 lines
19 KiB
C

#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/semaphore.h>
#include <linux/msg_queue.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/defs.h>
#include "os.h"
#define IPC_MUTEX_VALID_MAGIC_NUM (0x1A1A1A1A)
#define IPC_SEMA_VALID_MAGIC_NUM (0x2B2B2B1B)
#define IPC_MSGQ_VALID_MAGIC_NUM (0x3C3C3C3C)
#define IPC_TIMER_VALID_MAGIC_NUM (0x4D4D4D4D)
#define IPC_TASK_VALID_MAGIC_NUM (0x5E5E5E5E)
#define IPC_INVALID_MAGIC_NUM (0x4D3C2B1A)
#define osWaitForever (0xffffffffu)
#define hgic_dbg(fmt, ...) PRINTF("%s:%d::"fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define hgic_err(fmt, ...) printf("%s:%d::"fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
typedef void (*task_pfunc)(void *);
extern int os_msgqueue_init(unsigned int *queue_hdl,int elem_num);
extern void *os_msgqueue_recv(unsigned int queue_hdl,int millisec);
extern int os_msgqueue_send(unsigned int queue_hdl,int data,int millisec);
extern void os_msgqueue_del(unsigned int queue_hdl);
extern int os_msgqueue_get_count(unsigned int queue_hdl);
extern int os_mutex_new(unsigned int *mutex_handle);
extern int os_mutex_take(unsigned int mutex_handle);
extern void os_mutex_release(unsigned int mutex_handle);
extern void os_mutex_delete(unsigned int mutex_handle);
extern int os_sem_new(unsigned int *sem_hdl,int val);
extern void os_sem_free(unsigned int sem_hdl);
extern int os_sem_take(unsigned int sem_hdl,unsigned int timeout);
extern void os_sem_release(unsigned int sem_hdl);
extern void os_timer_stop(unsigned int timer);
extern void os_timer_start(unsigned int timer);
extern int os_timer_create(unsigned int *tmr,void *param, timer_func_t func,int ms);
extern int os_timer_change(unsigned int timer,unsigned int ms);
extern void os_timer_free(unsigned int timer);
extern int os_thread_create(unsigned int *taskhdl,task_pfunc func,
char *name,unsigned int param,
unsigned int stack_size,unsigned int task_prio);
extern void os_thread_delete(unsigned int task);
//-------------------Memory---------------------------//
void *osal_zalloc(unsigned long size)
{
void *ptr = MALLOC(size);
if (ptr)
{ MEMSET(ptr, 0, size); }
return ptr;
}
char *osal_strdup(const char *s)
{
unsigned long len;
char *d;
if(s == NULL) return NULL;
len = strlen(s);
d = MALLOC(len + 1);
if (d == NULL) {
return NULL;
}
memcpy(d, s, len);
d[len] = '\0';
return d;
}
void *osal_realloc(void *sptr, unsigned long size)
{
void *ptr = NULL;
if (sptr == NULL)
{ return osal_zalloc(size); }
ptr = MALLOC(size);
if (ptr) {
MEMSET(ptr, 0, size);
MEMCPY(ptr, sptr, size);
FREE(sptr);
}
return ptr;
}
//-------------------Task-----------------------------//
void tasklet_create(struct tasklet_struct *t, tasklet_func_t func,
unsigned long data, int stack_size)
{
char *name = t->name;
unsigned int task_prio = 1;//Normal
int ret = 0;
memset(t, 0, sizeof(struct tasklet_struct));
os_sema_init(&t->sem, 0);
os_sema_init(&t->rcu_sem, 0);
t->name = name;
t->func = func;
t->args = data;
t->enable = 1;
t->stop = 0;
t->running = 0;
t->rculock_id = -1;
ret = os_thread_create(&t->task, tasklet_entry, name, t, stack_size, task_prio);
ASSERT(!ret);
t->magic = IPC_TASK_VALID_MAGIC_NUM;
hgic_dbg("Task %s create success,task_hdl:%p,func:%p\n", name,
t->task, func);
}
void tasklet_destory(struct tasklet_struct *t)
{
int idx = 0;
if (t == NULL) {
hgic_err("Input param error!\n");
return;
}
if (t->magic != IPC_TASK_VALID_MAGIC_NUM) {
hgic_err("Invaild tasklet_struct!\n");
return;
}
hgic_dbg("Destroy task,task handle:%p\n", t->task);
os_task_delete(t->task);
t->magic = IPC_INVALID_MAGIC_NUM;
}
//-------------------Msgqueue-------------------------//
int msg_queue_init(struct msg_queue *msgq, int size)
{
int ret = 0;
if (msgq->vaild != IPC_MSGQ_VALID_MAGIC_NUM) {
ret = os_msgqueue_init(&msgq->q, size);
ASSERT(!ret);
msgq->vaild = IPC_MSGQ_VALID_MAGIC_NUM;
}
return 0;
}
int msg_queue_get(struct msg_queue *msgq, int millisec)
{
int ret = 0;
ASSERT(msgq);
if (msgq->vaild != IPC_MSGQ_VALID_MAGIC_NUM) {
hgic_err("Invaild msgq!ret_addr:%p\n", RETURN_ADDR());
ASSERT(0);
}
return (int)os_msgqueue_recv(msgq->q, millisec);
}
int msg_queue_put(struct msg_queue *msgq, int data, int millisec)
{
int ret = 0;
ASSERT(msgq);
if (msgq->vaild != IPC_MSGQ_VALID_MAGIC_NUM) {
hgic_err("Invaild msgq!ret_addr:%p\n", RETURN_ADDR());
return -1;
}
return os_msgqueue_send(msgq->q, data, millisec);
}
int msg_queue_del(struct msg_queue *msgq)
{
int ret = 0;
if (msgq) {
if (msgq->vaild != IPC_MSGQ_VALID_MAGIC_NUM) {
hgic_err("Invaild msgq!ret_addr:%p\n", RETURN_ADDR());
ASSERT(0);
}
os_msgqueue_del(msgq->q);
msgq->vaild = IPC_INVALID_MAGIC_NUM;
return ret;
}
return 0;
}
int msg_queue_count(struct msg_queue *msgq)
{
if (msgq->vaild != IPC_MSGQ_VALID_MAGIC_NUM) {
hgic_err("Invaild msgq!ret_addr:%p\n", RETURN_ADDR());
ASSERT(0);
}
return os_msgqueue_get_count(msgq->q);
}
//------------------------Mutex----------------------------//
void os_mutex_init(struct mutex *lock)
{
int ret = 0;
ASSERT(lock);
if (lock->vaild != IPC_MUTEX_VALID_MAGIC_NUM) {
ret = os_mutex_new(&lock->mutex);
ASSERT(!ret);
lock->vaild = IPC_MUTEX_VALID_MAGIC_NUM;
} else {
hgic_err("Already inited!ret_addr:%p\n", RETURN_ADDR());
}
}
void os_mutex_lock(struct mutex *lock)
{
int ret = 0;
ASSERT(lock);
if (lock->vaild != IPC_MUTEX_VALID_MAGIC_NUM) {
hgic_err("Invaild mutex!ret_addr:%p,vaild:0x%x\n", RETURN_ADDR(),lock->vaild);
while(1);
}
ret = os_mutex_take(lock->mutex);
if (ret == 0) {
lock->locked ++;
} else {
hgic_err("mutex lock failed,ret_addr:%p\n",RETURN_ADDR());
}
}
/*Returns 1 if the mutex has been acquired successfully*/
int os_mutex_trylock(struct mutex *lock)
{
int ret = 0;
ASSERT(lock);
if (lock->vaild != IPC_MUTEX_VALID_MAGIC_NUM) {
hgic_err("Invaild mutex!ret_addr:%p\n", RETURN_ADDR());
ASSERT(0);
}
if (lock->locked) {
return 0;
} else {
ret = os_mutex_take(lock->mutex);
if (ret == 0) {
lock->locked ++;
return 1;
} else {
return 0;
}
}
}
void os_mutex_unlock(struct mutex *lock)
{
ASSERT(lock);
if (lock->vaild != IPC_MUTEX_VALID_MAGIC_NUM) {
hgic_err("Invaild mutex!ret_addr:%p,%x\n", RETURN_ADDR(),lock->vaild);
while(1);
}
lock->locked --;
os_mutex_release(lock->mutex);
}
void os_mutex_destroy(struct mutex *lock)
{
ASSERT(lock);
if (lock->vaild != IPC_MUTEX_VALID_MAGIC_NUM) {
hgic_err("Invaild mutex!ret_addr:%p\n", RETURN_ADDR());
ASSERT(0);
}
os_mutex_delete(lock->mutex);
lock->vaild = IPC_INVALID_MAGIC_NUM;
}
//------------------------Semaphore------------------------//
void os_sema_init(struct semaphore *sem, int val)
{
int ret = 0;
ASSERT(sem);
if(sem->vaild != IPC_SEMA_VALID_MAGIC_NUM) {
ret = os_sem_new(&sem->sem, val);
if(ret) {
hgic_err("Error:%d\n",ret);
return;
}
sem->vaild = IPC_SEMA_VALID_MAGIC_NUM;
}
}
void os_sema_destroy(struct semaphore *sem)
{
ASSERT(sem);
if(sem->vaild != IPC_SEMA_VALID_MAGIC_NUM) {
hgic_err("Invaild sem!ret_addr:%p\n",RETURN_ADDR());
ASSERT(0);
}
os_sem_free(sem->sem);
sem->vaild = IPC_INVALID_MAGIC_NUM;
}
int os_sema_down(struct semaphore *sem)
{
int ret = 0;
ASSERT(sem);
if(sem->vaild != IPC_SEMA_VALID_MAGIC_NUM) {
hgic_err("Invaild sem!ret_addr:%p\n",RETURN_ADDR());
ASSERT(0);
}
ret = os_sem_take(sem->sem, osWaitForever);
return ret;
}
/*If the semaphore is successfully acquired, returns 0.*/
int os_down_interruptible(struct semaphore *sem)
{
return os_sema_down(sem);
}
/*If the semaphore is successfully acquired, returns 0.*/
int os_down_killable(struct semaphore *sem)
{
return os_sema_down(sem);
}
/*If the semaphore is successfully acquired, returns 0.*/
int os_down_timeout(struct semaphore *sem, long millisec)
{
ASSERT(sem);
if(sem->vaild != IPC_SEMA_VALID_MAGIC_NUM) {
hgic_err("Invaild sem!ret_addr:%p\n",RETURN_ADDR());
ASSERT(0);
}
return os_sem_take(sem->sem, millisec);
}
void os_sema_up(struct semaphore *sem)
{
ASSERT(sem);
if(sem->vaild != IPC_SEMA_VALID_MAGIC_NUM) {
hgic_err("Invaild sem!ret_addr:%p\n",RETURN_ADDR());
ASSERT(0);
}
os_sem_release(sem->sem);
}
//------------------------Timer Management----------------------------//
#define PRE_ALLOC_TIMER_NUM 32
#define HGIC_TIMER_MAGIC (0x6F6F6F6F)
#define TIMER_TASK_STACK_SIZE 4096
struct hgic_timer_mgmt {
struct mutex timer_mgmt_lock;
struct hgic_timer timer_array[PRE_ALLOC_TIMER_NUM];
struct msg_queue timer_queue;
int timer_task_hdl;
};
static struct hgic_timer_mgmt g_timer_mgmt;
static void timer_cb(void *args);
static int hgic_timer_vaild(struct hgic_timer *tmr)
{
if (!tmr) {
hgic_err("Invaild timer!\n");
return -1;
}
if (tmr->tmr_magic != HGIC_TIMER_MAGIC) {
hgic_err("Invaild timer magic:0x%x\n", tmr->tmr_magic);
return -2;
}
if (tmr->used == 0) {
hgic_err("Unused timer!\n");
return -4;
}
if (tmr->timer_priv == NULL) {
hgic_err("Invaild timer priv data!\n");
return -5;
}
if (tmr->timer_priv->enable == 0) {
hgic_err("Timer %p disable!\n",tmr->timer_priv);
return -6;
}
return 0;
}
void hgic_timer_disable(struct timer_list *timer)
{
if(timer == NULL || timer->tmr == NULL) {
hgic_err("Input param error!\n");
}
os_timer_stop(timer->tmr->timer);
timer->enable = 0;
}
void hgic_timer_enable(struct timer_list *timer)
{
if(timer == NULL || timer->tmr == NULL) {
hgic_err("Input param error!\n");
}
os_timer_start(timer->tmr->timer);
timer->enable = 1;
}
static void hgic_timer_cb(void *arg)
{
struct hgic_timer *tmr = (struct hgic_timer *)arg;
struct hgic_timer_mgmt *timer_mgmt = NULL;
int ret = 0;
ASSERT(tmr);
ASSERT(tmr->tmr_magic == HGIC_TIMER_MAGIC);
//os_mutex_lock(&tmr->tmr_lock);
//ASSERT(tmr->timer_priv);
if(!tmr->timer_priv) {
hgic_err("invaild tmr:%p,timer_priv:%p\n",tmr,tmr->timer_priv);
//os_mutex_unlock(&tmr->tmr_lock);
return;
}
ASSERT(tmr->timer_mgr);
if(!tmr->used) {
hgic_err("Unused timer,function:%p\n",tmr->timer_priv->function);
//os_mutex_unlock(&tmr->tmr_lock);
return;
}
timer_mgmt = (struct hgic_timer_mgmt *)tmr->timer_mgr;
ret = msg_queue_put(&timer_mgmt->timer_queue, (int)tmr, 0);
if(ret) {
hgic_err("Timer msgqueue send failed,ret:%d\n",ret);
}
//os_mutex_unlock(&tmr->tmr_lock);
}
static void timer_cb(void *args)
{
struct timer_list *timer = (struct timer_list *)args;
ASSERT(timer);
ASSERT(timer->tmr);
if (timer->vaild == IPC_TIMER_VALID_MAGIC_NUM) {
timer->pending = 1;
timer->function((timer->data != 0xFFFFFFFF ? timer->data : (unsigned long)timer));
timer->pending = 0;
} else {
hgic_err("Invaild timer!\n");
ASSERT(0);
}
}
static void hgic_timer_task(void *arg)
{
struct hgic_timer_mgmt *timer_mgmt = (struct hgic_timer_mgmt *)arg;
struct hgic_timer *tmr = NULL;
int ret = 0;
while (1) {
tmr = NULL;
tmr = (struct hgic_timer *)msg_queue_get(&timer_mgmt->timer_queue, osWaitForever);
//os_mutex_lock(&tmr->tmr_lock);
ret = hgic_timer_vaild(tmr);
if (ret) {
hgic_err("Invaild timer,ret:%d\n", ret);
//os_mutex_unlock(&tmr->tmr_lock);
continue;
}
timer_cb(tmr->timer_priv);
//os_mutex_unlock(&tmr->tmr_lock);
}
}
int os_timer_mgr_init()
{
struct hgic_timer_mgmt *timer_mgmt = &g_timer_mgmt;
struct hgic_timer *tmr = NULL;
int i = 0;
int ret = 0;
unsigned int task_prio = 0;//HIGH
memset(timer_mgmt, 0, sizeof(struct hgic_timer_mgmt));
os_mutex_init(&timer_mgmt->timer_mgmt_lock);
ret = msg_queue_init(&timer_mgmt->timer_queue, 32);
ASSERT(!ret);
for (i = 0; i < PRE_ALLOC_TIMER_NUM; i++) {
tmr = &timer_mgmt->timer_array[i];
memset(tmr, 0, sizeof(struct hgic_timer));
tmr->index = i;
os_mutex_init(&tmr->tmr_lock);
ret = os_timer_create(&tmr->timer,tmr,hgic_timer_cb,300);
ASSERT(!ret);
tmr->tmr_magic = HGIC_TIMER_MAGIC;
tmr->timer_mgr = timer_mgmt;
}
ret = os_thread_create(&timer_mgmt->timer_task_hdl,
hgic_timer_task, "hgtmr_task", timer_mgmt, TIMER_TASK_STACK_SIZE, task_prio);
ASSERT(!ret);
return 0;
}
static struct hgic_timer *hgic_get_free_timer(void)
{
struct hgic_timer *tmr = NULL;
struct hgic_timer_mgmt *timer_mgmt = &g_timer_mgmt;
int i = 0;
int find = 0;
unsigned int intr = 0;
os_mutex_lock(&timer_mgmt->timer_mgmt_lock);
for (i = 0; i < PRE_ALLOC_TIMER_NUM; i++) {
tmr = &timer_mgmt->timer_array[i];
if (tmr->used == 0) {
find = 1;
break;
}
}
if (find == 0) {
os_mutex_unlock(&timer_mgmt->timer_mgmt_lock);
hgic_err("no free timer!\n");
for (i = 0; i < PRE_ALLOC_TIMER_NUM; i++) {
tmr = &timer_mgmt->timer_array[i];
hgic_err("timer index:%d,callback:%p,magic:0x%x\n",
i,tmr->timer_priv->function,tmr->timer_priv->vaild);
}
return NULL;
} else {
tmr->used = 1;
os_mutex_unlock(&timer_mgmt->timer_mgmt_lock);
return tmr;
}
}
static void hgic_timer_del(struct hgic_timer *tmr)
{
unsigned int intr = 0;
struct hgic_timer_mgmt *timer_mgmt = NULL;
ASSERT(tmr->tmr_magic == HGIC_TIMER_MAGIC);
ASSERT(tmr->timer_mgr);
timer_mgmt = (struct hgic_timer_mgmt *)tmr->timer_mgr;
os_mutex_lock(&timer_mgmt->timer_mgmt_lock);
tmr->timer_priv = NULL;
tmr->used = 0;
os_mutex_unlock(&timer_mgmt->timer_mgmt_lock);
}
//-------------------------Timer---------------------//
int os_init_timer(struct timer_list *timer)
{
ASSERT(timer);
if (timer->vaild != IPC_TIMER_VALID_MAGIC_NUM) {
timer->pending = 0;
timer->tmr = hgic_get_free_timer();
if (timer->tmr == NULL) {
hgic_err("Failed!\n");
return -1;
}
ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
os_mutex_lock(&timer->tmr->tmr_lock);
hgic_timer_disable(timer);
timer->tmr->timer_priv = timer;
timer->vaild = IPC_TIMER_VALID_MAGIC_NUM;
os_mutex_unlock(&timer->tmr->tmr_lock);
return 0;
} else {
return 0;
}
}
int os_setup_timer(struct timer_list *timer, void (*func)(unsigned long data), unsigned long data)
{
int ret = 0;
ret = os_init_timer(timer); //must auto create
if (ret) {
hgic_err("Failed!\n");
return ret;
}
ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
os_mutex_lock(&timer->tmr->tmr_lock);
timer->function = func;
timer->data = data;
os_mutex_unlock(&timer->tmr->tmr_lock);
return 0;
}
int os_timer_setup(struct timer_list *timer, void (*func)(struct timer_list *timer), unsigned int flags)
{
int ret = 0;
ret = os_init_timer(timer); //must auto create
if (ret) {
hgic_err("Failed!\n");
return ret;
}
ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
os_mutex_lock(&timer->tmr->tmr_lock);
timer->function = (timer_func_t)func;
timer->data = 0xFFFFFFFF;
os_mutex_unlock(&timer->tmr->tmr_lock);
return 0;
}
int os_add_timer(struct timer_list *timer)
{
int ret = 0;
int ms = 0;
ret = os_init_timer(timer); //must auto create
if (ret) {
hgic_dbg("Failed!\n");
return ret;
}
ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
ms = jiffies_to_msecs(timer->expires - jiffies);
os_mutex_lock(&timer->tmr->tmr_lock);
hgic_timer_disable(timer);
os_timer_change(timer->tmr->timer, ms < 10 ? 10 : ms);
hgic_timer_enable(timer);
os_mutex_unlock(&timer->tmr->tmr_lock);
return 0;
}
int os_mod_timer(struct timer_list *timer, unsigned long expires)
{
//ASSERT(timer);
//ASSERT(timer->tmr);
//ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
//os_mutex_lock(&timer->tmr->tmr_lock);
timer->expires = expires;
//os_mutex_unlock(&timer->tmr->tmr_lock);
return os_add_timer(timer);
}
int os_stop_timer(struct timer_list *timer)
{
int ret = 0;
ASSERT(timer);
if (timer->vaild != IPC_TIMER_VALID_MAGIC_NUM) {
hgic_err("Invaild timer!ret_addr:%p\n", RETURN_ADDR());
ASSERT(0);
}
ASSERT(timer->tmr);
ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
os_mutex_lock(&timer->tmr->tmr_lock);
hgic_timer_disable(timer);
os_mutex_unlock(&timer->tmr->tmr_lock);
return ret;
}
int os_del_timer(struct timer_list *timer)
{
struct mutex *timer_lock = NULL;
ASSERT(timer);
if (timer->vaild != IPC_TIMER_VALID_MAGIC_NUM) {
//hgic_err("Invaild timer!ret_addr:%p,magic:%x\n", RETURN_ADDR(), timer->vaild);
return 0;
}
ASSERT(timer->tmr);
ASSERT(timer->tmr->tmr_magic == HGIC_TIMER_MAGIC);
timer_lock = &timer->tmr->tmr_lock;
os_mutex_lock(timer_lock);
hgic_timer_disable(timer);
hgic_timer_del(timer->tmr);
timer->tmr = NULL;
timer->vaild = IPC_INVALID_MAGIC_NUM;
os_mutex_unlock(timer_lock);
return 0;
}
int os_del_timer_sync(struct timer_list *timer)
{
struct mutex *timer_lock = NULL;
ASSERT(timer);
if (timer->vaild != IPC_TIMER_VALID_MAGIC_NUM) {
//hgic_err("Invaild timer!ret_addr:%p,magic:%x\n", RETURN_ADDR(), timer->vaild);
return 0;
}
ASSERT(timer->tmr);
while (timer->pending == 1) {
hgic_dbg("Wait for timer handle done...\n");
sleep_ms(1000);
}
timer_lock = &timer->tmr->tmr_lock;
os_mutex_lock(timer_lock);
hgic_timer_disable(timer);
hgic_timer_del(timer->tmr);
timer->tmr = NULL;
timer->vaild = IPC_INVALID_MAGIC_NUM;
os_mutex_unlock(timer_lock);
return 0;
}
void os_timer_mgr_delete()
{
struct hgic_timer *tmr = NULL;
struct hgic_timer_mgmt *timer_mgmt = &g_timer_mgmt;
int i = 0;
os_mutex_lock(&timer_mgmt->timer_mgmt_lock);
for (i = 0; i < PRE_ALLOC_TIMER_NUM; i++) {
tmr = &timer_mgmt->timer_array[i];
hgic_timer_disable(tmr->timer_priv);
os_timer_free(tmr->timer);
os_mutex_destroy(&tmr->tmr_lock);
tmr->index = 0;
tmr->timer_priv = NULL;
tmr->used = 0;
tmr->tmr_magic = IPC_INVALID_MAGIC_NUM;
}
os_task_delete(timer_mgmt->timer_task_hdl);
msg_queue_del(&timer_mgmt->timer_queue);
os_mutex_unlock(&timer_mgmt->timer_mgmt_lock);
os_mutex_destroy(&timer_mgmt->timer_mgmt_lock);
memset(timer_mgmt, 0, sizeof(struct hgic_timer_mgmt));
}