📄 smpl.c
字号:
{ /* requesting token's priority is not higher than */
/* that of any user: enqueue requestor & return r=1 */
enqueue(f,tkn,pri,event,0.0); r=1;
if (tr) then msg(7,tkn,fname(f),1,l3[f]);
}
else
{ /* preempt user of server k. suspend event, save */
/* event number & remaining event time, & enqueue */
/* preempted token. If remaining event time is 0 */
/* (preemption occurred at the instant release was */
/* to occur, set 'te' > 0 for proper enqueueing */
/* (see 'enlist'). Update facility & server stati- */
/* stics for the preempted token, and set r = 0 to */
/* reserve the facility for the preempting token. */
if (tr) then msg(8,tkn,fname(f),2,0);
j=l1[k]; i=suspend(j); ev=l3[i]; te=l5[i]-clock;
if (te==0.0) then te=1.0e-99; put_elm(i);
enqueue(f,j,l2[k],ev,te);
if (tr) then
{msg(10,-1,"",j,l3[f]); msg(12,-1,fname(f),tkn,0);}
l3[k]++; l4[k]+=clock-l5[k];
l2[f]--; l4[f+1]++; r=0;
}
}
if (r==0) then
{ /* reserve server k of facility */
l1[k]=tkn; l2[k]=pri; l5[k]=clock; l2[f]++;
}
return(r);
}
/*------------------------ RELEASE FACILITY ------------------------*/
release(f,tkn)
int f,tkn;
{
int i,j=0,k,m; real te;
/* locate server (j) reserved by releasing token */
k=f+1+l1[f]; /* index of last server element */
for (i=f+2; i<=k; i++) if (l1[i]==tkn) then {j=i; break;}
if (j==0) then error(7,NULL); /* no server reserved */
l1[j]=0; l3[j]++; l4[j]+=clock-l5[j]; l2[f]--;
if (tr) then msg(9,tkn,fname(f),0,0);
if (l3[f]>0) then
{ /* queue not empty: dequeue request ('k' = */
/* index of element) & update queue measures */
k=l1[f+1]; l1[f+1]=l1[k]; te=l4[k];
l5[f+1]+=l3[f]*(clock-l5[f]); l3[f]--; l4[f]++; l5[f]=clock;
if (tr) then msg(11,-1,"",l2[k],l3[f]);
if (te==0.0) then
then
{ /* blocked request: place request at head of event */
/* list (so its facility request can be re-initiated */
/* before any other requests scheduled for this time) */
l5[k]=clock; l1[k]=evl; evl=k; m=4;
}
else
{ /* return after preemption: reserve facility for de- */
/* queued request & reschedule remaining event time */
l1[j]=l2[k]; l2[j]=(int)l5[k]; l5[j]=clock; l2[f]++;
if (tr) then msg(12,-1,fname(f),l2[k],0);
l5[k]=clock+te; enlist(&evl,k); m=5;
}
if (tr) then msg(m,-1,"",l3[k],0);
}
}
/*----------------------- GET FACILITY STATUS ----------------------*/
status(f)
int f;
{
return(l1[f]==l2[f]? 1:0);
}
/*-------------------- GET CURRENT QUEUE LENGTH --------------------*/
inq(f)
int f;
{
return(l3[f]);
}
/*-------------------- GET FACILITY UTILIZATION --------------------*/
real U(f)
int f;
{
int i; real b=0.0,t=clock-start;
if (t>0.0) then
{
for (i=f+2; i<=f+l1[f]+1; i++) b+=l4[i];
b/=t;
}
return(b);
}
/*---------------------- GET MEAN BUSY PERIOD ----------------------*/
real B(f)
int f;
{
int i,n=0; real b=0.0;
for (i=f+2; i<=f+l1[f]+1; i++) {b+=l4[i]; n+=l3[i];}
return((n>0)? b/n:b);
}
/*-------------------- GET AVERAGE QUEUE LENGTH --------------------*/
real Lq(f)
int f;
{
real t=clock-start;
return((t>0.0)? (l5[f+1]/t):0.0);
}
/*----------------------- TURN TRACE ON/OFF ------------------------*/
trace(n)
int n;
{
switch(n)
{
case 0: tr=0; break;
case 1:
case 2:
case 3: tr=n; tl= -1.0; newpage(); break;
case 4: end_line(); break;
default: break;
}
}
/*-------------------- GENERATE TRACE MESSAGE ----------------------*/
static msg(n,i,s,q1,q2)
int n,i,q1,q2; char *s;
{
static char *m[14] = {"", "SCHEDULE", "CAUSE", "CANCEL",
" RESCHEDULE"," RESUME", " SUSPEND", "REQUEST", "PREEMPT",
"RELEASE", " QUEUE", " DEQUEUE", " RESERVE", "FACILITY" };
if (clock>tl) /* print time stamp (if time has advanced) */
then {tl=clock; fprintf(opf," time %-12.3f ",clock);}
else fprintf(opf,"%21s",m[0]);
if (i>=0) /* print token number if specified */
then fprintf(opf,"-- token %-4d -- ",i);
else fprintf(opf,"-- -- ");
fprintf(opf,"%s %s",m[n],s); /* print basic message */
switch(n)
{ /* append qualifier */
case 1:
case 2:
case 3:
case 4:
case 5:
case 6: fprintf(opf," EVENT %d",q1); break;
case 7:
case 8: switch(q1)
{
case 0: fprintf(opf,": RESERVED"); break;
case 1: fprintf(opf,": QUEUED (inq = %d)",q2);
break;
case 2: fprintf(opf,": INTERRUPT"); break;
default: break;
}
break;
case 9: break;
case 10:
case 11: fprintf(opf," token %d (inq = %d)",q1,q2); break;
case 12: fprintf(opf," for token %d",q1); break;
case 13: fprintf(opf,": f = %d",q1); break;
default: break;
}
fprintf(opf,"\n"); end_line();
}
/*------------------------- TRACE LINE END -------------------------*/
static end_line()
{
if ((--lft)==0) then
{ /* end of page/screen. for trace 1, advance page if print- */
/* er output; screen output is free-running. for trace 2, */
/* pause on full screen; for trace 3, pause after line. */
switch(tr)
{
case 1: if (opf==display)
then lft=sl;
else endpage();
break;
case 2: if (mr)
then {putchar('\n'); lft=sl; pause();}
else endpage();
break;
case 3: lft=sl; break;
}
}
if (tr==3) then pause();
}
/*----------------------------- PAUSE ------------------------------*/
pause()
{ /* pause execution via 'mtr' call (if active) */
/* if (mr) then mtr(tr,1); else */ getchar();
}
/*------------------ DISPLAY ERROR MESSAGE & EXIT ------------------*/
error(n,s)
int n; char *s;
{
FILE *dest;
static char
*m[8]= { "Simulation Error at Time ",
"Empty Element Pool",
"Empty Name Space",
"Facility Defined After Queue/Schedule",
"Negative Event Time",
"Empty Event List",
"Preempted Token Not in Event List",
"Release of Idle/Unowned Facility" };
dest=opf;
while(1)
{ /* send messages to both printer and screen */
fprintf(dest,"\n**** %s%.3f\n",m[0],clock);
if (n) then fprintf(dest," %s\n",m[n]);
if (s!=NULL) then fprintf(dest," %s\n",s);
if (dest==display) then break; else dest=display;
}
if (opf!=display) then report();
/* if (mr) then mtr(0,1); */
exit(0);
}
/*------------------------ GENERATE REPORT -------------------------*/
report()
{
newpage();
reportf();
endpage();
}
/*-------------------- GENERATE FACILITY REPORT --------------------*/
reportf()
{
int f;
if ((f=fchn)==0)
then fprintf(opf,"\nno facilities defined: report abandoned\n");
else
{ /* f = 0 at end of facility chain */
while(f) {f=rept_page(f); if (f>0) then endpage();}
}
}
/*---------------------- GENERATE REPORT PAGE ----------------------*/
static rept_page(fnxt)
int fnxt;
{
int f,i,n; char fn[19];
static char *s[7]= {
"smpl SIMULATION REPORT", " MODEL: ", "TIME: ", "INTERVAL: ",
"MEAN BUSY MEAN QUEUE OPERATION COUNTS",
" FACILITY UTIL. ",
" PERIOD LENGTH RELEASE PREEMPT QUEUE" };
fprintf(opf,"\n%51s\n\n\n",s[0]);
fprintf(opf,"%-s%-54s%-s%11.3f\n",s[1],mname(),s[2],clock);
fprintf(opf,"%68s%11.3f\n\n",s[3],clock-start);
fprintf(opf,"%75s\n",s[4]);
fprintf(opf,"%s%s\n",s[5],s[6]);
f=fnxt; lft-=8;
while(f && lft--)
{
n=0; for (i=f+2; i<=f+l1[f]+1; i++) n+=l3[i];
if (l1[f]==1)
then sprintf(fn,"%s",fname(f));
else sprintf(fn,"%s[%d]",fname(f),l1[f]);
fprintf(opf," %-17s%6.4f %10.3f %13.3f %11d %9d %7d\n",
fn,U(f),B(f),Lq(f),n,(int)l4[f+1],(int)l4[f]);
f=l2[f+1];
}
return(f);
}
/*--------------------------- COUNT LINES --------------------------*/
lns(i)
int i;
{
lft-=i; if (lft<=0) then endpage();
return(lft);
}
/*---------------------------- END PAGE ----------------------------*/
endpage()
{
int c;
if (opf==display)
then
{ /* screen output: push to top of screen & pause */
while(lft>0) {putc('\n',opf); lft--;}
printf("\n[ENTER] to continue:"); getchar();
/* if (mr) then clr_scr(); else */ printf("\n\n");
}
else if (lft<pl) then putc(FF,opf);
newpage();
}
/*---------------------------- NEW PAGE ----------------------------*/
newpage()
{ /* set line count to top of page/screen after page change/screen */
/* clear by 'smpl', another SMPL module, or simulation program */
lft=(opf==display)? sl:pl;
}
/*------------------------ REDIRECT OUTPUT -------------------------*/
FILE *sendto(dest)
FILE *dest;
{
if (dest!=NULL) then opf=dest;
return(opf);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -