/*****************************************************************************
University of West Bohemia, DCS, Pilsen, Czech Republic
(c) copyright
01.04.2003
C-Sim version 5.1
file csim.c
C-Sim library
*****************************************************************************/
#include <string.h>
#include "csim.h"
/********************/
/* global variables */
/********************/
/* counter of simulation steps */
GLOBAL unsigned long int csim_step_number = 0;
/********************/
/* local variables */
/********************/
LOCAL CSIM_BOOLEAN in_step = FALSE; /* csim_step() activity flag */
LOCAL CSIM_BOOLEAN is_error = FALSE; /* error flag */
LOCAL CSIM_BOOLEAN statistics = FALSE; /* statistics switch */
LOCAL CSIM_PROCESS *current_proc = NULL; /* active process */
LOCAL CSIM_PROCESS *sqs = NULL; /* head of calendar */
LOCAL CSIM_DYN_MEM *mem = NULL; /* dyn. mem. - head of list */
LOCAL CSIM_TIME current_time = CSIM_ZERO_TIME; /* model time */
LOCAL CSIM_ERROR act_error; /* error record */
/*********************************************/
/* forwarded declarations of local functions */
/*********************************************/
/* inserts object into the list of dyn. memory blocks */
LOCAL void mem_in(CSIM_DYN_MEM *p_dyn_mem);
/* removes object from the list of dyn. memory blocks */
LOCAL void mem_out(CSIM_DYN_MEM *p_dyn_mem);
/* compute head statistics for item insert */
LOCAL void compute_into_hs(CSIM_HEAD *p_head);
/* compute head statistics for item remove */
LOCAL void compute_out_hs(CSIM_HEAD *p_head,
CSIM_LINK *p_link);
/* compute process statistics for activate */
LOCAL void compute_activate_ps(CSIM_PROCESS *p_process);
/*********************/
/* global functions */
/* *******************/
GLOBAL void csim_exception(CSIM_UWORD error_code,
CSIM_PROCESS *p_process,
void *p_void)
{
act_error.error_code = error_code;
act_error.p_proc_error = p_process;
act_error.p_void = p_void;
is_error = TRUE;
if (in_step == TRUE) {
csim_return_to_step();
}
}
GLOBAL void csim_error(CSIM_ERROR *p_error)
{
p_error->error_code = act_error.error_code;
p_error->p_proc_error = act_error.p_proc_error;
p_error->p_void = act_error.p_void;
is_error = FALSE;
}
GLOBAL CSIM_BOOLEAN csim_error_status(void)
{
return is_error;
}
GLOBAL CSIM_RESULT csim_set_name(CSIM_DYN_MEM *p_dyn_mem, char *name)
{
char *str = NULL;
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_dyn_mem(p_dyn_mem) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_SET_NAME_DYN_MEM,
csim_dyn_mem_state(p_dyn_mem)), current_proc, p_dyn_mem);
return FAILURE;
}
#endif
if (p_dyn_mem->name != NULL)
free(p_dyn_mem->name);
if (name != NULL) {
if ((str = (char *) malloc((strlen(name) + 1) * sizeof(char))) != NULL)
strcpy(str, name);
}
p_dyn_mem->name = str;
return SUCCESS;
}
GLOBAL CSIM_LINK *csim_first(CSIM_HEAD *p_head)
{
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_head(p_head) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_FIRST_HEAD, csim_head_state(p_head)),
current_proc, p_head);
return (NULL);
}
#endif
return (p_head->p_first);
}
GLOBAL CSIM_LINK *csim_last(CSIM_HEAD *p_head)
{
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_head(p_head) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_LAST_HEAD, csim_head_state(p_head)),
current_proc, p_head);
return (NULL);
}
#endif
return (p_head->p_last);
}
GLOBAL CSIM_BOOLEAN csim_empty(CSIM_HEAD *p_head)
{
CSIM_HEAD_CHECK state;
switch (state = csim_head_state(p_head)) {
case CSIM_H_EMPTY:
return (TRUE);
case CSIM_H_NOT_EMPTY:
return (FALSE);
case CSIM_H_DEFECTIVE:
case CSIM_H_ILLEGAL:
case CSIM_H_IS_NULL:
csim_exception(CSIM_ERR_CODE(CSIM_E_EMPTY_HEAD, state),
current_proc, p_head);
default:
break;
}
return (TRUE);
}
GLOBAL CSIM_WORD csim_cardinal(CSIM_HEAD *p_head)
{
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_head(p_head) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_CARD_HEAD, csim_head_state(p_head)),
current_proc, p_head);
return (-1);
}
#endif
return (p_head->lq);
}
GLOBAL CSIM_RESULT csim_clear(CSIM_HEAD *p_head)
{
CSIM_LINK *p_link;
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_head(p_head) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_CLEAR_HEAD, csim_head_state(p_head)),
current_proc, p_head);
return FAILURE;
}
#endif
while ((p_link = p_head->p_first) != p_head->p_last) {
p_link->suc->pred = p_link->pred;
p_link->pred->suc = p_link->suc;
p_head->p_first = p_link->suc;
if ((statistics == TRUE) || (p_head->statistics == TRUE)) {
p_head->sum_tw = csim_time_add(p_head->sum_tw,
csim_time_sub(current_time, p_link->enter_time));
p_link->head->arrival_cnt++;
}
p_link->suc = NULL;
p_link->pred = NULL;
p_link->head = NULL;
}
if (p_head->p_first != NULL) {
p_head->p_first = NULL;
p_head->p_last = NULL;
compute_out_hs(p_head, p_link);
p_head->last_time = current_time;
p_link->suc = NULL;
p_link->pred = NULL;
p_link->head = NULL;
p_head->lq = 0;
}
return SUCCESS;
}
GLOBAL CSIM_RESULT csim_out(CSIM_LINK *p_link)
{
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_link(p_link) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_OUT_LINK, csim_link_state(p_link)),
current_proc, p_link);
return FAILURE;
}
#endif
if (p_link->suc != NULL) {
p_link->suc->pred = p_link->pred;
p_link->pred->suc = p_link->suc;
if (p_link == p_link->head->p_first) {
if (p_link == p_link->head->p_last) {
p_link->head->p_first = NULL;
p_link->head->p_last = NULL;
}
else {
p_link->head->p_first = p_link->suc;
}
}
else {
if (p_link == p_link->head->p_last)
p_link->head->p_last = p_link->pred;
}
compute_out_hs(p_link->head, p_link);
p_link->head->last_time = current_time;
p_link->head->lq--;
p_link->suc = NULL;
p_link->pred = NULL;
p_link->head = NULL;
}
return SUCCESS;
}
GLOBAL CSIM_RESULT csim_into(CSIM_LINK *p_link,
CSIM_HEAD *p_head)
{
#ifndef CSIM_ERRCHECK_DISABLE
if (csim_check_link(p_link) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_INTO_LINK, csim_link_state(p_link)),
current_proc, p_link);
return FAILURE;
}
if (csim_check_head(p_head) == FALSE) {
csim_exception(CSIM_ERR_CODE(CSIM_E_INTO_HEAD, csim_head_state(p_head)),
current_proc, p_head);
return FAILURE;
}
#endif
if ((p_link->suc == NULL) && (p_link->pred == NULL)) {
if ((p_head->p_first == NULL) && (p_head->p_last == NULL)) {
p_head->p_first = p_link;
p_head->p_last = p_link;
p_link->pred = p_link;
p_link->suc = p_link;
p_link->head = p_head;
compute_into_hs(p_head);
p_link->head->last_time = current_time;
p_link->enter_time = current_time;
p_head->lq = 1;
}
else {
p_link->suc = p_head->p_first;
p_link->pred = p_head->p_last;
p_head->p_last->suc = p_link;
p_head->p_first->pred = p_link;
p_link->head = p_head;
p_head->p_last = p_link;
compute_into_hs(p_head);
p_link->head->last_time = current_time;