📄 cxver5.c
字号:
/* place the task into the resource doubly linked wait list. */
tp = (tcbpointer)res_ptr; /* address of resource link list. */
do /* insert tcb at appropriate wait slot, based on priority. */
{
tp = tp->fwlink;
} while ((tp != (tcbpointer)res_ptr) && (tp->priority <= activetcb->priority));
/* We should insert it just after prevtcb, just before tp. */
activetcb->fwlink = tp->bwlink->fwlink;
tp->bwlink->fwlink = activetcb;
activetcb->bwlink = tp->bwlink;
tp->bwlink = activetcb;
if (res_ptr->fwlink->priority < res_ptr->owner->priority)
{
res_ptr->owner->priority = res_ptr->fwlink->priority;
}
/*
res_ptr->fwlink->priority is highest priority !!!
which we will then raise owner to highest !!!
*/
/* go place task into suspended state. */
if (K_I_Time_Common(timecnt,RESOURCE))
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in1(CXRSRSV_DELAY_K_TIMEOUT);
}
#endif
return(K_TIMEOUT); /* return the warning: that the time period expired */
}
else
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXRSRSV_K_OK,res_grp);
}
#endif
return(K_OK);
}
}
/* NO, no task owned this resource. This task is now the owner of
this resource */
res_ptr->fwlink = res_ptr->bwlink = (tcbpointer)(res_ptr);
res_ptr->owner = activetcb;
res_ptr->owner_priority = activetcb->priority;
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in3(CXRSRSV_K_OK,res_grp,func_mode);
}
#endif
K_I_Func_Return(); /* release task block. */
return(K_OK); /* return good status. */
}
/*****************************************************************
This lets a task that owns a resource, to release it. Once the resource
is released, if another task is waiting for it, then that task will
automatically become the owner.
******************************************************************/
byte K_Resource_Release(byte res_grp)
{
RESHDR *res_ptr;
if (res_grp >= MAX_RESOURCES) /* see if resource group OK */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXRSREL_K_ERROR,res_grp);
}
#endif
return(K_ERROR); /* no, return error status */
}
res_ptr = &res_que[res_grp]; /* get address of resource */
if (res_ptr->owner != activetcb) /* see if task really "owns" this. */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXRSREL_K_RESOURCE_NOT_OWNED,res_grp);
}
#endif
return(K_RESOURCE_NOT_OWNED); /* resource not owned by this task */
}
K_I_Disable_Sched(); /* set task block */
/* restore original task's priority */
res_ptr->owner->priority = active_priority = res_ptr->owner_priority;
/* see if another task waiting for this resource. */
if ((res_ptr->owner = res_ptr->fwlink) != (tcbpointer)res_ptr)
{
/* properly adjust the linked list. */
res_ptr->fwlink = res_ptr->fwlink->fwlink;
res_ptr->fwlink->bwlink = res_ptr->owner->bwlink;
res_ptr->owner->tcbstate = RESUME; /* wake task that was sleeping. */
if (res_ptr->owner->priority < active_priority)
PREEMPTED; /* yes, set the preempted scheduling flag */
res_ptr->owner_priority = res_ptr->owner->priority;
}
else
{
res_ptr->owner = NULL;
}
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXRSREL_K_OK,res_grp);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status to caller */
}
/*****************************************************************
QUEUE MANAGER
******************************************************************/
byte K_Que_Create(sign_word16 num_slots,byte slot_size,byte *queuearray,byte queuenum)
{
QUEHDR *queue_ptr;
if (queuenum >= MAX_QUEUES) /* see if queue number OK. */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQCRE_K_ERROR,queuenum);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block. */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQCRE_K_OK,queuenum);
}
#endif
queue_ptr = &queue[queuenum]; /* get address of proper queue handler. */
queue_ptr->base_ptr = queuearray; /* tell CMX where queue begins. */
queue_ptr->num_slots = num_slots; /* load number of slots */
queue_ptr->size_slot = slot_size; /* load in the size of slots */
K_Que_Reset(queuenum); /* reset the queue, all slots empty. */
K_I_Func_Return(); /* release task block */
return(K_OK);
}
byte K_Que_Reset(byte queuenum)
{
QUEHDR *queue_ptr;
if (queuenum >= MAX_QUEUES) /* see if queue number within range. */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQRST_K_ERROR,queuenum);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block. */
queue_ptr = &queue[queuenum]; /* get address of proper queue handler. */
/* reset the queue_ptr's variables, that maintain the queue_ptr */
queue_ptr->queue_cnt = queue_ptr->head = queue_ptr->tail = 0;
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQRST_K_OK,queuenum);
}
#endif
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status. */
}
/************************************************************
CMX general add to queue function.
called by K_Que_Add_Top and K_Que_Add_Bottom functions.
test: if testing for less then 0, then pointer = num_slots - 1
if testing for equal to num_slots then pointer = 0
when adding to top
add to where head points
increment head and test.
when adding to bottom.
decrement tail and test
add to where tail points
when removing from top
decrement head and test
remove from where head points
when removing from bottom
remove from where tail points
increment tail and test
top = 0: add to bottom
top = 1: add to top
*************************************************************/
byte K_I_Que_Add_Common(byte queuenum,void *byteptr,sign_word16 top)
{
QUEHDR *queue_ptr;
queue_ptr = &queue[queuenum]; /* get address of proper queue handler. */
if (queuenum >= MAX_QUEUES || (!queue_ptr->size_slot))
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQADD_K_ERROR,queuenum);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block */
/* see if queue is full already */
if (queue_ptr->queue_cnt == queue_ptr->num_slots)
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQADD_FULL,queuenum);
}
#endif
K_I_Func_Return(); /* release task block. */
return(K_ERROR); /* return proper status. */
}
if (top) /* see if adding to top of queue */
{
top = queue_ptr->head; /* top will now be our index into array. */
/* see if head equals the max number slots, and
if so, set pointer to bottom of queue */
if (++queue_ptr->head == queue_ptr->num_slots)
queue_ptr->head = 0;
}
else
{
/* were adding to bottom of queue, use tail pointer */
if (--queue_ptr->tail < 0) /* decrement tail pointer and test */
queue_ptr->tail = (queue_ptr->num_slots - 1);
top = queue_ptr->tail; /* top will now be our index into array. */
}
/* K_I_Copy = dest,source,count */
K_I_Copy((&(queue_ptr->base_ptr[top *
queue_ptr->size_slot])),byteptr,queue_ptr->size_slot);
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQADD_K_OK,queuenum);
}
#endif
/* see if queue now full */
if (++queue_ptr->queue_cnt == queue_ptr->num_slots)
{
K_I_Func_Return();
return(K_QUE_FULL); /* return status indicating queue now full. */
}
K_I_Func_Return(); /* release task block */
return(K_OK); /* return good status */
}
/********************************************************
test: if testing for less then 0 then pointer = num_slots - 1
if testing for equal to num_slots then pointer = 0
when removing from top
decrement head and test
remove from where head points
when removing from bottom
remove from where tail points
increment tail and test
top = 0: remove from bottom
top = 1: remove from top
*********************************************************/
byte K_I_Que_Get_Common(byte queuenum,void *byteptr,sign_word16 top)
{
QUEHDR *queue_ptr;
queue_ptr = &queue[queuenum]; /* get address of proper queue handler. */
if (queuenum >= MAX_QUEUES || (!queue_ptr->size_slot))
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQRMV_K_ERROR,queuenum);
}
#endif
return(K_ERROR);
}
K_I_Disable_Sched(); /* set task block */
/* see if queue_ptr has any slots filled */
if (!(queue_ptr->queue_cnt))
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQRMV_EMPTY,queuenum);
}
#endif
K_I_Func_Return();
return(K_ERROR); /* no, return error */
}
if (top) /* see if request was to remove top slot contents */
{
/* decrement head and test to see if head less then 0 */
if (--queue_ptr->head < 0)
queue_ptr->head = (queue_ptr->num_slots - 1);
top = queue_ptr->head; /* top will now be our index into array. */
}
else
{
/* request was to remove from bottom slot */
top = queue_ptr->tail; /* top will now be our index into array. */
/* see if tail pointer has reached its maximum count and set
to 0, if so */
if (++queue_ptr->tail == queue_ptr->num_slots)
queue_ptr->tail = 0;
}
/* K_I_Copy = dest,source,count */
K_I_Copy(byteptr,(&(queue_ptr->base_ptr[top *
queue_ptr->size_slot])),queue_ptr->size_slot);
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXQRMV_K_OK,queuenum);
}
#endif
/* see if queue_ptr now empty */
if (--queue_ptr->queue_cnt)
{
K_I_Func_Return(); /* no, release task block */
return(K_OK); /* return good operation */
}
K_I_Func_Return(); /* yes, queue empty, release task block */
return(K_QUE_EMPTY); /* return warning that queue now empty */
}
/***********************************************************
MESSAGE FUNCTIONS
**********************************************************/
/**********************************************************
The following is the generalize message wait function
is_get = 0, means to wait for message, with possible timeout
is_get = 1, means don't wait for message, if none.
**********************************************************/
void * K_I_Mesg_Wait_Common(byte mailbox,word16 timecnt,byte is_get)
{
MAILBOX *mail_ptr;
byte *copy_ptr;
MSG *link;
if (mailbox >= MAX_MAILBOXES) /* see if mailbox number OK. */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in3(CXMSWATM_K_ERROR,mailbox,is_get);
}
#endif
return(NULL); /* no, return null idicating error. */
}
K_I_Disable_Sched(); /* set task block. */
mail_ptr = &mail_box[mailbox]; /* address of the CMX mailbox handler. */
if (mail_ptr->waiter) /* see if another task already "owns" this mailbox. */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in3(CXMSWATM_MAILBOX_K_ERROR,mailbox,is_get);
}
#endif
K_I_Func_Return(); /* release task block. */
return(NULL); /* return error, for only one task may wait on mailbox. */
}
if (!mail_ptr->first_lnk) /* any messages present in mailbox, null = no */
{
if (is_get) /* K_Mesg_Get function used, do not wait */
{
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in2(CXMSGET_NOMESG_K_ERROR,mailbox);
}
#endif
K_I_Func_Return(); /* release task block. */
return(NULL); /* return error. */
}
mail_ptr->waiter = activetcb; /* identify who "owns" mailbox. */
#if (defined(CMXTRACKER) || defined(WINTRACKER))
if (CMXTRACKER_ON)
{
cmxtracker_in4(CXMSWATM_CALL,mailbox,timecnt);
}
#endif
K_I_Time_Common(timecnt,WAIT_MESG); /* go suspend task. */
/* task will be return to here by the K_I_Time_Common function. */
mail_ptr->waiter = NULL; /* now task will NOT own mailbox. */
/* test to see if time expired or task forcefully woken, prior
to a message being set to this mailbox. */
if (activetcb->tcbstate & TIME_EXPIRED)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -