blob: 70442d7703d7d11b3c392d72280235600f356572 [file] [log] [blame]
/*******************************************************************/
/************************* File Description ************************/
/*******************************************************************/
/* File Name: $Workfile: hmx_uprade_system.c $
* Version: $Revision: 1.0 $
* Original Author: Yang Hyun Uk $
* Current Author: $Author: huyang@humaxdigital.com $
* Date: $Date: 2011.09.30
* File Description: Humax Upgrade APIs
* Module:
* Remarks:
*/
/**
* @defgroup UPGRADE_SYSTEM System APIs for Upgrade Module
* @ingroup UPGRADE
*/
/**
* @author Hyunuk Yang(huyang@humaxdigital.com)
* @date 30 Sept 2011
*/
/**
* @note
* Copyright (C) 2011 Humax Corporation. All Rights Reserved. <br>
* This software is the confidential and proprietary information
* of Humax Corporation. You may not use or distribute this software
* except in compliance with the terms and conditions of any applicable license
* agreement in writing between Humax Corporation and you.
*/
/*@{*/
/**
* @file hmx_upgrade_system.c
*/
/*******************************************************************/
/**************************** Header Files *************************/
/*******************************************************************/
/* Start Including Header Files */
#include "hmx_upgrade_system.h"
/* End Including Headers */
/*******************************************************************/
/****************************** define *****************************/
/*******************************************************************/
#ifdef TASK_DEBUG
#define PrintDebug(fmt, ...) printf (fmt, ## __VA_ARGS__)
#define PrintError(fmt, ...) printf (fmt, ## __VA_ARGS__)
#define PrintEnter(...) printf("(+)%s\n", __FUNCTION__)
#define PrintExit(...) printf("(-)%s\n", __FUNCTION__)
#else
#define PrintDebug(fmt, ...) while (0) ((int (*)(char *, ...)) 0)
#define PrintError(fmt, ...) printf (fmt, ## __VA_ARGS__)
#define PrintEnter(...) while (0) ((int (*)(char *, ...)) 0)
#define PrintExit(...) while (0) ((int (*)(char *, ...)) 0)
#endif
#define list_size(list) ((list)->curr_msg_count_)
#define list_bitmap_size(list, i) ((list)->bitmap_count[(i)])
#define list_head(list, i) ((list)->head[i])
#define list_tail(list, i) ((list)->tail[i])
#define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)
#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)
#define list_data(element) ((element)->data)
#define list_next(element) ((element)->next)
#define HAPPY(a) (void)(a)
/* End #define */
/*******************************************************************/
/****************************** typedef ****************************/
/*******************************************************************/
/* Start typedef */
/* End typedef */
/*******************************************************************/
/************************ global variables *************************/
/*******************************************************************/
/* Start global variable */
/* End global variable */
/*******************************************************************/
/************************ static variables *************************/
/*******************************************************************/
/* Start static variable */
/* End static variable */
/*******************************************************************/
/************************ static funtions **************************/
/*******************************************************************/
static int P_MSG_Check(struct HMX_MSG_queue *q, unsigned long q_id);
/*
list_find_highest_priority_bitmap
bitmap¿¡¼­ °¡Àå ³ôÀº ¿ì¼±¼øÀ§¸¦ ã´Â´Ù.
*/
unsigned long list_find_highest_priority_bitmap(struct HMX_MSG_queue *list)
{
int i;
for(i=MSG_PRIORITY_MAX-1; i>=0; i--)
{
if(list->bitmap[i] == 1)
return i;
}
return 0;
}
/*
print_list
HMX_MSG_queue ±¸Á¶Ã¼ Àüü¸¦ PrintÇÑ´Ù.
*/
void print_list(const struct HMX_MSG_queue *list)
{
struct HMX_MSG_element *element;
int *data, i, count;
fprintf(stdout, "Msg Queue Current total size is %ld\n", list_size(list));
for(count=0; count<MSG_PRIORITY_MAX; count++)
{
i = 0;
if( list->bitmap[count] != 0)
{
element = list_head(list, count);
while (1)
{
data = list_data(element);
fprintf(stdout, "priority[%d] : qlist[%03d]=%03d\n", count, i, *data);
i++;
if (list_is_tail(element))
break;
else
element = list_next(element);
}
}
}
}
/*
list_set_bitmap
¿ì¼±¼øÀ§¿¡ ÇØ´çÇÏ´Â ºñÆ®¸ÊÀ» set ÇÑ´Ù.
*/
void list_set_bitmap(struct HMX_MSG_queue *list, unsigned long prio)
{
list->bitmap[prio] = 1;
}
/*
list_clear_bitmap
¿ì¼±¼øÀ§¿¡ ÇØ´çÇÏ´Â ºñÆ®¸ÊÀ» clear ÇÑ´Ù.
*/
void list_clear_bitmap(struct HMX_MSG_queue *list, unsigned long prio)
{
list->bitmap[prio] = 0;
}
/*
list_bitmap_count_increase
ÇØ´çÇÏ´Â ¿ì¼±¼øÀ§ÀÇ bitmap Count¸¦ Áõ°¡ ½ÃŲ´Ù.
*/
void list_bitmap_count_increase(struct HMX_MSG_queue *list, unsigned long prio)
{
list->bitmap_count[prio]++;
}
/*
list_bitmap_count_decrease
ÇØ´çÇÏ´Â ¿ì¼±¼øÀ§ÀÇ bitmap Count¸¦ °¨¼Ò ½ÃŲ´Ù.
*/
void list_bitmap_count_decrease(struct HMX_MSG_queue *list, unsigned long prio)
{
list->bitmap_count[prio]--;
}
/*
list_mapping_task_priority_to_msgq
ŽºÅ© ¿ì¼±¼øÀ§¸¦ ±âÁØÀ¸·Î ¸Þ¼¼ÁöÅ¥ ¿ì¼±¼øÀ§¸¦ °áÁ¤ÇÑ´Ù.
*/
int list_find_msg_q_priority_from_task_priority(unsigned long *prio)
{
struct sched_param param;
int policy = 0;
int rc;
rc = pthread_getschedparam( pthread_self(), &policy, &param);
if(rc != HMX_OK)
{
*prio = MSG_PRIORITY0;
return HMX_OK;
}
PrintDebug("policy = %d\n", policy);
PrintDebug("param.sched_priority = %d\n", param.sched_priority);
switch(param.sched_priority)
{
case USER_PRIORITY0:
*prio = MSG_PRIORITY0;
break;
case USER_PRIORITY1:
*prio = MSG_PRIORITY1;
break;
case USER_PRIORITY2:
*prio = MSG_PRIORITY2;
break;
case USER_PRIORITY3:
*prio = MSG_PRIORITY3;
break;
case USER_PRIORITY4:
*prio = MSG_PRIORITY4;
break;
case USER_PRIORITY5:
*prio = MSG_PRIORITY5;
break;
case USER_PRIORITY6:
*prio = MSG_PRIORITY6;
break;
case USER_PRIORITY7:
*prio = MSG_PRIORITY7;
break;
case USER_PRIORITY8:
*prio = MSG_PRIORITY8;
break;
case USER_PRIORITY9:
*prio = MSG_PRIORITY9;
break;
case USER_PRIORITY10:
*prio = MSG_PRIORITY10;
break;
case USER_PRIORITY11:
*prio = MSG_PRIORITY11;
break;
case USER_PRIORITY12:
*prio = MSG_PRIORITY12;
break;
case USER_PRIORITY13:
*prio = MSG_PRIORITY13;
break;
case USER_PRIORITY14:
*prio = MSG_PRIORITY14;
break;
case USER_PRIORITY15:
*prio = MSG_PRIORITY15;
break;
default:
*prio = MSG_PRIORITY15;
break;
}
return HMX_OK;
}
/*
q_insert_temp_tail_element
temp Qeue¿¡ element¸¦ ¿¬°á ÇÑ´Ù.
*/
void q_insert_temp_tail_element(struct HMX_MSG_queue *q, struct HMX_MSG_element *element)
{
if(q->temp_tail == NULL)
{
q->temp_head = element;
element->next = NULL;
element->prev = NULL;
q->temp_tail = element;
}
else
{
q->temp_tail->next = element;
element->next = NULL;
element->prev = q->temp_tail;
q->temp_tail = element;
}
}
/*
q_remove_temp_tail_element
temp Qeue¿¡¼­ ¸¶Áö¸· element¸¦ Á¦°ÅÇÏ¿© ³Ñ°ÜÁØ´Ù.
*/
void q_remove_temp_tail_element(struct HMX_MSG_queue *q, struct HMX_MSG_element **element)
{
PrintEnter();
*element = q->temp_tail;
if(q->temp_head->next == NULL) //element 1°³ ³²Àº °æ¿ì.
{
q->temp_head = NULL;
q->temp_tail = NULL;
}
else
{
q->temp_tail->prev->next = NULL;
q->temp_tail = q->temp_tail->prev;
}
PrintExit();
}
/*
q_destory_temp_tail
temp QeueÀÇ element memory¸¦ ¼Ò¸ê½ÃŲ´Ù.
*/
void q_destory_temp_tail(struct HMX_MSG_queue *q)
{
struct HMX_MSG_element *q_element;
PrintEnter();
do
{
q_element = q->temp_tail;
q->temp_tail = q->temp_tail->prev;
} while(q->temp_tail != NULL);
if (q->pPool)
{
free(q->pPool);
q->pPool = NULL;
}
if (q->pDataPool)
{
free(q->pDataPool);
q->pDataPool = NULL;
}
PrintExit();
}
/*
list_rem_next
element¿¡¼­ data¸¦ »èÁ¦ÇÑ´Ù.
*/
int list_rem_next(struct HMX_MSG_queue *list, void *data, unsigned long size, unsigned char timeoutflag, struct timespec *timeo)
{
struct HMX_MSG_element *old_element;
unsigned long prio;
int rc = 0;
PrintEnter();
list->reader_count_++;
if ((list_size(list) == 0 || list->reader_count_ > 1) && 0 == rc)
{
if(TRUE == timeoutflag)
{
rc = pthread_cond_timedwait(&list->q_not_empty_, &list->q_lock_, timeo);
}
else
{
rc = pthread_cond_wait(&list->q_not_empty_, &list->q_lock_);
}
}
list->reader_count_--;
if(rc != 0)
{
PrintDebug("%s : rc[%d] !!\n", __FUNCTION__, rc);
return rc;
}
prio = list_find_highest_priority_bitmap(list);
PrintDebug("list_find_highest_priority_bitmap : prio = %d\n", prio);
memcpy(data, list->head[prio]->data, size);
old_element = list->head[prio];
if(NULL == list->head[prio]->next)
{
list->head[prio] = NULL;
list->tail[prio] = NULL;
}
else
{
list->head[prio] = list->head[prio]->next;
}
q_insert_temp_tail_element(list, old_element);
list->curr_msg_count_--;
list_bitmap_count_decrease(list, prio);
if(list->bitmap_count[prio] == 0)
list_clear_bitmap(list, prio);
if (list->writer_count_ > 0)
pthread_cond_signal(&list->q_not_full_);
PrintExit();
return rc;
}
static void *thread_func_(void *arg)
{
struct HMX_TASK_arg *p = (struct HMX_TASK_arg *)arg;
int rc = 0;
#if defined(CONFIG_DEBUG)
p->pid = getpid();
p->tid = (long int)syscall(4222);
#endif
pthread_mutex_lock(&p->lock_);
while (p->start == 0 && 0 == rc) //wait signal
rc = pthread_cond_wait(&p->cond_, &p->lock_);
pthread_mutex_unlock(&p->lock_);
#if defined(CONFIG_DEBUG)
p->thread_id = pthread_self();
PrintDebug("[%s] task started...\n", p->name);
#endif
(*p->start_func_)(p->arg_);
return NULL;
}
/*
HMX_TASK_Create
ŽºÅ©¸¦ »ý¼ºÇÑ´Ù.
*/
int HMX_TASK_Create(void (*start_func)(void *), unsigned long prio,unsigned long stack_size, const char *name, void *arg, unsigned long *taskId, int IsJoinable)
{
int rc;
struct HMX_TASK *task;
pthread_attr_t thread_attr;
struct sched_param schParam;
unsigned char *pucDstStackAddr = NULL;
unsigned char *pucTaskStack;
rc = pthread_attr_init (&thread_attr);
if (rc) {
return HMX_ERROR;
}
rc = pthread_attr_setschedpolicy (&thread_attr, HMX_TASK_PTHREAD_DEFAULT_PRIO);
if (rc) {
return HMX_ERROR;
}
pthread_attr_getschedparam(&thread_attr, &schParam);
schParam.sched_priority = prio;
rc = pthread_attr_setschedparam (&thread_attr, &schParam);
if (rc) {
return HMX_ERROR;
}
if (stack_size < HMX_TASK_PTHREAD_STACK_MIN)
stack_size = HMX_TASK_PTHREAD_STACK_MIN;
pucTaskStack = malloc(stack_size+HMX_TASK_STACK_OVERHEAD_SIZE+HMX_TASK_GUARD_SIZE);
if (pucTaskStack == NULL)
return HMX_ERROR;
memset(pucTaskStack, 0xA5, stack_size+HMX_TASK_STACK_OVERHEAD_SIZE+HMX_TASK_GUARD_SIZE );
PrintDebug("%s(%d) : pucTaskStack = %p, stack_size= %d\n", __FUNCTION__, __LINE__, pucTaskStack, stack_size);
rc = pthread_attr_setstack(&thread_attr, (void *)pucTaskStack, stack_size );
if (rc) {
return HMX_ERROR;
}
rc = pthread_attr_getstack(&thread_attr,(void *)&pucDstStackAddr, (size_t *)&stack_size );
if (rc) {
return HMX_ERROR;
}
PrintDebug("%s(%d) : pucDstStackAddr = %p, stack_size= %d\n", __FUNCTION__, __LINE__, pucDstStackAddr, stack_size);
if (IsJoinable == TRUE)
{
rc = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
}
else if(IsJoinable == FALSE)
{
rc = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
}
else
{
PrintError("%s(%s) : IsJoinable Parameter Error!!\n", __func__, __LINE__);
return HMX_ERROR;
}
if (rc) {
PrintError ("%s(%d) : Failed to IsJoinable %s\n", __FUNCTION__, __LINE__, strerror (rc));
return HMX_ERROR;
}
if (task = (struct HMX_TASK *)malloc(sizeof(struct HMX_TASK)), NULL == task) {
*taskId = 0;
free(pucTaskStack);
return HMX_ERROR;
}
task->targ_.start_func_ = start_func;
task->targ_.arg_ = arg;
task->targ_.priority_ = prio;
task->targ_.stackSize_ = stack_size;
task->targ_.IsJoinable = IsJoinable;
task->targ_.pucTaskStack = (unsigned long *)pucTaskStack;
task->targ_.pulStackStartAddress = (unsigned long *)pucDstStackAddr;
pthread_mutex_init(&task->targ_.lock_, NULL);
pthread_cond_init(&task->targ_.cond_, NULL);
task->targ_.start = 0;
strncpy(task->targ_.name, name, sizeof(task->targ_.name)-1);
rc = pthread_create(&task->task_, &thread_attr, thread_func_, &task->targ_);
if (rc) {
free(pucTaskStack);
free(task);
*taskId = 0;
return HMX_ERROR;
}
*taskId = (unsigned long)task;
#if defined(CONFIG_TASK_PRIORITY)
pthread_setschedparam(task->task_, HMX_TASK_PTHREAD_DEFAULT_PRIO, &schParam);
#endif
pthread_attr_destroy(&thread_attr);
PrintDebug("%s(%d) : s_ucTaskCount = %d\n", __func__, __LINE__, s_ucTaskCount);
return HMX_OK;
}
int HMX_TASK_Start(unsigned long taskId)
{
struct HMX_TASK *task = (struct HMX_TASK *)taskId;
PrintEnter();
if(NULL == task)
{
PrintError("%s(%d) : task is NULL!!\n", __func__, __LINE__);
return HMX_ERROR;
}
pthread_mutex_lock(&task->targ_.lock_);
if (task->targ_.start == 0) {
task->targ_.start = 1;
pthread_cond_signal(&task->targ_.cond_);
}
pthread_mutex_unlock(&task->targ_.lock_);
PrintExit();
return HMX_OK;
}
/*
HMX_TASK_Stop
Task¸¦ ¼öÇàµÈ ÀÌÈÄ¿¡ ÀÌ ÇÔ¼ö¸¦ È£ÃâÇصµ STOPÀº µÇÁö ¾Ê´Â´Ù.
´ÜÁö count¸¸ 0À¸·Î ¸¸µç´Ù.
*/
int HMX_TASK_Stop(unsigned long taskId)
{
struct HMX_TASK *task = (struct HMX_TASK *)taskId;
PrintEnter();
if (task == NULL) {
return HMX_OK;
}
pthread_mutex_lock(&task->targ_.lock_);
if (task->targ_.start != 0)
task->targ_.start = 0;
pthread_mutex_unlock(&task->targ_.lock_);
return HMX_OK;
}
/*
sleep
ŽºÅ©¸¦ ÀáÀç¿î´Ù.
*/
int HMX_Sleep(unsigned long ultime)
{
struct timespec delay;
struct timespec rem;
int rc;
if (ultime != 0)
{
HMX_TASK_CheckCallback();
}
delay.tv_sec = ultime / 1000;
delay.tv_nsec = (ultime % 1000) * 1000000;
for (;;) {
rc = nanosleep(&delay, &rem);
if (0 != rc) {
if (EINTR == errno) {
delay = rem;
continue;
}
return HMX_ERROR;
}
break;
}
return HMX_OK;
}
/*
HMX_TASK_Destroy
ŽºÅ©¸¦ ¼Ò¸êÇÑ´Ù.
*/
int HMX_TASK_Destroy(unsigned long taskId)
{
int rc;
struct HMX_TASK *task = (struct HMX_TASK *)taskId;
if( taskId == (unsigned long)NULL )
{
PrintDebug("%s(%d) taskId == NULL\n", __FUNCTION__, __LINE__);
return HMX_ERROR;
}
else
{
pthread_mutex_lock(&task->targ_.lock_);
if (task->targ_.start == 1)
{
task->targ_.start = 0;
}
rc = pthread_cancel(task->task_);
if (rc)
{
PrintError("[HMX_TASK_Destroy] warning : there is no thread in pthread taskId(%08X) pthreadId(%08X)\n", taskId, task->task_);
}
HMX_Sleep(1);
#if defined(CONFIG_THREAD_JOIN_TEMPORARY)
#else
if (task->targ_.IsJoinable)
#endif
pthread_join(task->task_, NULL);
free(task->targ_.pucTaskStack);
pthread_mutex_unlock(&task->targ_.lock_);
}
free(task);
return HMX_OK;
}
/*
HMX_TASK_SetCurrentPriority
»õ·Î¿î ¿ì¼±¼øÀ§¸¦ ¼¼ÆÃÇÑ´Ù.
*/
int HMX_TASK_SetCurrentPriority(unsigned long taskId, unsigned long newpriority)
{
int rc;
int policy;
struct HMX_TASK *task = (struct HMX_TASK *)taskId;
struct sched_param schParam;
if (task == NULL)
{
return HMX_ERROR;
}
rc = pthread_getschedparam(task->task_, &policy, &schParam);
if (schParam.sched_priority == (int)newpriority)
{
return HMX_OK;
}
schParam.sched_priority = newpriority;
pthread_mutex_lock(&task->targ_.lock_);
rc = pthread_setschedparam(task->task_, policy, &schParam);
pthread_mutex_unlock(&task->targ_.lock_);
if (rc) {
return HMX_ERROR;
}
return HMX_OK;
}
/*
list_init
HMX_MSG_queue ±¸Á¶Ã¼¸¦ ÃʱâÈ­ ÇÑ´Ù.
*/
void list_init(struct HMX_MSG_queue *list, unsigned long ulSize, unsigned long ulCount, unsigned char ucSuspendType)
{
int i;
list->curr_msg_count_ = 0;
list->msg_size_ = ulSize;
list->msg_count_ = ulCount;
list->writer_count_ = 0;
list->reader_count_ = 0;
list->suspend_type_ = ucSuspendType;
pthread_mutex_init(&list->q_lock_, NULL);
pthread_cond_init(&list->q_not_empty_, NULL);
pthread_cond_init(&list->q_not_full_, NULL);
list->temp_head = NULL;
list->temp_tail = NULL;
for(i=0; i<MSG_PRIORITY_MAX; i++)
{
list->head[i] = NULL;
list->tail[i] = NULL;
list->bitmap_count[i] = 0;
list->bitmap[i] = 0;
}
#ifdef HMX_MSG_DEBUG
list->sendTick = 0;
list->receiveTick = 0;
list->lastSendTick = 0;
list->lastReceiveTick = 0;
#endif
return;
}
/*
list_destroy
HMX_MSG_queue ±¸Á¶Ã¼¸¦ ¼Ò¸ê½ÃŲ´Ù.
*/
void list_destroy(struct HMX_MSG_queue *list)
{
void *data;
data = (char *)malloc(list->msg_size_);
while (list_size(list) > 0)
{
if ( list_rem_next(list, (void *)data, list->msg_size_, FALSE, FALSE) != 0 )
{
PrintError("%s : list_rem_next Error!!\n", __func__);
}
}
free(data);
return;
}
/*
list_ins_next
element¿¡ data¸¦ Ãß°¡ÇÑ´Ù.
*/
int list_ins_next(struct HMX_MSG_queue *list, unsigned long prio, const void *data, unsigned long size, unsigned char timeoutflag, struct timespec *timeo)
{
struct HMX_MSG_element *new_element;
int rc = 0;
PrintEnter();
list->writer_count_++;
while (list->msg_count_ == list->curr_msg_count_ && 0 == rc)
{
if(TRUE == timeoutflag)
{
rc = pthread_cond_timedwait(&list->q_not_full_, &list->q_lock_, timeo);
}
else
{
rc = pthread_cond_wait(&list->q_not_full_, &list->q_lock_);
}
}
list->writer_count_--;
if(rc != 0)
{
PrintDebug("%s : rc[%d] !!\n", __FUNCTION__, rc);
return rc;
}
q_remove_temp_tail_element(list, &new_element);
memcpy(new_element->data, data, size);
if(list->tail[prio] == NULL)
{
list->head[prio] = new_element;
new_element->next = NULL;
new_element->prev = NULL;
list->tail[prio] = new_element;
}
else
{
list->tail[prio]->next = new_element;
new_element->next = NULL;
new_element->prev = list->tail[prio];
list->tail[prio] = new_element;
}
list->curr_msg_count_++;
list_bitmap_count_increase(list, prio);
list_set_bitmap(list, prio);
if (list->reader_count_ > 0)
pthread_cond_signal(&list->q_not_empty_);
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_Init
¸Þ¼¼Áö Å¥¸¦ ÃʱâÈ­ ÇÑ´Ù.
*/
int HMX_MSG_Init(void)
{
#if defined(HMX_MSG_DEBUG)
TAILQ_INIT(&msg_q_list_head);
#endif
return HMX_OK;
}
/*
HMX_MSG_Create
¸Þ¼¼Áö Å¥¸¦ »ý¼ºÇÑ´Ù.
*/
int HMX_MSG_Create(unsigned long q_count, unsigned long msg_size,
const char *q_name, unsigned long *q_id, HMX_SUSPENDTYPE suspendType)
{
struct HMX_MSG_queue *q;
struct HMX_MSG_element *q_element;
unsigned long i;
struct HMX_MSG_element *q_element_pool;
unsigned char *data_pool;
HAPPY(q_name);
PrintEnter();
if(suspendType >= HMX_SUSPENDTYPE_MAX)
{
PrintError("%s[%d] : ulSuspendType %d Error\n", __FUNCTION__, __LINE__, suspendType);
return HMX_ERROR;
}
if((q = (struct HMX_MSG_queue *)malloc(sizeof(struct HMX_MSG_queue))) == NULL)
{
PrintError("%s[%d] : malloc Error\n", __FUNCTION__, __LINE__);
return HMX_ERROR;
}
memset(q, 0, sizeof(struct HMX_MSG_queue));
list_init(q, msg_size, q_count, suspendType);
q_element_pool = (struct HMX_MSG_element *)malloc(sizeof(struct HMX_MSG_element)*q_count);
data_pool = (unsigned char *)malloc(msg_size*q_count);
for(i=0; i<q_count; i++)
{
q_element = &q_element_pool[i];
q_element->data = &data_pool[i*msg_size];
q_insert_temp_tail_element(q, q_element);
}
q->pDataPool = data_pool;
q->pPool = q_element_pool;
*q_id = (unsigned long)q;
#if defined(HMX_MSG_DEBUG)
TAILQ_INSERT_TAIL(&msg_q_list_head, q, entries);
#endif
#if defined(CONFIG_DEBUG)
if (q_name)
strncpy(q->name, q_name, sizeof(q->name)-1);
else
q->name[0] = 0;
#endif
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_Destroy
¸Þ¼¼ÁöÅ¥¸¦ ¼Ò¸ê½ÃŲ´Ù.
*/
int HMX_MSG_Destroy(unsigned long q_id)
{
struct HMX_MSG_queue *q;
PrintEnter();
q = (struct HMX_MSG_queue *)q_id;
if(q == NULL)
{
return HMX_ERROR;
}
pthread_cond_destroy(&q->q_not_full_);
pthread_cond_destroy(&q->q_not_empty_);
pthread_mutex_destroy(&q->q_lock_);
list_destroy(q);
q_destory_temp_tail(q);
#if defined(HMX_MSG_DEBUG)
TAILQ_REMOVE(&msg_q_list_head, q, entries);
#endif
if(q != NULL)
{
free(q);
}
PrintExit();
return HMX_OK;
}
int HMX_MSG_Clear(unsigned long q_id)
{
struct HMX_MSG_queue *q;
int rc = HMX_OK;
// struct timespec cur_time;
long long exp_nsec;
struct timespec timeo, cur_time;
unsigned long size;
void *pBuf;
PrintEnter();
q = (struct HMX_MSG_queue *)q_id;
size = q->msg_size_;
pBuf = malloc(size);
if (pBuf == NULL)
return HMX_ERROR;
(void)pthread_mutex_lock(&q->q_lock_);
do
{
clock_gettime(CLOCK_REALTIME, &cur_time);
exp_nsec = (long long)cur_time.tv_sec * (long long)1000 * (long long)1000 * (long long)1000 + (long long)cur_time.tv_nsec;
timeo.tv_sec = exp_nsec / (1000 * 1000 * 1000);
timeo.tv_nsec = exp_nsec % (1000 * 1000 * 1000);
rc = list_rem_next(q, pBuf, size, TRUE, &timeo);
if(HMX_OK != rc)
{
if(ETIMEDOUT == rc)
{
(void)pthread_mutex_unlock(&q->q_lock_);
free(pBuf);
return HMX_OK;
}
}
}while (1);
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
free(pBuf);
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_Send
¸Þ¼¼Áö¸¦ º¸³½´Ù.
*/
int HMX_MSG_Send(unsigned long q_id, const void *msg, unsigned long size)
{
struct HMX_MSG_queue *q;
int rc = HMX_OK;
unsigned long prio;
PrintEnter();
q = (struct HMX_MSG_queue *)q_id;
if(size > q->msg_size_)
{
PrintError("%s[%d] : size %ld Error\n", __FUNCTION__, __LINE__, size);
return HMX_ERROR;
}
HMX_TASK_CheckCallback();
rc = P_MSG_Check(q, q_id);
if (HMX_OK != rc)
{
#if defined(CONFIG_DEBUG)
PrintError("%s(%d) : P_MSG_Check : HMX_MSG_FULL!! queue name (%s)\n", __func__, __LINE__, q->name);
#endif
return rc;
}
if(HMX_SUSPENDTYPE_PRIORITY == q->suspend_type_)
{
rc = list_find_msg_q_priority_from_task_priority(&prio);
if(rc != HMX_OK)
{
prio = MSG_PRIORITY0;
}
}
else
{
prio = MSG_PRIORITY0;
}
(void)pthread_mutex_lock(&q->q_lock_);
rc = list_ins_next(q, prio, msg, size, FALSE, NULL);
if(HMX_OK != rc)
{
PrintError("%s : list_ins_next() rc[%d] Error!!\n", __FUNCTION__, rc);
(void)pthread_mutex_unlock(&q->q_lock_);
return rc;
}
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
#ifdef HMX_MSG_DEBUG
q->lastSendTick = VK_TIMER_GetSystemTick();
#endif
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_SendTimeout
¸Þ¼¼Áö¸¦ Timeout³»¿¡ º¸³½´Ù.
*/
int HMX_MSG_SendTimeout(unsigned long q_id, const void *msg, unsigned long size, unsigned long timeout)
{
struct HMX_MSG_queue *q;
int rc = HMX_OK;
unsigned long prio = 0;
struct timespec timeo;
struct timespec cur_time;
long long exp_nsec;
PrintEnter();
if (timeout != 0)
{
// HMX_TASK_CheckCallback();
}
if (timeout == 0xFFFFFFFF)
{
return HMX_MSG_Send(q_id, msg, size);
}
q = (struct HMX_MSG_queue *)q_id;
if(size > q->msg_size_)
{
PrintError("%s[%d] : size %ld Error\n", __FUNCTION__, __LINE__, size);
return HMX_ERROR;
}
rc = P_MSG_Check(q, q_id);
if (HMX_OK != rc)
{
#if defined(CONFIG_DEBUG)
PrintError("%s(%d) : P_MSG_Check : HMX_MSG_FULL!! queue name : %s\n", __func__, __LINE__, q->name);
#endif
return rc;
}
if(HMX_SUSPENDTYPE_PRIORITY == q->suspend_type_)
{
rc = list_find_msg_q_priority_from_task_priority(&prio);
if(rc != HMX_OK)
{
prio = MSG_PRIORITY0;
}
}
else
{
prio = MSG_PRIORITY0;
}
clock_gettime(CLOCK_REALTIME, &cur_time);
exp_nsec = (long long)cur_time.tv_sec * 1000 * 1000 * 1000 + cur_time.tv_nsec;
if (timeout != 0)
exp_nsec += (timeout * 1000 - 999) * 1000;
timeo.tv_sec = exp_nsec / (1000 * 1000 * 1000);
timeo.tv_nsec = exp_nsec % (1000 * 1000 * 1000);
(void)pthread_mutex_lock(&q->q_lock_);
rc = list_ins_next(q, prio, msg, size, TRUE, &timeo);
if(HMX_OK != rc)
{
(void)pthread_mutex_unlock(&q->q_lock_);
if(ETIMEDOUT == rc)
{
PrintDebug("%s : list_ins_next() rc[%d] HMX_TIMEOUT!!\n", __FUNCTION__, rc);
return HMX_TIMEOUT;
}
else
{
PrintError("%s : list_ins_next() rc[%d] Error!!\n", __FUNCTION__, rc);
return HMX_ERROR;
}
}
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_SendUrgent
±ä±Þ ¸Þ¼¼Áö¸¦ º¸³½´Ù.
*/
int HMX_MSG_SendUrgent(unsigned long q_id, const void *msg, unsigned long size)
{
struct HMX_MSG_queue *q;
int rc = HMX_OK;
unsigned long prio;
PrintEnter();
q = (struct HMX_MSG_queue *)q_id;
if(size > q->msg_size_)
{
PrintError("%s[%d] : size %ld Error\n", __FUNCTION__, __LINE__, size);
return HMX_ERROR;
}
rc = P_MSG_Check(q, q_id);
if (HMX_OK != rc)
{
#if defined(CONFIG_DEBUG)
PrintError("%s(%d) : P_MSG_Check : HMX_MSG_FULL!! queue name (%s)\n", __func__, __LINE__, q->name);
#endif
return rc;
}
if(HMX_SUSPENDTYPE_PRIORITY == q->suspend_type_)
{
prio = MSG_PRIORITY_MAX-1; //°¡Àå ³ôÀº ¿ì¼±¼øÀ§·Î º¸³½´Ù.
}
else
{
prio = MSG_PRIORITY0;
}
(void)pthread_mutex_lock(&q->q_lock_);
rc = list_ins_next(q, prio, msg, size, FALSE, FALSE);
if(HMX_OK != rc)
{
PrintError("%s : list_ins_next() rc[%d] Error!!\n", __FUNCTION__, rc);
(void)pthread_mutex_unlock(&q->q_lock_);
return rc;
}
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
#ifdef HMX_MSG_DEBUG
q->lastSendTick = VK_TIMER_GetSystemTick();
#endif
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_SendUrgentTimeout
±ä±Þ ¸Þ¼¼Áö¸¦ Timeout ³»¿¡ º¸³½´Ù.
*/
int HMX_MSG_SendUrgentTimeout(unsigned long q_id, const void *msg, unsigned long size, unsigned long timeout)
{
struct HMX_MSG_queue *q;
int rc = HMX_OK;
unsigned long prio = 0;
struct timespec timeo;
struct timespec cur_time;
long long exp_nsec;
PrintEnter();
if (timeout == 0xFFFFFFFF)
{
return HMX_MSG_SendUrgent(q_id, msg, size);
}
q = (struct HMX_MSG_queue *)q_id;
if(size > q->msg_size_)
{
PrintError("%s[%d] : size %ld Error\n", __FUNCTION__, __LINE__, size);
return HMX_ERROR;
}
rc = P_MSG_Check(q, q_id);
if (HMX_OK != rc)
{
#if defined(CONFIG_DEBUG)
PrintError("%s(%d) : P_MSG_Check : HMX_MSG_FULL!! queue name(%s)\n", __func__, __LINE__, q->name);
#endif
return rc;
}
if(HMX_SUSPENDTYPE_PRIORITY == q->suspend_type_)
{
prio = MSG_PRIORITY_MAX-1; //°¡Àå ³ôÀº ¿ì¼±¼øÀ§·Î º¸³½´Ù.
}
else
{
prio = MSG_PRIORITY0;
}
clock_gettime(CLOCK_REALTIME, &cur_time);
exp_nsec = (long long)cur_time.tv_sec * 1000 * 1000 * 1000 + cur_time.tv_nsec;
if (timeout != 0)
exp_nsec += (timeout * 1000 - 999) * 1000;
timeo.tv_sec = exp_nsec / (1000 * 1000 * 1000);
timeo.tv_nsec = exp_nsec % (1000 * 1000 * 1000);
(void)pthread_mutex_lock(&q->q_lock_);
rc = list_ins_next(q, prio, msg, size, TRUE, &timeo);
if(HMX_OK != rc)
{
(void)pthread_mutex_unlock(&q->q_lock_);
if(ETIMEDOUT == rc)
{
PrintDebug("%s : list_ins_next() rc[%d] HMX_TIMEOUT!!\n", __FUNCTION__, rc);
return HMX_TIMEOUT;
}
else
{
PrintError("%s : list_ins_next() rc[%d] Error!!\n", __FUNCTION__, rc);
return HMX_ERROR;
}
}
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
PrintExit();
return HMX_OK;
}
#if defined(HMX_MSG_DEBUG) && defined(VK_TASK_DEBUG)
#define HMX_MSG_CRITICAL_DELAY_TICK 20
#define HMX_MSG_NORMAL_DELAY_TICK 200
#endif
/*
HMX_MSG_Receive
¸Þ¼¼Áö¸¦ ¹Þ´Â´Ù.
*/
int HMX_MSG_Receive(unsigned long q_id, void *msg, unsigned long size)
{
struct HMX_MSG_queue *q;
// unsigned long prio;
int rc = HMX_OK;
PrintEnter();
HMX_TASK_CheckCallback();
q = (struct HMX_MSG_queue *)q_id;
if(size > q->msg_size_)
{
PrintError("%s : size %ld Error!!\n", __FUNCTION__, size);
return HMX_ERROR;
}
(void)pthread_mutex_lock(&q->q_lock_);
#if defined(HMX_MSG_DEBUG) && defined(VK_TASK_DEBUG)
q->receiveTick = VK_TIMER_GetSystemTick();
if (q->lastReceiveTick != 0 && (q->receiveTick - q->lastReceiveTick > HMX_MSG_NORMAL_DELAY_TICK))
{
if ((q->receiveTick - tickForVkDebug) > HMX_MSG_CRITICAL_DELAY_TICK)
{
PrintError("HMX_MSG_Receive : It has excuted too long time (%d) queue(%s)\n", q->receiveTick - q->lastReceiveTick, q->name);
}
}
#endif
rc = list_rem_next(q, msg, size, FALSE, NULL);
#if defined(HMX_MSG_DEBUG) && defined(VK_TASK_DEBUG)
q->lastReceiveTick = tickForVkDebug = VK_TIMER_GetSystemTick();
#endif
if(HMX_OK != rc)
{
PrintError("%s : list_rem_next() rc[%d] Error!!\n", __FUNCTION__, rc);
(void)pthread_mutex_unlock(&q->q_lock_);
return rc;
}
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
PrintExit();
return HMX_OK;
}
/*
HMX_MSG_ReceiveTimeout
¸Þ¼¼Áö¸¦ Timeout³»¿¡ ¹Þ´Â´Ù.
*/
int HMX_MSG_ReceiveTimeout(unsigned long q_id, void *msg, unsigned long size, unsigned long timeout)
{
struct HMX_MSG_queue *q;
int rc = HMX_OK;
// struct timespec cur_time;
long long exp_nsec;
struct timespec timeo, cur_time;
PrintEnter();
if (timeout != 0)
{
HMX_TASK_CheckCallback();
}
if (timeout == 0xFFFFFFFF)
{
return HMX_MSG_Receive(q_id, msg, size);
}
q = (struct HMX_MSG_queue *)q_id;
if(size > q->msg_size_)
{
PrintError("%s : size %ld Error!!\n", __FUNCTION__, size);
return HMX_ERROR;
}
clock_gettime(CLOCK_REALTIME, &cur_time);
exp_nsec = (long long)cur_time.tv_sec * (long long)1000 * (long long)1000 * (long long)1000 + (long long)cur_time.tv_nsec;
if (timeout != 0)
exp_nsec += (long long)(timeout * (long long)1000 - 999) * (long long)1000;
timeo.tv_sec = exp_nsec / (1000 * 1000 * 1000);
timeo.tv_nsec = exp_nsec % (1000 * 1000 * 1000);
(void)pthread_mutex_lock(&q->q_lock_);
#if defined(HMX_MSG_DEBUG) && defined(VK_TASK_DEBUG)
q->receiveTick = VK_TIMER_GetSystemTick();
if (q->lastReceiveTick != 0 && (q->receiveTick - q->lastReceiveTick > HMX_MSG_NORMAL_DELAY_TICK))
{
if ((q->receiveTick - tickForVkDebug) > HMX_MSG_CRITICAL_DELAY_TICK)
{
PrintError("HMX_MSG_ReceiveTimeout : It has excuted too long time (%d) queue(%s)\n", q->receiveTick - q->lastReceiveTick, q->name);
}
}
#endif
rc = list_rem_next(q, msg, size, TRUE, &timeo);
#if defined(HMX_MSG_DEBUG) && defined(VK_TASK_DEBUG)
q->lastReceiveTick = tickForVkDebug = VK_TIMER_GetSystemTick();
#endif
if(HMX_OK != rc)
{
(void)pthread_mutex_unlock(&q->q_lock_);
if(ETIMEDOUT == rc)
{
PrintDebug("%s : list_rem_next() rc[%d] HMX_TIMEOUT!!\n", __FUNCTION__, rc);
return HMX_TIMEOUT;
}
else
{
PrintError("%s : list_rem_next() rc[%d] Error!!\n", __FUNCTION__, rc);
return HMX_ERROR;
}
}
#ifdef DEBUG_MSG_LIST_PRINT
print_list(q);
#endif
(void)pthread_mutex_unlock(&q->q_lock_);
PrintExit();
return HMX_OK;
}
int HMX_MSG_GetMessageCount(unsigned long q_id, unsigned long *pulMsgCount, unsigned long *pulMaxMsgCount)
{
struct HMX_MSG_queue *q;
PrintEnter();
q = (struct HMX_MSG_queue *)q_id;
(void)pthread_mutex_lock(&q->q_lock_);
*pulMsgCount = q->curr_msg_count_;
*pulMaxMsgCount = q->msg_count_;
(void)pthread_mutex_unlock(&q->q_lock_);
PrintExit();
return HMX_OK;
}
static int P_MSG_Check(struct HMX_MSG_queue *q, unsigned long q_id)
{
unsigned long ulNearlyFullCount;
#if !defined(CONFIG_DEBUG)
UNUSED(q_id);
#endif
ulNearlyFullCount = (q->msg_count_ * 3);
ulNearlyFullCount = ulNearlyFullCount/4;
if(q->msg_count_ == q->curr_msg_count_)
{
#if defined(CONFIG_DEBUG)
if (VK_TIMER_GetSystemTick() - tickForVkDebug > 5000)
{
tickForVkDebug = VK_TIMER_GetSystemTick();
// queue is full.
#if defined(CONFIG_DEBUG)
PrintError("\n!!\n!!! %s(): WARNING: queue_id 0x%X, name:%s full !!!%c\n!!!\n", __FUNCTION__, q_id, q->name, 7);
#if defined(VK_TASK_DEBUG)
VK_TASK_PrintTaskList();
#endif
#if defined(HMX_MSG_DEBUG)
HMX_MSG_PrintMsgQList();
#endif
#if defined(VK_SEM_DEBUG)
VK_SEM_PrintSemList();
#endif
#else
PrintError("\n!!\n!!! %s(): WARNING: queue_id 0x%X, full !!!%c\n!!!\n", __FUNCTION__, q_id, 7);
#endif
}
#endif
return HMX_MSG_FULL;
}
else if( q->curr_msg_count_ > ulNearlyFullCount )
{
#if defined(CONFIG_DEBUG)
PrintError("[HMX_MSG_Send] MsgQue is nearly full - SendTask:%d, QueId:0x%X, (%ld, %ld), name:%s\r\n",
pthread_self(), q_id, q->msg_count_, q->curr_msg_count_, q->name);
#endif
}
return HMX_OK;
}
/*
HMX_MSG_PrintMsgQList
¸Þ¼¼ÁöÅ¥ Á¤º¸¸¦ Ãâ·ÂÇÑ´Ù.
*/
#if defined(HMX_MSG_DEBUG)
void HMX_MSG_PrintMsgQList(void)
{
HINT32 ulCnt=0;
struct HMX_MSG_queue *pMsgQ;
PrintDebug("**********************************************************\n");
PrintDebug(" Name Qid Size Count Cur_Count Type\n");
for (pMsgQ = msg_q_list_head.tqh_first; pMsgQ != NULL; pMsgQ = pMsgQ->entries.tqe_next)
{
PrintDebug("[%03d]%20s 0x%08X %04d %05d %09d %04d\n",ulCnt,
pMsgQ->name, (unsigned long)pMsgQ, pMsgQ->msg_size_, pMsgQ->msg_count_, pMsgQ->curr_msg_count_, pMsgQ->suspend_type_);
ulCnt++;
}
PrintDebug("**********************************************************\n");
}
#endif
/*@}*/