1 Star 0 Fork 1

wjh731/disksim_original

forked from 颜明博/disksim_original 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
disksim_ioqueue.c 126.67 KB
一键复制 编辑 原始数据 按行查看 历史
颜明博 提交于 2018-06-25 19:31 . first commit
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108
/*
* DiskSim Storage Subsystem Simulation Environment (Version 3.0)
* Revision Authors: John Bucy, Greg Ganger
* Contributors: John Griffin, Jiri Schindler, Steve Schlosser
*
* Copyright (c) of Carnegie Mellon University, 2001, 2002, 2003.
*
* This software is being provided by the copyright holders under the
* following license. By obtaining, using and/or copying this software,
* you agree that you have read, understood, and will comply with the
* following terms and conditions:
*
* Permission to reproduce, use, and prepare derivative works of this
* software is granted provided the copyright and "No Warranty" statements
* are included with all reproductions and derivative works and associated
* documentation. This software may also be redistributed without charge
* provided that the copyright and "No Warranty" statements are included
* in all redistributions.
*
* NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
* CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
* EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
* TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
* OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
* MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
* TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
* COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE
* OR DOCUMENTATION.
*
*/
/*
* DiskSim Storage Subsystem Simulation Environment (Version 2.0)
* Revision Authors: Greg Ganger
* Contributors: Ross Cohen, John Griffin, Steve Schlosser
*
* Copyright (c) of Carnegie Mellon University, 1999.
*
* Permission to reproduce, use, and prepare derivative works of
* this software for internal use is granted provided the copyright
* and "No Warranty" statements are included with all reproductions
* and derivative works. This software may also be redistributed
* without charge provided that the copyright and "No Warranty"
* statements are included in all redistributions.
*
* NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
* CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
* EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
* TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
* OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
* MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
* TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*/
/*
* DiskSim Storage Subsystem Simulation Environment
* Authors: Greg Ganger, Bruce Worthington, Yale Patt
*
* Copyright (C) 1993, 1995, 1997 The Regents of the University of Michigan
*
* This software is being provided by the copyright holders under the
* following license. By obtaining, using and/or copying this software,
* you agree that you have read, understood, and will comply with the
* following terms and conditions:
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose and without fee or royalty is
* hereby granted, provided that the full text of this NOTICE appears on
* ALL copies of the software and documentation or portions thereof,
* including modifications, that you make.
*
* THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
* BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR
* THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY
* THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT
* HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR
* DOCUMENTATION.
*
* This software is provided AS IS, WITHOUT REPRESENTATION FROM THE
* UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
* WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
* EXPRESSED OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS
* OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
* INCLUDING SPECIAL , INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION WITH THE
* USE OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS
* BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* The names and trademarks of copyright holders or authors may NOT be
* used in advertising or publicity pertaining to the software without
* specific, written prior permission. Title to copyright in this software
* and any associated documentation will at all times remain with copyright
* holders.
*/
#include "disksim_global.h"
#include "disksim_ioqueue.h"
#include "disksim_iosim.h"
#include "disksim_stat.h"
#include "disksim_disk.h"
#include "config.h"
#include "modules/disksim_ioqueue_param.h"
#define READY_TO_GO(iobufptr,queue) (((iobufptr)->state == WAITING) && (((queue)->enablement == NULL) || ((*(queue)->enablement)((iobufptr)->iolist))))
/* Request scheduling algorithms */
#define MINSCHED 1
#define FCFS 1
#define ELEVATOR_LBN 2
#define CYCLE_LBN 3
#define SSTF_LBN 4
#define ELEVATOR_CYL 5
#define CYCLE_CYL 6
#define SSTF_CYL 7
#define SPTF_OPT 8
#define SPCTF_OPT 9
#define SATF_OPT 10
#define WPTF_OPT 11
#define WPCTF_OPT 12
#define WATF_OPT 13
#define ASPTF_OPT 14
#define ASPCTF_OPT 15
#define ASATF_OPT 16
#define VSCAN_LBN 17
#define VSCAN_CYL 18
#define PRI_VSCAN_LBN 19
#define PRI_ASPTF_OPT 20
#define PRI_ASPCTF_OPT 21
#define SDF_APPROX 22
#define SDF_EXACT 23
#define SPTF_ROT_OPT 24
#define SPTF_ROT_WEIGHT 25
#define SPTF_SEEK_WEIGHT 26
#define TSPS 27
#define MAXSCHED 27
/* Sequential Stream Schemes */
#define IOQUEUE_CONCAT_READS 1
#define IOQUEUE_CONCAT_WRITES 2
#define IOQUEUE_CONCAT_BOTH 3
#define IOQUEUE_SEQSTREAM_READS 4
#define IOQUEUE_SEQSTREAM_WRITES 8
#define IOQUEUE_SEQSTREAM_EITHER 16
/* Sub queue identifications */
#define IOQUEUE_BASE 1
#define IOQUEUE_TIMEOUT 2
#define IOQUEUE_PRIORITY 3
/* Buffer states while in ioqueue */
#define WAITING 0
#define PENDING 1
/* Priority schemes */
#define ALLEQUAL 0
#define TWOQUEUE 1
/* Timeout schemes */
#define NOTIMEOUT 0
#define BASETIMEOUT 1
#define HALFTIMEOUT 2
/* Directions of movement for scanning policies */
#define ASC 1
#define DESC 2
/* read-only globals used during readparams phase */
static char *statdesc_accstats = "Physical access time";
static char *statdesc_qtimestats = "Queue time";
static char *statdesc_outtimestats = "Response time";
static char *statdesc_intarrstats = "Inter-arrival time";
static char *statdesc_readintarrstats = "Read inter-arrival";
static char *statdesc_writeintarrstats = "Write inter-arrival";
static char *statdesc_idlestats = "Idle period length";
static char *statdesc_infopenalty = "Sub-optimal mapping penalty";
static char *statdesc_reqsizestats = "Request size";
static char *statdesc_readsizestats = "Read request size";
static char *statdesc_writesizestats = "Write request size";
static char *statdesc_instqueuelen = "Instantaneous queue length";
typedef struct iob {
double starttime;
int state;
struct iob *next;
struct iob *prev;
int totalsize;
int devno;
int blkno;
int flags;
union {
struct {
int waittime;
ioreq_event *concat;
} pend;
double time;
} iob_un;
ioreq_event *iolist;
int reqcnt;
int cylinder;
int surface;
int opid;
} iobuf;
struct ioq;
typedef struct subq {
struct ioq * bigqueue;
int sched_alg;
int surfoverforw;
int force_absolute_fcfs;
int (**enablement)(ioreq_event *);
iobuf * list;
iobuf * current;
int prior;
int dir;
double vscan_value;
int vscan_cyls;
u_int lastblkno;
int lastsurface;
int lastcylno;
int optcylno;
int optsurface;
int sstfupdown;
int sstfupdowncnt;
int numreads;
int numwrites;
int switches;
int maxqlen;
double lastalt;
int listlen;
int iobufcnt;
int maxlistlen;
double runlistlen;
int readlen;
int maxreadlen;
double runreadlen;
int maxwritelen;
int numcomplete;
int reqoutstanding;
int numoutstanding;
int maxoutstanding;
double runoutstanding;
int num_sptf_sdf_different;
int num_scheduling_decisions;
statgen outtimestats;
statgen critreadstats;
statgen critwritestats;
statgen nocritreadstats;
statgen nocritwritestats;
statgen qtimestats;
statgen accstats;
statgen instqueuelen;
statgen infopenalty;
} subqueue;
typedef struct ioq {
subqueue base;
subqueue timeout;
subqueue priority;
int devno;
void (**idlework)(void *,int);
void * idleworkparam;
int idledelay;
timer_event *idledetect;
int (**concatok)(void *,int,int,int,int);
void * concatokparam;
int concatmax;
int comboverlaps;
int seqscheme;
int seqstreamdiff;
int to_scheme;
int to_time;
int pri_scheme;
int priority_mix;
int cylmaptype;
double writedelay;
double readdelay;
int sectpercyl;
int lastsubqueue;
int timeouts;
int timeoutreads;
int halfouts;
int halfoutreads;
double idlestart;
double lastarr;
double lastread;
double lastwrite;
double latency_weight;
statgen idlestats;
statgen intarrstats;
statgen readintarrstats;
statgen writeintarrstats;
statgen reqsizestats;
statgen readsizestats;
statgen writesizestats;
int maxlistlen;
int maxqlen;
int maxoutstanding;
int maxreadlen;
int maxwritelen;
int overlapscombed;
int readoverlapscombed;
int seqblkno;
int seqflags;
int seqreads;
int seqwrites;
int printqueuestats;
int printcritstats;
int printidlestats;
int printintarrstats;
int printsizestats;
char *name;
} ioqueue;
void ioqueue_print_contents (ioqueue *queue)
{
int i;
iobuf *tmp;
tmp = queue->base.list->next;
fprintf (outputfile, "Contents of base queue: listlen %d\n", queue->base.listlen);
for (i = 0; i < queue->base.iobufcnt; i++) {
fprintf(outputfile, "State: %d, blkno: %d\n", tmp->state, tmp->blkno);
tmp = tmp->next;
}
tmp = queue->timeout.list->next;
fprintf(outputfile, "Contents of timeout queue: listlen %d\n", queue->timeout.listlen);
for (i = 0; i < queue->timeout.iobufcnt; i++) {
fprintf(outputfile, "State: %d, blkno: %d\n", tmp->state, tmp->blkno);
tmp = tmp->next;
}
tmp = queue->priority.list->next;
fprintf(outputfile, "Contents of priority queue: listlen %d\n", queue->priority.listlen);
for (i = 0; i < queue->priority.iobufcnt; i++) {
fprintf(outputfile, "State: %d, blkno: %d\n", tmp->state, tmp->blkno);
tmp = tmp->next;
}
}
static void ioqueue_print_subqueue_state (subqueue *queue)
{
int i;
iobuf *tmp;
tmp = queue->list->next;
fprintf(outputfile, "\nContents of subqueue: listlen %d\n", queue->listlen);
fprintf(outputfile, "Subqueue state: lastblkno %d, lastcylno %d, lastsurface %d, dir %d\n", queue->lastblkno, queue->lastcylno, queue->lastsurface, queue->dir);
for (i = 0; i < queue->iobufcnt; i++) {
fprintf(outputfile, "State: %d, blkno: %d, cylno %d, surface %d\n", tmp->state, tmp->blkno, tmp->cylinder, tmp->surface);
tmp = tmp->next;
}
}
int ioqueue_get_number_in_queue (ioqueue *queue)
{
return(queue->base.listlen + queue->timeout.listlen + queue->priority.listlen);
}
int ioqueue_get_number_pending (ioqueue *queue)
{
int numpend = 0;
numpend += queue->base.listlen - queue->base.numoutstanding;
numpend += queue->timeout.listlen - queue->timeout.numoutstanding;
numpend += queue->priority.listlen - queue->priority.numoutstanding;
return(numpend);
}
int ioqueue_get_reqoutstanding (ioqueue *queue)
{
int numout = 0;
numout += queue->base.reqoutstanding;
numout += queue->timeout.reqoutstanding;
numout += queue->priority.reqoutstanding;
return(numout);
}
int ioqueue_get_number_of_requests (ioqueue *queue)
{
int numreqs = 0;
numreqs += queue->base.numcomplete + queue->base.listlen;
numreqs += queue->timeout.numcomplete + queue->timeout.listlen;
numreqs += queue->priority.numcomplete + queue->priority.listlen;
return(numreqs);
}
int ioqueue_get_number_of_requests_initiated (ioqueue *queue)
{
int numreqs = 0;
numreqs += queue->base.numcomplete + queue->base.numoutstanding;
numreqs += queue->timeout.numcomplete + queue->timeout.numoutstanding;
numreqs += queue->priority.numcomplete + queue->priority.numoutstanding;
return(numreqs);
}
int ioqueue_get_dist (ioqueue *queue, int blkno)
{
int lastblkno;
if (queue->lastsubqueue == IOQUEUE_BASE) {
lastblkno = queue->base.lastblkno;
} else if (queue->lastsubqueue == IOQUEUE_TIMEOUT) {
lastblkno = queue->timeout.lastblkno;
} else if (queue->lastsubqueue == IOQUEUE_PRIORITY) {
lastblkno = queue->priority.lastblkno;
} else {
fprintf(stderr, "Unknown queue identification at ioqueue_get_dist - %d\n", queue->lastsubqueue);
exit(1);
}
return(abs(blkno - lastblkno));
}
static void
ioqueue_get_cylinder_mapping(ioqueue *queue,
iobuf *curr,
int blkno,
int *cylptr,
int *surfptr,
int cylmaptype)
{
cylmaptype = (cylmaptype == -1) ? queue->cylmaptype : cylmaptype;
switch (cylmaptype) {
case MAP_NONE:
*cylptr = 0;
*surfptr = 0;
break;
case MAP_IGNORESPARING:
case MAP_ZONEONLY:
case MAP_ADDSLIPS:
case MAP_FULL:
device_get_mapping(cylmaptype,
curr->iolist->devno,
blkno,
cylptr,
surfptr,
NULL);
break;
case MAP_FROMTRACE:
/* this yucky cast is being allowed for convenience. We know
* it can't really hurt us... */
*cylptr = (int) curr->iolist->buf;
*surfptr = 0;
break;
case MAP_AVGCYLMAP:
*cylptr = blkno / queue->sectpercyl;
*surfptr = 0;
break;
default:
fprintf(stderr, "Unknown cylinder mapping type: %d\n", queue->cylmaptype);
exit(1);
}
}
void ioqueue_set_concatok_function (ioqueue *queue, int (**concatok)(void *,int,int,int,int), void *concatokparam)
{
queue->concatok = concatok;
queue->concatokparam = concatokparam;
}
void ioqueue_set_idlework_function (ioqueue *queue, void (**idlework)(void *,int), void *idleworkparam, double idledelay)
{
queue->idlework = idlework;
queue->idleworkparam = idleworkparam;
queue->idledelay = idledelay;
queue->idledetect = NULL;
}
void ioqueue_set_enablement_function (ioqueue *queue, int (**enablement)(ioreq_event *))
{
queue->base.enablement = enablement;
queue->timeout.enablement = enablement;
queue->priority.enablement = enablement;
}
static void ioqueue_idledetected (timer_event *timereq)
{
ioqueue *queue = (ioqueue *) timereq->ptr;
queue->idledetect = NULL;
(*queue->idlework)(queue->idleworkparam, queue->devno);
addtoextraq((event *)timereq);
}
void ioqueue_reset_idledetecter (ioqueue *queue, int timechange)
{
timer_event *idledetect = queue->idledetect;
int listlen = queue->base.listlen + queue->timeout.listlen + queue->priority.listlen;
if ((listlen) || ((idledetect) && (!timechange))) {
return;
}
if (idledetect) {
if (!(removefromintq((event *)idledetect))) {
fprintf(stderr, "existing idledetect event not on intq in ioqueue_reset_idledetecter\n");
exit(1);
}
} else {
idledetect = (timer_event *) getfromextraq();
idledetect->type = TIMER_EXPIRED;
idledetect->func = &disksim->timerfunc_ioqueue;
idledetect->ptr = queue;
queue->idledetect = idledetect;
}
idledetect->time = simtime + queue->idledelay;
addtointq((event *)idledetect);
}
static void ioqueue_update_arrival_stats (ioqueue *queue, ioreq_event *curr)
{
double tdiff;
if (queue->printintarrstats) {
tdiff = simtime - queue->lastarr;
queue->lastarr = simtime;
stat_update(&queue->intarrstats, tdiff);
if (curr->flags & READ) {
tdiff = simtime - queue->lastread;
queue->lastread = simtime;
stat_update(&queue->readintarrstats, tdiff);
} else {
tdiff = simtime - queue->lastwrite;
queue->lastwrite = simtime;
stat_update(&queue->writeintarrstats, tdiff);
}
}
if (queue->printsizestats) {
stat_update(&queue->reqsizestats, (double) curr->bcount);
if (curr->flags & READ) {
stat_update(&queue->readsizestats, (double) curr->bcount);
} else {
stat_update(&queue->writesizestats, (double) curr->bcount);
}
}
if (curr->blkno == queue->seqblkno) {
if ((curr->flags & READ) && (queue->seqflags & READ)) {
queue->seqreads++;
} else if (!(curr->flags & READ) && !(queue->seqflags & READ)) {
queue->seqwrites++;
}
}
queue->seqblkno = curr->blkno + curr->bcount;
queue->seqflags = curr->flags;
}
static void ioqueue_update_subqueue_statistics (subqueue *queue)
{
double tdiff = simtime - queue->lastalt;
queue->runlistlen += tdiff * queue->listlen;
queue->runreadlen += tdiff * queue->readlen;
if (queue->readlen > queue->maxreadlen) {
queue->maxreadlen = queue->readlen;
}
if ((queue->listlen - queue->readlen) > queue->maxwritelen) {
queue->maxwritelen = queue->listlen - queue->readlen;
}
queue->runoutstanding += tdiff * queue->numoutstanding;
if (queue->numoutstanding > queue->maxoutstanding) {
queue->maxoutstanding = queue->numoutstanding;
}
if (queue->listlen > queue->maxlistlen) {
queue->maxlistlen = queue->listlen;
}
if ((queue->listlen - queue->numoutstanding) > queue->maxqlen) {
queue->maxqlen = queue->listlen - queue->numoutstanding;
}
queue->lastalt = simtime;
}
static void remove_tsps(iobuf *tmp);
static void ioqueue_remove_from_subqueue (subqueue *queue, iobuf *tmp)
{
if(queue->sched_alg == TSPS){
remove_tsps(tmp);
}
if ((queue->list == tmp) && (tmp == tmp->next)) {
queue->list = NULL;
} else {
tmp->next->prev = tmp->prev;
tmp->prev->next = tmp->next;
if (queue->list == tmp) {
queue->list = tmp->prev;
}
}
tmp->next = NULL;
tmp->prev = NULL;
}
/* queue->list not NULL when entered */
static void ioqueue_insert_fcfs_to_queue (subqueue *queue, iobuf *temp)
{
temp->next = queue->list->next;
temp->prev = queue->list;
temp->next->prev = temp;
temp->prev->next = temp;
queue->list = temp;
}
/* queue->list not NULL when entered */
static void ioqueue_insert_ordered_to_queue (subqueue *queue, iobuf *temp)
{
iobuf *head;
iobuf *run;
head = queue->list->next;
if ((temp->cylinder < head->cylinder) ||
((temp->cylinder == head->cylinder) &&
(temp->surface < head->surface)) ||
((temp->cylinder == head->cylinder) &&
(temp->surface == head->surface) &&
(temp->blkno < head->blkno))) {
queue->list->next = temp;
temp->next = head;
temp->prev = queue->list;
head->prev = temp;
} else if ((temp->cylinder > queue->list->cylinder) ||
((temp->cylinder == queue->list->cylinder) &&
(temp->surface > queue->list->surface)) ||
((temp->cylinder == queue->list->cylinder) &&
(temp->surface == queue->list->surface) &&
(temp->blkno >= queue->list->blkno))) {
temp->next = head;
temp->prev = queue->list;
head->prev = temp;
queue->list->next = temp;
queue->list = temp;
} else {
run = head;
while ((temp->cylinder > run->next->cylinder) ||
((temp->cylinder == run->next->cylinder) &&
(temp->surface > run->next->surface)) ||
((temp->cylinder == run->next->cylinder) &&
(temp->surface == run->next->surface) &&
(temp->blkno >= run->next->blkno))) {
run = run->next;
}
temp->next = run->next;
temp->prev = run;
temp->next->prev = temp;
run->next = temp;
}
}
static int ioqueue_check_concat (subqueue *queue, iobuf *req1, iobuf *req2, int concatmax)
{
ioreq_event *tmp;
int seqscheme = queue->bigqueue->seqscheme;
int (**concatok)(void *,int,int,int,int) = queue->bigqueue->concatok;
void *concatokparam = queue->bigqueue->concatokparam;
if (req1->next != req2) {
fprintf(stderr, "Non-adjacent requests sent to ioqueue_check_concat\n");
exit(1);
}
if (req1->flags & READ) {
if (!(seqscheme & IOQUEUE_CONCAT_READS) || !(req2->flags & READ)) {
return(0);
}
} else {
if (!(seqscheme & IOQUEUE_CONCAT_WRITES) || (req2->flags & READ)) {
return(0);
}
}
if ((req1 == queue->list) || (req1 == req2) || !READY_TO_GO(req1,queue) || !READY_TO_GO(req2,queue) || ((req1->blkno + req1->totalsize) != req2->blkno) || ((req1->totalsize + req2->totalsize) > concatmax)) {
return(0);
}
if (concatok) {
if ((*concatok)(concatokparam, req1->blkno, req1->totalsize, req2->blkno, req2->totalsize) == 0) {
return(0);
}
}
tmp = req1->iolist;
if (tmp == NULL) {
req1->iolist = req2->iolist;
} else {
while (tmp->next) {
tmp = tmp->next;
}
tmp->next = req2->iolist;
}
req1->next = req2->next;
req1->next->prev = req1;
req1->reqcnt += req2->reqcnt;
req1->totalsize += req2->totalsize;
if (queue->list == req2) {
queue->list = req1;
}
queue->iobufcnt--;
addtoextraq((event *) req2);
return(1);
}
static void ioqueue_insert_new_request (subqueue *queue, iobuf *temp)
{
int concatmax;
ioqueue_update_subqueue_statistics(queue);
queue->iobufcnt++;
if (queue->list == NULL) {
queue->list = temp;
temp->next = temp;
temp->prev = temp;
} else {
if ((queue->sched_alg == FCFS) || (queue->sched_alg == PRI_VSCAN_LBN)) {
ioqueue_insert_fcfs_to_queue(queue, temp);
} else {
ioqueue_insert_ordered_to_queue(queue, temp);
}
}
concatmax = queue->bigqueue->concatmax;
if (concatmax) {
temp = temp->prev;
if (!(ioqueue_check_concat(queue, temp, temp->next, concatmax))) {
temp = temp->next;
}
ioqueue_check_concat(queue, temp, temp->next, concatmax);
}
queue->listlen++;
if (temp->flags & READ) {
queue->readlen++;
queue->numreads++;
} else {
queue->numwrites++;
}
}
/* Returns 0 if request is sequential from a previous request (and detection */
/* enabled). Otherwise returns 1. */
/* Assuming no command queueing. */
static int ioqueue_seqstream_head (ioqueue *queue, iobuf *listhead, iobuf *current)
{
int idiff;
int ret = 0;
if (!(queue->seqscheme & (IOQUEUE_SEQSTREAM_READS|IOQUEUE_SEQSTREAM_WRITES|IOQUEUE_SEQSTREAM_EITHER))) {
return(1);
}
idiff = queue->seqstreamdiff;
if ((current == listhead) || !READY_TO_GO(current->prev,(&queue->base))) {
ret = 1;
}
if (ret == 0) {
if (current->flags & READ) {
if (current->prev->flags & READ) {
if (!(queue->seqscheme & (IOQUEUE_SEQSTREAM_READS|IOQUEUE_SEQSTREAM_EITHER))) {
ret = 1;
}
} else {
if (!(queue->seqscheme & IOQUEUE_SEQSTREAM_EITHER)) {
ret = 1;
}
}
if ((current->prev->blkno != current->blkno) && (((current->prev->blkno + current->prev->totalsize + idiff) < current->blkno))) {
ret = 1;
}
} else {
if (current->prev->flags & READ) {
if (!(queue->seqscheme & IOQUEUE_SEQSTREAM_EITHER)) {
ret = 1;
}
} else {
if (!(queue->seqscheme & (IOQUEUE_SEQSTREAM_WRITES|IOQUEUE_SEQSTREAM_EITHER))) {
ret = 1;
}
}
if ((current->prev->blkno != current->blkno) && ((current->prev->blkno + current->prev->totalsize) != current->blkno)) {
ret = 1;
}
}
}
return(ret);
}
/* Queue contains >= 2 items when called */
static iobuf * ioqueue_get_request_from_fcfs_queue (subqueue *queue)
{
iobuf *tmp;
int i;
tmp = queue->list->next;
for (i = 0; i < queue->iobufcnt; i++) {
if (queue->force_absolute_fcfs) {
if (tmp->state == WAITING) {
if (READY_TO_GO(tmp,queue)) {
return(tmp);
} else {
return(NULL);
}
}
} else {
if (READY_TO_GO(tmp,queue)) {
return(tmp);
}
}
tmp = tmp->next;
}
return(NULL);
}
/* Queue contains >= 2 items when called */
static int ioqueue_get_priority_level (ioqueue *ioqueue, iobuf *req)
{
int ret = 0;
if (ioqueue->priority_mix == 1) {
if ((req->flags & TIME_CRITICAL) || (req->flags & READ)) {
ret = 1;
}
} else if (ioqueue->priority_mix == 2) {
if (req->flags & TIME_CRITICAL) {
ret = 2;
} else if (req->flags & READ) {
ret = 1;
}
} else if (ioqueue->priority_mix == 3) {
if (req->flags & READ) {
ret = 2;
} else if (req->flags & TIME_CRITICAL) {
ret = 1;
}
} else if (ioqueue->priority_mix == 4) {
if (req->flags & TIME_CRITICAL) {
ret = (req->flags & READ) ? 2 : 3;
} else {
ret = (req->flags & READ) ? 1 : 0;
}
} else if (ioqueue->priority_mix == 5) {
if (req->flags & READ) {
ret = 1;
}
} else if (ioqueue->priority_mix == 6) {
if (req->flags & TIME_CRITICAL) {
ret = 1;
}
}
return(ret);
}
static iobuf * ioqueue_get_request_from_pri_lbn_vscan_queue (subqueue *queue, int numlbns, int vscan_value)
{
int schedalg;
int priority_factor;
int age_factor;
iobuf *tmp;
int curr_effpri = 0, best_effpri = 0;
iobuf *ret = NULL;
int i;
schedalg = queue->bigqueue->timeout.sched_alg;
priority_factor = queue->bigqueue->priority.sched_alg;
age_factor = queue->bigqueue->to_time;
if (schedalg == ELEVATOR_LBN) {
vscan_value = numlbns;
} else if (schedalg == SSTF_LBN) {
vscan_value = 0;
}
tmp = queue->list->next;
for (i = 0; i < queue->iobufcnt; i++) {
if (READY_TO_GO(tmp,queue)) {
curr_effpri = tmp->blkno - queue->lastblkno;
if (schedalg == CYCLE_LBN) {
if (curr_effpri < 0) {
curr_effpri += numlbns;
}
} else if (curr_effpri) {
if (curr_effpri < 0) {
curr_effpri = -curr_effpri;
if (queue->dir == ASC) {
curr_effpri += vscan_value;
}
} else {
if (queue->dir == DESC) {
curr_effpri += vscan_value;
}
}
}
curr_effpri = numlbns - curr_effpri;
curr_effpri += (priority_factor * numlbns * ioqueue_get_priority_level(queue->bigqueue, tmp)) / 100;
curr_effpri += (age_factor * (int) (simtime - tmp->starttime)) / 1280;
if ((ret == NULL) || (curr_effpri > best_effpri)) {
ret = tmp;
best_effpri = curr_effpri;
}
}
tmp = tmp->next;
}
return(ret);
}
/* Queue contains >= 2 items when called */
static iobuf * ioqueue_get_request_from_lbn_scan_queue (subqueue *queue)
{
iobuf *temp;
iobuf *stop;
temp = queue->list->next;
stop = temp;
if (queue->lastblkno > temp->blkno) {
while ((temp->next != stop) && (queue->lastblkno > temp->next->blkno)) {
temp = temp->next;
}
temp = temp->next;
}
stop = temp;
while ((temp->next != stop) && !READY_TO_GO(temp,queue)) {
temp = temp->next;
}
if ((temp->next == stop) && !READY_TO_GO(temp,queue)) {
temp = NULL;
}
return(temp);
}
/* Queue contains >= 2 items when called */
static iobuf * ioqueue_get_request_from_lbn_vscan_queue (subqueue *queue, int value)
{
iobuf *temp;
iobuf *head;
iobuf *top = NULL;
iobuf *bottom = NULL;
int diff1, diff2;
int tmpdir;
iobuf *bestbottom;
tmpdir = queue->dir;
temp = queue->list->next;
head = queue->list->next;
while ((temp->next != head) && (queue->lastblkno > temp->next->blkno)) {
temp = temp->next;
}
if (temp->blkno < queue->lastblkno) {
bottom = temp;
while ((bottom != head) && !READY_TO_GO(bottom,queue)) {
bottom = bottom->prev;
}
if ((bottom == head) && !READY_TO_GO(bottom,queue)) {
bottom = NULL;
} else {
bestbottom = bottom;
while ((bottom != head) && ((bottom->prev->blkno == bestbottom->blkno) || (!(ioqueue_seqstream_head(queue->bigqueue, head, bottom))))) {
bottom = bottom->prev;
bestbottom = (READY_TO_GO(bottom,queue)) ? bottom : bestbottom;
}
bottom = bestbottom;
}
}
if (temp->next != head) {
if (temp->blkno >= queue->lastblkno) {
top = temp;
} else {
top = temp->next;
}
while ((top->next != head) && !READY_TO_GO(top,queue)) {
top = top->next;
}
}
if ((top == NULL) || !READY_TO_GO(top,queue) || (!(ioqueue_seqstream_head(queue->bigqueue, head, top)))) {
temp = bottom;
} else if ((bottom == NULL) || !READY_TO_GO(bottom,queue)) {
temp = top;
} else {
diff1 = diff(top->blkno, queue->lastblkno);
diff2 = diff(queue->lastblkno, bottom->blkno);
if (queue->dir == ASC) {
diff2 = (diff2) ? (diff2 + value) : diff2;
} else {
diff1 = (diff1) ? (diff1 + value) : diff1;
}
if (diff1 < diff2) {
temp = top;
} else if ((diff1 > diff2) || (queue->sstfupdown)) {
temp = bottom;
} else {
temp = top;
}
if (diff1 == diff2) {
queue->sstfupdown = (queue->sstfupdown) ? 0 : 1;
queue->sstfupdowncnt++;
}
}
if (temp->blkno != queue->lastblkno) {
queue->dir = (temp->blkno > queue->lastblkno) ? ASC : DESC;
}
top = (temp == top) ? bottom : top;
if ((top) && READY_TO_GO(top,queue)) {
int cylno1, cylno2;
int surface1, surface2;
ioqueue_get_cylinder_mapping(queue->bigqueue, temp, temp->blkno, &cylno1, &surface1, MAP_FULL);
ioqueue_get_cylinder_mapping(queue->bigqueue, top, top->blkno, &cylno2, &surface2, MAP_FULL);
diff1 = abs(cylno1 - queue->optcylno);
diff2 = abs(cylno2 - queue->optcylno);
if (((tmpdir == ASC) && (temp != bottom)) || ((tmpdir == DESC) && (temp == bottom))) {
if (diff2) {
diff2 += (int) (queue->vscan_value * (double) device_get_numcyls(temp->iolist->devno));
}
} else if (diff1) {
if (diff1) {
diff1 += (int) (queue->vscan_value * (double) device_get_numcyls(temp->iolist->devno));
}
}
if (diff1 > diff2) {
stat_update(&queue->infopenalty, (double) (diff1 - diff2));
/*
fprintf (outputfile, "diff1 %d, diff2 %d, diffdiff %d\n", diff1, diff2, (diff1 - diff2));
*/
} else if ((diff1 == diff2) && (diff1 == 0)) {
if ((queue->optsurface == surface2) && (surface1 != surface2)) {
stat_update(&queue->infopenalty, (double) 0);
}
}
}
return(temp);
}
/* Queue contains >= 2 items when called */
/* Returns pointer to "best" request on queue->lastcylno, or first request
on next available forward cylinder, or head (in priority order). */
static iobuf *ioqueue_identify_request_on_cylinder (subqueue *queue)
{
iobuf *temp;
iobuf *head;
iobuf *cylstop;
iobuf *surfstop;
int lastcylno;
int lastsurface;
int lastblkno;
lastcylno = queue->lastcylno;
lastsurface = queue->lastsurface;
lastblkno = queue->lastblkno;
head = queue->list->next;
temp = head;
if ((head->cylinder < lastcylno) && (lastcylno <= queue->list->cylinder)) {
while ((temp->next != head) && (lastcylno > temp->next->cylinder)) {
temp = temp->next;
}
temp = temp->next;
}
if (temp->cylinder != lastcylno) {
return(temp);
}
cylstop = temp; /* first req on cylinder */
while ((temp->next != head) && (lastcylno == temp->next->cylinder) && (lastsurface > temp->surface)) {
temp = temp->next;
}
if (lastsurface > temp->surface) {
temp = cylstop; /* drop out and try from first req on cylinder */
} else if (!queue->surfoverforw) {
while ((temp->next != head) && (lastcylno == temp->next->cylinder) && (!READY_TO_GO(temp,queue) || (temp->blkno < lastblkno))) {
temp = temp->next;
}
if (READY_TO_GO(temp,queue) && (temp->blkno >= lastblkno)) {
return(temp);
} else {
temp = cylstop; /* drop out and try from first req on cylinder */
}
} else { /* surfoverforw */
surfstop = temp; /* first req on surface */
while ((temp->next != head) && (lastcylno == temp->next->cylinder) && (lastsurface == temp->next->surface) && (!READY_TO_GO(temp,queue) || (temp->blkno < lastblkno))) {
temp = temp->next;
}
if (READY_TO_GO(temp,queue) && (temp->blkno >= lastblkno) && (temp->surface == lastsurface)) {
return(temp);
}
temp = surfstop;
while ((temp->next != head) && (lastcylno == temp->next->cylinder) && !READY_TO_GO(temp,queue)) {
temp = temp->next;
}
if (READY_TO_GO(temp,queue)) {
return(temp);
}
temp = cylstop; /* drop out and try from first req on cylinder */
}
/* drop out recovery point */
if (!READY_TO_GO(temp,queue)) {
while (!READY_TO_GO(temp,queue) && (temp->next != head) && (temp->next->cylinder == lastcylno)) {
temp = temp->next;
}
temp = temp->next;
}
return(temp);
}
/* Queue contains >= 2 items when called */
static iobuf * ioqueue_get_request_from_cyl_scan_queue (subqueue *queue)
{
iobuf *temp;
iobuf *stop;
temp = queue->list->next;
if (queue->lastcylno >= temp->cylinder) {
temp = ioqueue_identify_request_on_cylinder(queue);
}
stop = temp;
while (!READY_TO_GO(temp,queue) && (temp->next != stop)) {
temp = temp->next;
}
if ((temp->next == stop) && !READY_TO_GO(temp,queue)) {
temp = NULL;
}
return(temp);
}
/* Queue contains >= 2 items when called */
static iobuf * ioqueue_get_request_from_cyl_vscan_queue (subqueue *queue, int value)
{
iobuf *temp;
iobuf *head;
iobuf *top = NULL;
iobuf *bottom = NULL;
iobuf *bottom2 = NULL;
iobuf *bestone;
int diff1, diff2, diff3;
int tmpdir;
int cylno1, cylno2, cylno3;
int surface1, surface2, surface3;
tmpdir = queue->dir;
temp = queue->list->next;
head = queue->list->next;
bestone = ioqueue_identify_request_on_cylinder(queue);
if (!READY_TO_GO(bestone,queue) || (bestone->cylinder != queue->lastcylno)) {
bestone = NULL;
}
while ((temp->next != head) && (queue->lastblkno > temp->next->blkno)) {
temp = temp->next;
}
if (temp->blkno < queue->lastblkno) {
bottom = temp;
while ((bottom != head) && !READY_TO_GO(bottom,queue)) {
bottom = bottom->prev;
}
bottom2 = temp;
if (READY_TO_GO(bottom,queue) && (!bestone)) {
while ((bottom != head) && (bottom->prev->cylinder == bottom->cylinder)) {
bottom = bottom->prev;
}
while ((bottom != temp) && !READY_TO_GO(bottom,queue)) {
bottom = bottom->next;
}
}
}
if (temp->next != head) {
top = (temp->blkno >= queue->lastblkno) ? temp : temp->next;
while ((top->next != head) && !READY_TO_GO(top,queue)) {
top = top->next;
}
}
if (!bestone) {
if ((top == NULL) || !READY_TO_GO(top,queue)) {
temp = bottom;
} else if ((bottom == NULL) || !READY_TO_GO(bottom,queue)) {
temp = top;
} else {
diff1 = diff(top->cylinder, queue->lastcylno);
diff2 = diff(queue->lastcylno, bottom->cylinder);
if (queue->dir == ASC) {
diff2 += value;
} else {
diff1 += value;
}
if (diff1 < diff2) {
temp = top;
} else if ((diff1 > diff2) || (queue->sstfupdown)) {
temp = bottom;
} else {
temp = top;
}
if (diff1 == diff2) {
queue->sstfupdown = (queue->sstfupdown) ? 0 : 1;
queue->sstfupdowncnt++;
}
}
} else {
temp = bestone;
}
if (temp->cylinder != queue->lastcylno) {
queue->dir = (temp->cylinder > queue->lastcylno) ? ASC : DESC;
}
ioqueue_get_cylinder_mapping(queue->bigqueue, temp, temp->blkno, &cylno1, &surface1, MAP_FULL);
diff1 = abs(cylno1 - queue->optcylno);
if ((top == NULL) || !READY_TO_GO(top,queue)) {
top = temp;
}
ioqueue_get_cylinder_mapping(queue->bigqueue, top, top->blkno, &cylno2, &surface2, MAP_FULL);
diff2 = abs(cylno2 - queue->optcylno);
if ((bottom2 == NULL) || !READY_TO_GO(bottom2,queue)) {
bottom2 = temp;
}
ioqueue_get_cylinder_mapping(queue->bigqueue, bottom2, bottom2->blkno, &cylno3, &surface3, MAP_FULL);
diff3 = abs(cylno3 - queue->optcylno);
if (tmpdir == ASC) {
diff3 = (diff3) ? (diff3 + value) : diff3;
diff1 = (temp->cylinder < queue->lastcylno) ? (diff1 + value) : diff1;
} else {
diff2 = (diff2) ? (diff2 + value) : diff2;
diff1 = (temp->cylinder > queue->lastcylno) ? (diff1 + value) : diff1;
}
if ((diff3 < diff2) || ((!diff3) && (surface3 == queue->optsurface))) {
surface2 = surface3;
diff2 = diff3;
}
if (diff1 > diff2) {
stat_update(&queue->infopenalty, (double) (diff1 - diff2));
/*
fprintf (outputfile, "diff1 %d, diff2 %d, diffdiff %d, value %d\n", diff1, diff2, (diff1 - diff2), value);
*/
} else if ((diff1 == diff2) && (diff1 == 0)) {
if ((queue->optsurface == surface2) && (surface1 != surface2)) {
stat_update(&queue->infopenalty, (double) 0);
}
}
return(temp);
}
/* Queue contains >= 2 items when called */
static iobuf *ioqueue_get_request_from_opt_sptf_queue (subqueue *queue, int checkcache, int ageweight, int posonly)
{
int i;
iobuf *temp;
iobuf *best = NULL;
ioreq_event *test;
double mintime = 100000.0;
double readdelay;
double writedelay;
double delay;
double weight;
double temp_delay;
ioreq_event *tmp;
double age = 0.0;
ASSERT((ageweight >= 0) && (ageweight <= 3));
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
//fprintf(outputfile, "get_request_from_sptf:: listlen = %d\n", queue->listlen);
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
//fprintf(outputfile, "temp_delay = %f\n",temp_delay);
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
//fprintf(outputfile, "get_request_from_sptf...:: delay = %f\n", delay);
// fprintf(stderr,"serv %f old eff = %f new %f blkno %ld\n",temp_serv, mintime, delay,temp->blkno);
if (delay < mintime) {
best = temp;
mintime = delay;
}
}
} else {
//fprintf(outputfile, "not READY_TO_GO\n");
}
temp = temp->next;
}
addtoextraq((event *) test);
/* fprintf (stderr, "Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n",
mintime, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);*/
return(best);
}
static double
service_time(unsigned int current_cyl,
unsigned int current_sector,
unsigned int current_head,
unsigned int target_cyl,
unsigned int target_sector,
unsigned int target_head,
int read,
unsigned int blocks,
disk *currdisk)
{
int i;
double seektime = 0.0;
double rotation = 0.0;
double xfer = 0.0;
unsigned int current_max_sectors = 0;
unsigned int target_max_sectors = 0;
double current_angle = 0.0;
double target_angle = 0.0;
double period = dm_time_itod(currdisk->model->mech->dm_period(currdisk->model));
// get the seek time
{
struct dm_mech_state p1, p2;
uint64_t nsecs;
p1.cyl = current_cyl;
p1.head = current_head;
p2.cyl = target_cyl;
p2.head = target_head;
nsecs = currdisk->model->mech->dm_seek_time(currdisk->model,
&p1,
&p2,
read);
seektime = dm_time_itod(nsecs);
}
/* for(i = 0; i <currdisk->numbands; i++){ */
/* if(target_cyl < currdisk->bands[i].endcyl && target_max_sectors == 0){ */
/* target_max_sectors = currdisk->bands[i].blkspertrack; */
/* } */
/* if(current_cyl < currdisk->bands[i].endcyl && current_max_sectors == 0){ */
/* current_max_sectors = currdisk->bands[i].blkspertrack; */
/* } */
/* } */
target_angle = (float)target_sector / (float)target_max_sectors;
current_angle = (float)current_sector / (float)current_max_sectors;
// make sure its in [0,1]
if(target_angle < current_angle){
target_angle += 1.0;
}
// get the rotation time
{
struct dm_mech_state p1, p2;
uint64_t nsecs;
p1.theta = dm_angle_dtoi(current_angle);
p2.theta = dm_angle_dtoi(target_angle);
nsecs = currdisk->model->mech->dm_rottime(currdisk->model,
p1.theta,
p2.theta);
rotation = dm_time_itod(nsecs);
}
while(rotation < seektime){
rotation += period;
}
xfer = ((float)blocks / (float)target_max_sectors) * period;
// fprintf(stderr,"From %d to %d: seek %f, rotate %f xfer %f\n",current_cyl, target_cyl,seektime,rotation,xfer);
return(xfer + rotation);
}
#define MAX_TSPS 10
static double min_time;
static int current_head=0;
static int sched_count=0;
static iobuf *requests[MAX_TSPS];
static void remove_tsps(iobuf *tmp){
int i;
iobuf *temp;
temp = tmp;
for(i=0;i<sched_count;i++){
if(requests[current_head+i] == temp){
if((current_head+i+1) < MAX_TSPS){
requests[current_head+i] = requests[current_head+i+1];
temp = requests[current_head+i+1];
}else{
requests[current_head+i] = NULL;
}
}
}
if(sched_count != 0){
sched_count--;
}
}
static void calc_sp(iobuf **array, subqueue *queue, int checkcache, int no_requests){
int i;
int sector;
ioreq_event *test;
struct disk *singledisk;
unsigned int last_head = 0;
iobuf *temp = NULL;
char start = 0;
double acc_time=0.0;
unsigned int last_cylinder = 0;
unsigned int last_sector = 0;
// fprintf(stderr,"calc_sp YEAH\n");
singledisk = getdisk(queue->bigqueue->devno);
test = (ioreq_event *) getfromextraq();
for (i=0; i<no_requests; i++) {
temp = array[i];
/* if(acc_time > min_time){
break;
}*/
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
test->time = simtime;
device_get_mapping(queue->bigqueue->cylmaptype, temp->iolist->devno, temp->blkno, NULL, NULL, &sector);
if(start == 0){
start = 1;
acc_time = device_get_acctime(test->devno, test, 100000);
}else{
acc_time += service_time(last_cylinder,
last_sector,
last_head,
temp->cylinder,
(unsigned int) sector,
temp->surface,
(temp->flags & READ),
temp->totalsize,
singledisk);
}
last_sector = sector;
last_cylinder = temp->cylinder;
last_head = temp->surface;
}
if(acc_time < min_time){
// fprintf(stderr,"time = %f\n",acc_time);
//fprintf(stderr,"Setting up acc_time\n");
for (i=0; i<MAX_TSPS; i++) {
if(i<no_requests){
// fprintf(stderr,"i = %d %d\n",i,array[i]->blkno);
requests[i] = array[i];
}else{
requests[i] = NULL;
}
}
// fprintf(stderr,"\n");
min_time = acc_time;
sched_count = no_requests;
current_head = 0;
}
addtoextraq((event *) test);
}
static void perm(iobuf **array,
int m,
subqueue *queue,
int checkcache,
int no_requests){
int i;
iobuf *temp;
// fprintf(stderr,"perm\n");
if(m == 0){
/* for(i=0;i<no_requests;i++){
fprintf(stderr,"%ld ",array[i]->blkno);
}
fprintf(stderr,"\n");*/
calc_sp(array, queue, checkcache, no_requests);
}else{
for(i=0;i<m;i++){
temp = array[i];
array[i] = array[m-1];
array[m-1] = temp;
perm(array,m-1,queue,checkcache,no_requests);
temp = array[m-1];
array[m-1] = array[i];
array[i] = temp;
}
}
}
/* Queue contains >= 2 items when called */
static iobuf *
ioqueue_get_request_from_opt_tsps_queue(subqueue *queue,
int checkcache,
int ageweight,
int posonly)
{
int i;
iobuf *temp;
iobuf *best = NULL;
ioreq_event *test;
double acc_time;
/* iobuf *best2 = NULL;
double mintime = 100000.0;
double mintime2 = 100000.0;
double mintime3 = 100000.0;
double readdelay;
double writedelay;
double delay;
double age;
double weight;
double acc_time=0.0;
double serv_time=0.0;
double seek_time=0.0;
double effciency=0.0;
double band_mult=0.0;
struct disk *singledisk;
unsigned int max_sectors=0;
unsigned int temp_sectors=0;*/
int request_count=0;
iobuf *test_requests[MAX_TSPS];
// ioreq_event *tmp;
ASSERT((ageweight >= 0) && (ageweight <= 3));
/* singledisk = getdisk(queue->bigqueue->devno);
for(j=0;j<singledisk->numbands;j++){
if(singledisk->bands[j].blkspertrack > max_sectors){
max_sectors = singledisk->bands[j].blkspertrack;
}
}
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;*/
if(sched_count != 0){
if(requests[current_head] != NULL){
best = requests[current_head];
test = (ioreq_event *) getfromextraq();
test->blkno = best->blkno;
test->bcount = best->totalsize;
test->devno = best->iolist->devno;
test->flags = best->flags;
test->time = simtime;
acc_time = device_get_acctime(test->devno, test, 100000);
addtoextraq((event *) test);
current_head++;
sched_count--;
fprintf (stderr, "2Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n",
acc_time, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);
return(best);
}else{
fprintf(stderr,"ERROR: request NULL with count != 0\n");
abort();
}
}
temp = queue->list->next;
//fprintf(outputfile, "get_request_from_sptf:: listlen = %d\n", queue->listlen);
min_time = 100000;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test_requests[request_count] = temp;
request_count++;
if(request_count == MAX_TSPS){
break;
}
/* test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
serv_time = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
seek_time = device_get_seektime(test->devno, test, checkcache, (mintime - delay));
acc_time = device_get_acctime(test->devno, test, checkcache, (mintime - delay));
for(j=0;j<singledisk->numbands;j++){
if(singledisk->bands[j].endcyl >= temp->cylinder){
temp_sectors = singledisk->bands[j].blkspertrack;
break;
}
}
band_mult = ((double)temp_sectors/(double)max_sectors);
if ((temp->totalsize/acc_time) > effciency) {
best = temp;
effciency = (temp->totalsize/acc_time);
mintime3 = serv_time;
}
if(serv_time < mintime2){
best2 = temp;
mintime2 = serv_time;
}
}*/
} else {
//fprintf(outputfile, "not READY_TO_GO\n");
}
temp = temp->next;
}
if(request_count != MAX_TSPS){
for(i=request_count;i<MAX_TSPS;i++){
test_requests[i] = NULL;
}
}
/* if(best2 != best){
fprintf (stderr, "\n\n\n\n\nSelected request: %f, cylno %d, blkno %d, read %d, devno %d\n",
mintime3, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);
fprintf (stderr, "Best 2Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n\n\n\n\n\n",
mintime2, best2->cylinder, best2->blkno, (best2->flags & READ), best2->iolist->devno);
}*/
/* fprintf (stderr, "Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n",
mintime, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);*/
perm(test_requests,request_count,queue,checkcache,request_count);
fprintf(stderr,"sched count = %d\n",sched_count);
if(sched_count != 0){
if(requests[current_head] != NULL){
best = requests[current_head];
test = (ioreq_event *) getfromextraq();
test->blkno = best->blkno;
test->bcount = best->totalsize;
test->devno = best->iolist->devno;
test->flags = best->flags;
test->time = simtime;
acc_time = device_get_acctime(test->devno, test, 100000);
addtoextraq((event *) test);
current_head++;
sched_count--;
fprintf (stderr, "3Selected request: %f, cylno %d, blkno %d, read %d, devno %d %f\n",
acc_time, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno, min_time);
return(best);
}else{
fprintf(stderr,"ERROR: request NULL with count != 0\n");
abort();
}
}else{
fprintf(stderr,"ERROR: sched count = 0\n");
abort();
}
fprintf(stderr, "blah\n");
return(best);
}
static iobuf *ioqueue_get_request_from_opt_sptf_rot_weight_queue (subqueue *queue, int checkcache, int ageweight, int posonly)
{
int i;
iobuf *temp;
ioreq_event *test;
double readdelay;
double writedelay;
double delay;
double weight;
ioreq_event *tmp;
iobuf *best = NULL;
double mintime = 100000.0;
double minsubtract = 0.0;
double age = 0.0;
double temp_delay = 0.0;
double temp_seek = 0.0;
ASSERT((ageweight >= 0) && (ageweight <= 3));
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
temp_seek = device_get_seektime(test->devno, test, checkcache, (mintime - delay));
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
if((temp_delay - temp_seek) < 0.0)
fprintf(stderr,"Oops delay negative %f\n",temp_delay-temp_seek);
if ((delay - (temp_delay - temp_seek) * queue->bigqueue->latency_weight) < (mintime - minsubtract)) {
best = temp;
mintime = delay;
minsubtract = (temp_delay - temp_seek) * queue->bigqueue->latency_weight;
}
}
}
temp = temp->next;
}
addtoextraq((event *) test);
/*
fprintf (outputfile, "Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n", mintime, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);
*/
return(best);
}
static iobuf *ioqueue_get_request_from_opt_sptf_weight_queue (subqueue *queue, int checkcache, int ageweight, int posonly)
{
int i;
iobuf *temp;
ioreq_event *test;
double readdelay;
double writedelay;
double weight;
ioreq_event *tmp;
iobuf *best = NULL;
iobuf *best2 = NULL;
double mintime = 100000.0;
double temp_mintime = 100000.0;
double maxrot = 0.0;
double delay = 0.0;
double age = 0.0;
double temp_delay = 0.0;
double temp_seek = 0.0;
ASSERT((ageweight >= 0) && (ageweight <= 3));
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
if (delay < temp_mintime) {
temp_mintime = delay;
best2 = temp;
}
}
}
temp = temp->next;
}
addtoextraq((event *) test);
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
temp_seek = device_get_seektime(test->devno, test, checkcache, (mintime - delay));
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
/*
fprintf(outputfile, "get_request_from_sptf...:: delay = %f\n", delay);
*/
if((temp_delay - temp_seek) < 0.0)
fprintf(stderr,"Oops delay negative %f\n",temp_delay-temp_seek);
if (delay <= (temp_mintime * (1+queue->bigqueue->latency_weight))) {
if((temp_delay - temp_seek) >= maxrot){
best = temp;
maxrot = temp_delay - temp_seek;
}
}
}
}
temp = temp->next;
}
addtoextraq((event *) test);
/*
fprintf (outputfile, "Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n", mintime, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);
*/
return(best);
}
static iobuf *ioqueue_get_request_from_opt_sptf_seek_weight_queue (subqueue *queue, int checkcache, int ageweight, int posonly)
{
int i;
iobuf *temp;
iobuf *best = NULL;
iobuf *best2 = NULL;
ioreq_event *test;
double mintime = 100000.0;
double temp_mintime = 100000.0;
double minseek = 100000.0;
double readdelay;
double writedelay;
double delay = 0.0;
double age = 0.0;
double weight;
double temp_delay = 0.0;
double temp_seek = 0.0;
ioreq_event *tmp;
ASSERT((ageweight >= 0) && (ageweight <= 3));
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
temp_seek = device_get_seektime(test->devno, test, checkcache, (mintime - delay));
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
/*
fprintf(outputfile, "get_request_from_sptf...:: delay = %f\n", delay);
*/
if (delay < temp_mintime) {
temp_mintime = delay;
best2 = temp;
}
if (delay <= (temp_mintime * (1+queue->bigqueue->latency_weight))) {
if(temp_seek < minseek){
best = temp;
minseek = temp_seek;
}
}
}
}
temp = temp->next;
}
addtoextraq((event *) test);
#if 0
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
//fprintf(outputfile, "temp_delay = %f\n",temp_delay);
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
/*
fprintf(outputfile, "get_request_from_sptf...:: delay = %f\n", delay);
*/
if (delay < temp_mintime) {
temp_mintime = delay;
best2 = temp;
}
}
}
temp = temp->next;
}
addtoextraq((event *) test);
readdelay = queue->bigqueue->readdelay;
writedelay = queue->bigqueue->writedelay;
weight = (double) queue->bigqueue->to_time;
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
delay = (temp->flags & READ) ? readdelay : writedelay;
test->time = simtime + delay;
if (ageweight) {
tmp = temp->iolist;
age = tmp->time;
while (tmp) {
if (tmp->time < age) {
age = tmp->time;
}
tmp = tmp->next;
}
age = simtime - age;
}
if ((ageweight == 2) ||
((ageweight == 3) &&
(test->flags & (TIME_CRITICAL | TIME_LIMITED)))) {
delay -= age * weight * (double) 0.001;
}
if (delay < mintime) {
if (posonly) {
temp_delay = device_get_servtime(test->devno, test, checkcache, (mintime - delay));
temp_seek = device_get_seektime(test->devno, test, checkcache, (mintime - delay));
//fprintf(outputfile, "temp_delay = %f\n",temp_delay);
delay += temp_delay;
} else {
delay += device_get_acctime(test->devno, test, (mintime - delay));
}
if (ageweight == 1) {
delay *= (weight - age) / weight;
}
/*
fprintf(outputfile, "get_request_from_sptf...:: delay = %f\n", delay);
*/
if(temp_seek < 0.0)
fprintf(stderr,"Oops delay negative %f\n",temp_delay-temp_seek);
if (delay <= (temp_mintime * (1+queue->bigqueue->latency_weight))) {
if(temp_seek < minseek){
best = temp;
minseek = temp_seek;
}
}
}
}
temp = temp->next;
}
addtoextraq((event *) test);
#endif
/*
fprintf (outputfile, "Selected request: %f, cylno %d, blkno %d, read %d, devno %d\n", mintime, best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno);
*/
return(best);
}
/*
*
* ioqueue_get_request_from_sdf_queue()
*
* subqueue queue - the queue
* int exact - a flag to device_get_distance: if FALSE, then calculate from the last lbn requested,
* if TRUE, calculate from current device position
* int direction - a flag to device_get_distance: if FALSE, don't take distance into account
* if TRUE, return an "equivalent distance" taking into account the current direction
* of the moving sled/disk arm
*
* returns the request with the shortest distance from the current position
*
*/
static iobuf *ioqueue_get_request_from_sdf_queue (subqueue *queue, int exact, int direction) {
int i;
iobuf *temp;
iobuf *best = NULL;
ioreq_event *test;
int distance;
int min_distance = 1000000;
/*
fprintf(outputfile, "ioqueue_get_request_from_sdf_queue:: exact = %d, direction = %d\n",
exact, direction);
*/
test = (ioreq_event *) getfromextraq();
temp = queue->list->next;
for (i=0; i<queue->listlen; i++) {
if (READY_TO_GO(temp,queue) && (ioqueue_seqstream_head(queue->bigqueue, queue->list->next, temp))) {
test->blkno = temp->blkno;
test->bcount = temp->totalsize;
test->devno = temp->iolist->devno;
test->flags = temp->flags;
if (exact) {
distance = device_get_distance(test->devno, test, -1, direction);
}
else {
distance = device_get_distance(test->devno, test, queue->lastblkno, direction);
}
/*
fprintf(outputfile, "get_from_sdf_queue:: blkno = %d, distance = %d\n", test->blkno, distance);
*/
if (distance < min_distance) {
best = temp;
min_distance = distance;
}
}
temp = temp->next;
}
addtoextraq((event *) test);
/*
fprintf (outputfile, "Selected request: cylno %d, blkno %d, read %d, devno %d, with distance %d\n",
best->cylinder, best->blkno, (best->flags & READ), best->iolist->devno, min_distance);
*/
return(best);
}
static ioreq_event * ioqueue_show_next_request_from_subqueue (subqueue *queue)
{
iobuf *temp = 0;
ioreq_event *ret;
#if 0
iobuf *temp_sdf = NULL;
iobuf *temp_sptf = NULL;
#endif
int tmpdir;
tmpdir = queue->dir;
if ((queue->iobufcnt - queue->reqoutstanding) == 0) {
return(NULL);
} else if (queue->iobufcnt == 1) {
if (READY_TO_GO(queue->list,queue)) {
temp = queue->list;
} else {
temp = NULL;
}
} else {
if (queue->sched_alg == FCFS) {
temp = ioqueue_get_request_from_fcfs_queue(queue);
} else if (queue->sched_alg == PRI_VSCAN_LBN) {
temp = ioqueue_get_request_from_pri_lbn_vscan_queue(queue, device_get_number_of_blocks(queue->list->devno), queue->vscan_cyls);
} else if (queue->sched_alg == ELEVATOR_LBN) {
temp = ioqueue_get_request_from_lbn_vscan_queue(queue, device_get_number_of_blocks(queue->list->devno));
} else if (queue->sched_alg == CYCLE_LBN) {
temp = ioqueue_get_request_from_lbn_scan_queue(queue);
} else if (queue->sched_alg == SSTF_LBN) {
temp = ioqueue_get_request_from_lbn_vscan_queue(queue, 0);
} else if (queue->sched_alg == ELEVATOR_CYL) {
temp = ioqueue_get_request_from_cyl_vscan_queue(queue, device_get_numcyls(queue->list->devno));
} else if (queue->sched_alg == CYCLE_CYL) {
temp = ioqueue_get_request_from_cyl_scan_queue(queue);
} else if (queue->sched_alg == SSTF_CYL) {
temp = ioqueue_get_request_from_cyl_vscan_queue(queue, 0);
} else if (queue->sched_alg == SPTF_ROT_OPT) {
temp = ioqueue_get_request_from_opt_sptf_rot_weight_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == SPTF_ROT_WEIGHT) {
temp = ioqueue_get_request_from_opt_sptf_weight_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == SPTF_SEEK_WEIGHT) {
temp = ioqueue_get_request_from_opt_sptf_seek_weight_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == TSPS) {
temp = ioqueue_get_request_from_opt_tsps_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == SPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 0, TRUE);
fprintf(outputfile, "HEY THERE!\n");
#if 0
temp_sdf = ioqueue_get_request_from_sdf_queue(queue, FALSE, FALSE);
if ((temp_sdf != NULL) && (temp != NULL)) {
/*
fprintf(outputfile, "sptf_scheduler:: sptf = %d, sdf = %d\n",
temp->blkno, temp_sdf->blkno);
*/
if (temp_sdf->blkno != temp->blkno) {
queue->num_sptf_sdf_different++;
/*
fprintf(outputfile, "sptf scheduler:: sptf = %d, sdf = %d, num_different = %d\n",
temp->blkno, temp_sdf->blkno, queue->num_sptf_sdf_different);
*/
}
}
#endif
} else if (queue->sched_alg == SPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 0, TRUE);
} else if (queue->sched_alg == SATF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, 0, 0, FALSE);
} else if (queue->sched_alg == WPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 1, TRUE);
} else if (queue->sched_alg == WPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 1, TRUE);
} else if (queue->sched_alg == WATF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, 0, 1, FALSE);
} else if (queue->sched_alg == ASPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 2, TRUE);
} else if (queue->sched_alg == ASPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 2, TRUE);
} else if (queue->sched_alg == PRI_ASPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 3, TRUE);
} else if (queue->sched_alg == PRI_ASPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 3, TRUE);
} else if (queue->sched_alg == ASATF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, 0, 2, FALSE);
} else if (queue->sched_alg == VSCAN_LBN) {
temp = ioqueue_get_request_from_lbn_vscan_queue(queue, queue->vscan_cyls);
} else if (queue->sched_alg == VSCAN_CYL) {
temp = ioqueue_get_request_from_cyl_vscan_queue(queue, queue->vscan_cyls);
} else if (queue->sched_alg == SDF_APPROX) {
temp = ioqueue_get_request_from_sdf_queue(queue, FALSE, FALSE);
#if 0
temp_sptf = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 0, TRUE);
if ((temp_sptf != NULL) && (temp != NULL)) {
if (temp_sptf->blkno != temp->blkno) {
queue->num_sptf_sdf_different++;
/*
fprintf(outputfile, "sdf scheduler:: sptf = %d, sdf = %d, num_different = %d\n",
temp_sptf->blkno, temp->blkno, queue->num_sptf_sdf_different);
*/
}
}
#endif
} else if (queue->sched_alg == SDF_EXACT) {
temp = ioqueue_get_request_from_sdf_queue(queue, TRUE, FALSE);
#if 0
temp_sptf = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 0, TRUE);
if ((temp_sptf != NULL) && (temp != NULL)) {
if (temp_sptf->blkno != temp->blkno) {
queue->num_sptf_sdf_different++;
/*
fprintf(outputfile, "sdf scheduler:: sptf = %d, sdf = %d, num_different = %d\n",
temp_sptf->blkno, temp->blkno, queue->num_sptf_sdf_different);
*/
}
}
#endif
}
}
queue->dir = tmpdir;
if (temp == NULL) {
return(NULL);
} else if (!READY_TO_GO(temp,queue)) {
fprintf(stderr, "Selected request is !READY_TO_GO in show_next_request_from_subqueue\n");
exit(1);
}
ASSERT(temp->iolist != NULL);
if (temp->reqcnt == 1) {
ret = temp->iolist;
} else if (temp->iob_un.pend.concat) {
ret = temp->iob_un.pend.concat;
} else {
ret = (ioreq_event *) getfromextraq();
temp->iob_un.pend.concat = ret;
ret->time = simtime;
ret->type = temp->iolist->type;
ret->next = NULL;
ret->prev = NULL;
ret->bcount = temp->totalsize;
ret->blkno = temp->blkno;
ret->flags = temp->flags;
ret->busno = temp->iolist->busno;
ret->slotno = temp->iolist->slotno;
ret->devno = temp->iolist->devno;
ret->opid = temp->opid;
ret->buf = temp->iolist->buf;
}
queue->num_scheduling_decisions++;
return(ret);
}
static ioreq_event * ioqueue_get_next_request_from_subqueue (subqueue *queue)
{
iobuf *temp = NULL;
#if 0
iobuf *temp_sdf = NULL;
iobuf *temp_sptf = NULL;
#endif
ioreq_event *ret;
ioqueue_update_subqueue_statistics(queue);
if (0) {
ioqueue_print_subqueue_state(queue);
}
if ((queue->iobufcnt - queue->reqoutstanding) == 0) {
return(NULL);
} else if (queue->iobufcnt == 1) {
if (READY_TO_GO(queue->list,queue)) {
temp = queue->list;
switch (queue->sched_alg) {
case ELEVATOR_LBN:
case PRI_VSCAN_LBN:
case VSCAN_LBN:
if (queue->lastblkno != temp->blkno) {
queue->dir = (queue->lastblkno < temp->blkno) ? ASC : DESC;
}
break;
case ELEVATOR_CYL:
case VSCAN_CYL:
if (queue->lastcylno != temp->cylinder) {
queue->dir = (queue->lastcylno < temp->cylinder) ? ASC : DESC;
}
break;
}
} else { /* !READY_TO_GO */
temp = NULL;
}
} else {
if (queue->sched_alg == FCFS) {
temp = ioqueue_get_request_from_fcfs_queue(queue);
} else if (queue->sched_alg == PRI_VSCAN_LBN) {
temp = ioqueue_get_request_from_pri_lbn_vscan_queue(queue, device_get_number_of_blocks(queue->list->devno), queue->vscan_cyls);
} else if (queue->sched_alg == ELEVATOR_LBN) {
temp = ioqueue_get_request_from_lbn_vscan_queue(queue, device_get_number_of_blocks(queue->list->devno));
} else if (queue->sched_alg == CYCLE_LBN) {
temp = ioqueue_get_request_from_lbn_scan_queue(queue);
} else if (queue->sched_alg == SSTF_LBN) {
temp = ioqueue_get_request_from_lbn_vscan_queue(queue, 0);
} else if (queue->sched_alg == ELEVATOR_CYL) {
temp = ioqueue_get_request_from_cyl_vscan_queue(queue, device_get_numcyls(queue->list->devno));
} else if (queue->sched_alg == CYCLE_CYL) {
temp = ioqueue_get_request_from_cyl_scan_queue(queue);
} else if (queue->sched_alg == SSTF_CYL) {
temp = ioqueue_get_request_from_cyl_vscan_queue(queue, 0);
} else if (queue->sched_alg == SPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == SPTF_ROT_OPT) {
temp = ioqueue_get_request_from_opt_sptf_rot_weight_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == SPTF_ROT_WEIGHT) {
temp = ioqueue_get_request_from_opt_sptf_weight_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == SPTF_SEEK_WEIGHT) {
temp = ioqueue_get_request_from_opt_sptf_seek_weight_queue(queue, FALSE, 0, TRUE);
} else if (queue->sched_alg == TSPS) {
temp = ioqueue_get_request_from_opt_tsps_queue(queue, FALSE, 0, TRUE);
#if 0
temp_sdf = ioqueue_get_request_from_sdf_queue(queue, FALSE, FALSE);
if ((temp_sdf != NULL) && (temp != NULL)) {
/*
fprintf(outputfile, "sptf_scheduler:: sptf = %d, sdf = %d\n",
temp->blkno, temp_sdf->blkno);
*/
if (temp_sdf->blkno != temp->blkno) {
queue->num_sptf_sdf_different++;
/*
fprintf(outputfile, "sptf scheduler:: sptf = %d, sdf = %d, num_different = %d\n",
temp->blkno, temp_sdf->blkno, queue->num_sptf_sdf_different);
*/
}
}
#endif
} else if (queue->sched_alg == SPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 0, TRUE);
} else if (queue->sched_alg == SATF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, 0, 0, FALSE);
} else if (queue->sched_alg == WPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 1, TRUE);
} else if (queue->sched_alg == WPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 1, TRUE);
} else if (queue->sched_alg == WATF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, 0, 1, FALSE);
} else if (queue->sched_alg == ASPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 2, TRUE);
} else if (queue->sched_alg == ASPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 2, TRUE);
} else if (queue->sched_alg == PRI_ASPTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 3, TRUE);
} else if (queue->sched_alg == PRI_ASPCTF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, TRUE, 3, TRUE);
} else if (queue->sched_alg == ASATF_OPT) {
temp = ioqueue_get_request_from_opt_sptf_queue(queue, 0, 2, FALSE);
} else if (queue->sched_alg == VSCAN_LBN) {
temp = ioqueue_get_request_from_lbn_vscan_queue(queue, queue->vscan_cyls);
} else if (queue->sched_alg == VSCAN_CYL) {
temp = ioqueue_get_request_from_cyl_vscan_queue(queue, queue->vscan_cyls);
} else if (queue->sched_alg == SDF_APPROX) {
temp = ioqueue_get_request_from_sdf_queue(queue, FALSE, FALSE);
#if 0
temp_sptf = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 0, TRUE);
if ((temp_sptf != NULL) && (temp != NULL)) {
if (temp_sptf->blkno != temp->blkno) {
queue->num_sptf_sdf_different++;
/*
fprintf(outputfile, "sdf scheduler:: sptf = %d, sdf = %d, num_different = %d\n",
temp_sptf->blkno, temp->blkno, queue->num_sptf_sdf_different);
*/
}
}
#endif
} else if (queue->sched_alg == SDF_EXACT) {
temp = ioqueue_get_request_from_sdf_queue(queue, TRUE, FALSE);
#if 0
temp_sptf = ioqueue_get_request_from_opt_sptf_queue(queue, FALSE, 0, TRUE);
if ((temp_sptf != NULL) && (temp != NULL)) {
if (temp_sptf->blkno != temp->blkno) {
queue->num_sptf_sdf_different++;
/*
fprintf(outputfile, "sdf scheduler:: sptf = %d, sdf = %d, num_different = %d\n",
temp_sptf->blkno, temp->blkno, queue->num_sptf_sdf_different);
*/
}
}
#endif
}
}
if (temp == NULL) {
fprintf(stderr, "RETURNING NULL!!\n");
return(NULL);
} else if (!READY_TO_GO(temp,queue)) {
fprintf(stderr, "Selected request is !READY_TO_GO in get_next_request_from_subqueue\n");
exit(1);
}
/*
fprintf (outputfile, "Selected request: blkno %d, cylno %d, surface %d\n", temp->blkno, temp->cylinder, temp->surface);
*/
switch (queue->sched_alg) {
case ELEVATOR_LBN:
case CYCLE_LBN:
case PRI_VSCAN_LBN:
case ELEVATOR_CYL:
case CYCLE_CYL:
queue->lastblkno = temp->blkno;
break;
case VSCAN_LBN:
case VSCAN_CYL:
if (queue->vscan_cyls > 0) {
queue->lastblkno = temp->blkno;
break;
}
case SSTF_LBN:
if (queue->sched_alg != VSCAN_CYL) {
queue->lastblkno = temp->blkno + temp->totalsize;
if (queue->lastblkno != device_get_number_of_blocks(temp->iolist->devno)) {
break;
}
}
default:
queue->lastblkno = temp->blkno + temp->totalsize - 1;
break;
}
ioqueue_get_cylinder_mapping(queue->bigqueue, temp, queue->lastblkno, &queue->lastcylno, &queue->lastsurface, -1);
ioqueue_get_cylinder_mapping(queue->bigqueue, temp, queue->lastblkno, &queue->optcylno, &queue->optsurface, MAP_FULL);
if (temp->starttime == -1.0) {
temp->starttime = simtime;
}
ret = temp->iolist;
stat_update(&queue->instqueuelen, (double)(queue->iobufcnt - queue->reqoutstanding));
queue->reqoutstanding++;
queue->numoutstanding += temp->reqcnt;
while (ret) {
stat_update(&queue->qtimestats, (temp->starttime - ret->time));
ret = ret->next;
}
if (temp->iolist == NULL) {
fprintf(stderr, "iobuf structure with no iolist chosen to be scheduled\n");
exit(1);
} else if (temp->reqcnt == 1) {
ret = temp->iolist;
if (ret->next) {
fprintf(stderr, "More than one request when temp->reqcnt == 1\n");
exit(1);
}
temp->iolist = NULL;
temp->iob_un.time = ret->time;
} else if (temp->iob_un.pend.concat) {
ret = temp->iob_un.pend.concat;
temp->iob_un.pend.concat = NULL;
} else {
ret = (ioreq_event *) getfromextraq();
ret->time = temp->starttime;
ret->type = temp->iolist->type;
ret->next = NULL;
ret->prev = NULL;
ret->bcount = temp->totalsize;
ret->blkno = temp->blkno;
ret->flags = temp->flags;
ret->busno = temp->iolist->busno;
ret->slotno = temp->iolist->slotno;
ret->devno = temp->iolist->devno;
ret->opid = temp->opid;
ret->buf = temp->iolist->buf;
}
queue->current = temp;
temp->state = PENDING;
queue->num_scheduling_decisions++;
return(ret);
}
static int ioqueue_request_match (ioreq_event *wanted, iobuf *curr)
{
ioreq_event *tmp;
/* bcount undefined for completing requests */
if ((curr->blkno <= wanted->blkno) && ((curr->blkno + curr->totalsize) >= wanted->blkno)) {
if ((curr->blkno == wanted->blkno) && (curr->opid == wanted->opid) && ((curr->flags & READ) == (wanted->flags & READ))) {
return(1);
}
tmp = curr->iolist;
while (tmp) {
if ((tmp->blkno == wanted->blkno) && (tmp->opid == wanted->opid)) {
return(1);
}
tmp = tmp->next;
}
}
return(0);
}
/* Note: use of this function with concat will result in iobuf containing
the specified request */
static ioreq_event * ioqueue_get_specific_request_from_subqueue (subqueue *queue, ioreq_event *wanted)
{
iobuf *temp;
ioreq_event *ret;
ioqueue_update_subqueue_statistics(queue);
if ((queue->iobufcnt - queue->reqoutstanding) == 0) {
return(NULL);
} else {
temp = queue->list;
while ((temp->next != queue->list) && (ioqueue_request_match(wanted, temp) == 0)) {
temp = temp->next;
}
}
if (ioqueue_request_match(wanted, temp) == 0) {
return(NULL);
}
ASSERT(READY_TO_GO(temp,queue));
switch (queue->sched_alg) {
case ELEVATOR_LBN:
case CYCLE_LBN:
case PRI_VSCAN_LBN:
case ELEVATOR_CYL:
case CYCLE_CYL:
queue->lastblkno = temp->blkno;
break;
case VSCAN_LBN:
case VSCAN_CYL:
if (queue->vscan_cyls > 0) {
queue->lastblkno = temp->blkno;
break;
}
case SSTF_LBN:
if (queue->sched_alg != VSCAN_CYL) {
queue->lastblkno = temp->blkno + temp->totalsize;
if (queue->lastblkno != device_get_number_of_blocks(temp->iolist->devno)) {
break;
}
}
default:
queue->lastblkno = temp->blkno + temp->totalsize - 1;
break;
}
ioqueue_get_cylinder_mapping(queue->bigqueue, temp, queue->lastblkno, &queue->lastcylno, &queue->lastsurface, -1);
if (temp->starttime == -1.0) {
temp->starttime = simtime;
}
ret = temp->iolist;
stat_update(&queue->instqueuelen, (double)(queue->iobufcnt - queue->reqoutstanding));
queue->reqoutstanding++;
queue->numoutstanding += temp->reqcnt;
while (ret) {
stat_update(&queue->qtimestats, (temp->starttime - ret->time));
ret = ret->next;
}
ASSERT(temp->iolist != NULL);
if (temp->reqcnt == 1) {
ret = temp->iolist;
temp->iolist = NULL;
temp->iob_un.time = ret->time;
} else if (temp->iob_un.pend.concat) {
ret = temp->iob_un.pend.concat;
temp->iob_un.pend.concat = NULL;
} else {
ret = (ioreq_event *) getfromextraq();
ret->time = temp->starttime;
ret->type = temp->iolist->type;
ret->next = NULL;
ret->prev = NULL;
ret->bcount = temp->totalsize;
ret->blkno = temp->blkno;
ret->flags = temp->flags;
ret->busno = temp->iolist->busno;
ret->slotno = temp->iolist->slotno;
ret->devno = temp->iolist->devno;
ret->opid = temp->opid;
ret->buf = temp->iolist->buf;
}
queue->current = temp;
temp->state = PENDING;
return(ret);
}
static ioreq_event * ioqueue_set_starttime_in_subqueue (subqueue *queue, ioreq_event *target)
{
iobuf *temp = queue->list;
ioreq_event *ret;
if ((queue->iobufcnt - queue->reqoutstanding) == 0) {
return(NULL);
} else {
while ((temp->next != queue->list) && (!ioqueue_request_match(target, temp))) {
temp = temp->next;
}
}
if (!ioqueue_request_match(target, temp)) {
return(NULL);
}
ASSERT(temp->state == WAITING);
if (temp->starttime == -1.0) {
temp->starttime = simtime;
}
ret = temp->iolist;
return(ret);
}
static ioreq_event * ioqueue_remove_completed_request (subqueue *queue, ioreq_event *done)
{
iobuf *tmp;
iobuf *tail;
ioreq_event *trv;
/*
fprintf (outputfile, "Entering remove_completed_request - %d\n", queue->listlen);
*/
ioqueue_update_subqueue_statistics(queue);
tmp = queue->current;
ASSERT (tmp != NULL);
/* NOTE- the following match will fail with concat unless fixed properly */
if ((tmp->state != PENDING) || (ioqueue_request_match(done, tmp) == 0)) {
tmp = queue->list->next;
tail = queue->list;
while ((tmp != tail) && (ioqueue_request_match(done, tmp) == 0)) {
tmp = tmp->next;
}
if ((tmp->state != PENDING) || (ioqueue_request_match(done, tmp) == 0)) {
fprintf(stderr, "Completed event not found pending in ioqueue - blkno %d, tmp->blkno %d, tmp->totalsize %d, %d, %d, %d, %d\n", done->blkno, tmp->blkno, tmp->totalsize, (tmp == NULL), done->opid, tmp->opid, done->bcount);
fprintf(stderr, "tmp->state %d\n", tmp->state);
assert(0);
}
}
ioqueue_remove_from_subqueue(queue, tmp);
if (tmp->reqcnt == 1) {
trv = done;
trv->bcount = tmp->totalsize;
trv->time = tmp->starttime;
done->next = NULL;
queue->iobufcnt--;
queue->reqoutstanding--;
queue->listlen--;
if (tmp->flags & READ) {
queue->readlen--;
}
queue->numoutstanding--;
queue->numcomplete++;
stat_update(&queue->accstats, (simtime - tmp->starttime));
disksim->lastphystime = simtime - tmp->starttime;
stat_update(&queue->outtimestats, (simtime - tmp->iob_un.time));
if (tmp->flags & READ) {
if (tmp->flags & TIME_CRITICAL) {
stat_update(&queue->critreadstats, (simtime - tmp->iob_un.time));
} else {
stat_update(&queue->nocritreadstats, (simtime - tmp->iob_un.time));
}
} else {
if (tmp->flags & TIME_CRITICAL) {
stat_update(&queue->critwritestats, (simtime - tmp->iob_un.time));
} else {
stat_update(&queue->nocritwritestats, (simtime - tmp->iob_un.time));
}
}
} else {
trv = tmp->iolist;
queue->iobufcnt--;
queue->reqoutstanding--;
queue->listlen -= tmp->reqcnt;
if (trv->flags & READ) {
queue->readlen -= tmp->reqcnt;
}
queue->numoutstanding -= tmp->reqcnt;
queue->numcomplete += tmp->reqcnt;
while (trv) {
stat_update(&queue->accstats, (simtime - tmp->starttime));
disksim->lastphystime = simtime - tmp->starttime;
stat_update(&queue->outtimestats, (simtime - trv->time));
if (trv->flags & READ) {
if (trv->flags & TIME_CRITICAL) {
stat_update(&queue->critreadstats, (simtime - trv->time));
} else {
stat_update(&queue->nocritreadstats, (simtime - trv->time));
}
} else {
if (trv->flags & TIME_CRITICAL) {
stat_update(&queue->critwritestats, (simtime - trv->time));
} else {
stat_update(&queue->nocritwritestats, (simtime - trv->time));
}
}
trv = trv->next;
}
addtoextraq((event *) done);
trv = tmp->iolist;
}
addtoextraq((event *) tmp);
/*
fprintf (outputfile, "Exiting remove_completed_request\n");
*/
return(trv);
}
ioreq_event *ioqueue_get_specific_request(ioqueue *queue,
ioreq_event *wanted)
{
ioreq_event *tmp = NULL;
/*
* fprintf (outputfile, "Entering ioqueue_get_specific_request: %d\n",
* wanted->blkno);
*/
if((queue->priority.listlen - queue->priority.numoutstanding) > 0) {
tmp = ioqueue_get_specific_request_from_subqueue(&queue->priority,
wanted);
queue->lastsubqueue = IOQUEUE_PRIORITY;
}
if ((tmp == NULL) &&
((queue->timeout.listlen - queue->timeout.numoutstanding) > 0)) {
tmp = ioqueue_get_specific_request_from_subqueue(&queue->timeout, wanted);
queue->lastsubqueue = IOQUEUE_TIMEOUT;
}
if ((tmp == NULL)
&& ((queue->base.listlen - queue->base.numoutstanding) > 0)) {
tmp = ioqueue_get_specific_request_from_subqueue(&queue->base, wanted);
queue->lastsubqueue = IOQUEUE_BASE;
}
if (tmp) {
tmp->time = 0.0;
}
/*
* fprintf (outputfile, "Exiting ioqueue_get_specific_request: %x\n", tmp);
*/
return tmp;
}
/* This routine allows the queue owner to set the starttime without changing
the state of the queue or the request (i.e., setting the state to PENDING)
Specifically, this is used by advanced disk models which allow other
activity to occur for a request in advance of the actual selection of the
request to receive dedicated HDA (mechanical) activity. Thus, the request
needs to remain WAITING in order to enable algorithmic mechanical latency
reduction.
Not callable for concat queues, as a concat request may change inside
the queue after the starttime has been set, which means the queue owner
and the queue itself may have different ideas as to what constitutes the
entire request.
*/
ioreq_event * ioqueue_set_starttime (ioqueue *queue, ioreq_event *target)
{
ioreq_event *tmp = NULL;
/*
fprintf (outputfile, "Entering ioqueue_set_starttime: %d\n", target->blkno);
*/
/* Queue must not be concatable! */
ASSERT((queue->seqscheme & IOQUEUE_CONCAT_BOTH) == 0);
if ((queue->priority.listlen - queue->priority.numoutstanding) > 0) {
tmp = ioqueue_set_starttime_in_subqueue(&queue->priority, target);
}
if (!tmp && ((queue->timeout.listlen - queue->timeout.numoutstanding) > 0)) {
tmp = ioqueue_set_starttime_in_subqueue(&queue->timeout, target);
}
if (!tmp && ((queue->base.listlen - queue->base.numoutstanding) > 0)) {
tmp = ioqueue_set_starttime_in_subqueue(&queue->base, target);
}
/*
fprintf (outputfile, "Exiting ioqueue_set_starttime: %x\n", tmp);
*/
return(tmp);
}
ioreq_event * ioqueue_show_next_request (ioqueue *queue)
{
ioreq_event *tmp = NULL;
/*
fprintf (outputfile, "Entering ioqueue_show_next_request\n");
*/
if ((queue->priority.listlen - queue->priority.numoutstanding) > 0) {
tmp = ioqueue_show_next_request_from_subqueue(&queue->priority);
}
if (!tmp && ((queue->timeout.listlen - queue->timeout.numoutstanding) > 0)) {
tmp = ioqueue_show_next_request_from_subqueue(&queue->timeout);
}
if (!tmp && ((queue->base.listlen - queue->base.numoutstanding) > 0)) {
tmp = ioqueue_show_next_request_from_subqueue(&queue->base);
}
/*
fprintf (outputfile, "Exiting ioqueue_show_next_request: %d\n", ((tmp) ? tmp->blkno : -1));
*/
return(tmp);
}
ioreq_event * ioqueue_get_next_request (ioqueue *queue)
{
ioreq_event *tmp = NULL;
/*
fprintf (outputfile, "Entering ioqueue_get_next_request\n");
*/
if ((queue->priority.listlen - queue->priority.numoutstanding) > 0) {
if ((tmp = ioqueue_get_next_request_from_subqueue(&queue->priority))) {
queue->lastsubqueue = IOQUEUE_PRIORITY;
}
}
if (!tmp && ((queue->timeout.listlen - queue->timeout.numoutstanding) > 0)) {
if ((tmp = ioqueue_get_next_request_from_subqueue(&queue->timeout))) {
queue->lastsubqueue = IOQUEUE_TIMEOUT;
}
}
if (!tmp && ((queue->base.listlen - queue->base.numoutstanding) > 0)) {
if ((tmp = ioqueue_get_next_request_from_subqueue(&queue->base))) {
queue->lastsubqueue = IOQUEUE_BASE;
}
}
if (tmp) {
int numout = queue->base.numoutstanding + queue->timeout.numoutstanding + queue->priority.numoutstanding;
if (numout > queue->maxoutstanding) {
queue->maxoutstanding = numout;
}
tmp->time = 0.0;
}
/*
fprintf (outputfile, "Exiting ioqueue_get_next_request: %d\n", ((tmp) ? tmp->blkno : -1));
*/
return(tmp);
}
double ioqueue_add_new_request (ioqueue *queue, ioreq_event *new)
{
iobuf *tmp;
int listlen;
int qlen;
int readlen;
/*
fprintf (outputfile, "Entering ioqueue_add_new_request: %d\n", new->blkno);
*/
new->time = simtime;
ioqueue_update_arrival_stats(queue, new);
tmp = (iobuf *) getfromextraq();
StaticAssert (sizeof(iobuf) <= sizeof(event));
tmp->starttime = -1.0;
tmp->state = WAITING;
tmp->next = NULL;
tmp->prev = NULL;
tmp->totalsize = new->bcount;
tmp->devno = new->devno;
tmp->blkno = new->blkno;
tmp->flags = new->flags;
tmp->iolist = new;
new->next = NULL;
tmp->iob_un.pend.waittime = 0;
tmp->iob_un.pend.concat = NULL;
tmp->reqcnt = 1;
tmp->opid = new->opid;
switch(queue->pri_scheme) {
case ALLEQUAL:
if ((queue->base.sched_alg == ELEVATOR_LBN) ||
(queue->base.sched_alg == CYCLE_LBN) ||
(queue->base.sched_alg == SSTF_LBN) ||
(queue->base.sched_alg == VSCAN_LBN)) {
ioqueue_get_cylinder_mapping(queue, tmp, tmp->blkno, &tmp->cylinder, &tmp->surface, MAP_NONE);
} else {
ioqueue_get_cylinder_mapping(queue, tmp, tmp->blkno, &tmp->cylinder, &tmp->surface, -1);
}
ioqueue_insert_new_request(&queue->base, tmp);
break;
case TWOQUEUE:
if (new->flags & (TIME_CRITICAL|TIME_LIMITED)) {
if ((queue->priority.sched_alg == ELEVATOR_LBN) ||
(queue->priority.sched_alg == CYCLE_LBN) ||
(queue->priority.sched_alg == SSTF_LBN) ||
(queue->priority.sched_alg == VSCAN_LBN)) {
ioqueue_get_cylinder_mapping(queue, tmp, tmp->blkno, &tmp->cylinder, &tmp->surface, MAP_NONE);
} else {
ioqueue_get_cylinder_mapping(queue, tmp, tmp->blkno, &tmp->cylinder, &tmp->surface, -1);
}
ioqueue_insert_new_request(&queue->priority, tmp);
} else {
if ((queue->base.sched_alg == ELEVATOR_LBN) ||
(queue->base.sched_alg == CYCLE_LBN) ||
(queue->base.sched_alg == SSTF_LBN) ||
(queue->base.sched_alg == VSCAN_LBN)) {
ioqueue_get_cylinder_mapping(queue, tmp, tmp->blkno, &tmp->cylinder, &tmp->surface, MAP_NONE);
} else {
ioqueue_get_cylinder_mapping(queue, tmp, tmp->blkno, &tmp->cylinder, &tmp->surface, -1);
}
ioqueue_insert_new_request(&queue->base, tmp);
}
break;
default:
fprintf(stderr, "Unknown priority scheme being employed at ioqueue_add_new_request\n");
exit(1);
}
listlen = queue->base.listlen + queue->timeout.listlen + queue->priority.listlen;
qlen = listlen - (queue->base.numoutstanding + queue->timeout.numoutstanding + queue->priority.numoutstanding);
readlen = queue->base.readlen + queue->timeout.readlen + queue->priority.readlen;
queue->maxlistlen = max(listlen, queue->maxlistlen);
queue->maxqlen = max(qlen, queue->maxqlen);
queue->maxreadlen = max(readlen, queue->maxreadlen);
queue->maxwritelen = max((listlen - readlen), queue->maxwritelen);
if (listlen == 1) {
stat_update(&queue->idlestats, (simtime - queue->idlestart));
}
queue->idlestart = simtime;
if (queue->idledetect) {
if (!(removefromintq((event *)queue->idledetect))) {
fprintf(stderr, "existing idledetect event not on intq in ioqueue_add_new_request\n");
exit(1);
}
addtoextraq((event *)queue->idledetect);
queue->idledetect = NULL;
}
/*
fprintf (outputfile, "Exiting ioqueue_add_new_request\n");
*/
return(0.0);
}
static int ioqueue_raise_priority_subqueue (subqueue *queue, subqueue *priority, int opid, int pri_scheme)
{
int stop = FALSE;
iobuf *tmp;
ioreq_event *trv;
iobuf *bump;
int found = 0;
int iocnt;
/*
fprintf (outputfile, "Entered ioqueue_raise_priority_subqueue - opid %d (queue %p, priority %p, pri_scheme %d)\n", opid, queue, priority, pri_scheme);
*/
tmp = queue->list;
if (tmp == NULL) {
return (FALSE);
}
while (stop != TRUE) {
bump = NULL;
if ((tmp->iolist == NULL) || (tmp->totalsize == tmp->iolist->bcount)) {
if (tmp->opid == opid) {
bump = tmp;
}
} else {
trv = tmp->iolist;
while (trv != NULL) {
if (trv->opid == opid) {
bump = tmp;
}
trv = trv->next;
}
}
tmp = tmp->next;
if (tmp == queue->list) {
stop = TRUE;
}
if (bump) {
/*
fprintf (outputfile, "Raising priority of opid %d, buf %x, bump->state %d, read %d, crit %d, blkno %x\n", opid, bump->opid, bump->state, (bump->flags & READ), (bump->flags & TIME_CRITICAL), bump->blkno);
*/
if ((bump->state == WAITING) && (pri_scheme != ALLEQUAL)) {
ioqueue_update_subqueue_statistics(queue);
ioqueue_remove_from_subqueue(queue, bump);
ioqueue_insert_new_request(priority, bump);
found = 1;
}
found = (bump->state == WAITING) ? 1 : 2;
bump->flags |= TIME_CRITICAL;
trv = bump->iolist;
while (trv != NULL) {
if (trv->opid == opid) {
trv->flags |= TIME_CRITICAL;
}
trv = trv->next;
}
if ((bump->state == WAITING) && (pri_scheme != ALLEQUAL)) {
iocnt = bump->reqcnt;
priority->switches += iocnt;
queue->iobufcnt--;
queue->listlen -= iocnt;
if (bump->flags & READ) {
queue->readlen -= iocnt;
queue->numreads -= iocnt;
} else {
queue->numwrites -= iocnt;
}
}
break;
}
}
/*
fprintf (outputfile, "Returning found %d\n", found);
*/
return(found);
}
int ioqueue_raise_priority (ioqueue *queue, int opid)
{
int found = 0;
found = ioqueue_raise_priority_subqueue(&queue->base, &queue->priority, opid, queue->pri_scheme);
if (found) {
return(found);
}
found = ioqueue_raise_priority_subqueue(&queue->timeout, &queue->priority, opid, queue->pri_scheme);
return(found);
}
static int ioqueue_implement_timeouts (subqueue *queue, subqueue *timeout, int maxtime, u_int flag)
{
iobuf *tmp;
iobuf *done;
ioreq_event *trv;
int timeouts = 0;
int iocnt;
if (queue->list == NULL) {
return (0);
}
tmp = queue->list->next;
while (tmp != queue->list) {
tmp->iob_un.pend.waittime++;
/*
fprintf (outputfile, "New waittime for opid %d is %d, maxtime %d\n", tmp->opid, tmp->iob_un.pend.waittime, maxtime);
*/
if ((tmp->iob_un.pend.waittime > maxtime) && (tmp->state == WAITING)) {
/*
fprintf (outputfile, "Inside one of the request moving sections 1 - blkno %d, state %d\n", tmp->blkno, tmp->state);
*/
done = tmp;
tmp = tmp->next;
ioqueue_update_subqueue_statistics(queue);
ioqueue_remove_from_subqueue(queue, done);
ioqueue_insert_new_request(timeout, done);
done->flags |= flag;
trv = done->iolist;
while (trv != NULL) {
trv->flags |= flag;
trv = trv->next;
}
iocnt = done->reqcnt;
queue->iobufcnt--;
queue->listlen -= iocnt;
if (done->flags & READ) {
queue->numreads -= iocnt;
queue->readlen -= iocnt;
} else {
queue->numwrites -= iocnt;
}
timeouts += iocnt;
timeout->switches += iocnt;
if (queue->listlen == 0) {
tmp = NULL;
}
} else {
tmp = tmp->next;
}
}
if (tmp != NULL) {
tmp->iob_un.pend.waittime++;
/*
fprintf (outputfile, "New waittime for opid %d is %d, maxtime %d\n", tmp->opid, tmp->iob_un.pend.waittime, maxtime);
*/
if ((tmp->iob_un.pend.waittime > maxtime) && (tmp->state == WAITING)) {
/*
fprintf (outputfile, "Inside one of the request moving sections 2 - blkno %d, state %d\n", tmp->blkno, tmp->state);
*/
done = tmp;
ioqueue_update_subqueue_statistics(queue);
ioqueue_remove_from_subqueue(queue, done);
ioqueue_insert_new_request(timeout, done);
done->flags |= flag;
trv = done->iolist;
while (trv != NULL) {
trv->flags |= flag;
trv = trv->next;
}
iocnt = done->reqcnt;
queue->iobufcnt--;
queue->listlen -= iocnt;
if (done->flags & READ) {
queue->numreads -= iocnt;
queue->readlen -= iocnt;
} else {
queue->numwrites -= iocnt;
}
timeouts += iocnt;
timeout->switches += iocnt;
}
}
return(timeouts);
}
double ioqueue_tick (ioqueue *queue)
{
int timeouts;
int readcnt;
if (queue->to_scheme == BASETIMEOUT) {
if (queue->pri_scheme == ALLEQUAL) {
/*
fprintf(outputfile, "base queue to timeout queue\n");
*/
readcnt = queue->timeout.numreads;
timeouts = ioqueue_implement_timeouts(&queue->base, &queue->timeout, queue->to_time, TIMED_OUT);
queue->timeouts += timeouts;
queue->timeoutreads += queue->timeout.numreads - readcnt;
} else {
/*
fprintf(outputfile, "base queue to priority queue\n");
*/
readcnt = queue->priority.numreads;
timeouts = ioqueue_implement_timeouts(&queue->base, &queue->priority, queue->to_time, TIMED_OUT);
queue->timeouts += timeouts;
queue->timeoutreads += queue->priority.numreads - readcnt;
}
} else if (queue->to_scheme == HALFTIMEOUT) {
/*
fprintf(outputfile, "timeout queue to priority queue\n");
*/
readcnt = queue->priority.numreads;
timeouts = ioqueue_implement_timeouts(&queue->timeout, &queue->priority, queue->to_time, TIMED_OUT);
queue->timeouts += timeouts;
queue->timeoutreads += queue->priority.numreads - readcnt;
/*
fprintf(outputfile, "base queue to timeout queue\n");
*/
readcnt = queue->timeout.numreads;
timeouts = ioqueue_implement_timeouts(&queue->base, &queue->timeout, (queue->to_time / 2), HALF_OUT);
queue->halfouts += timeouts;
queue->halfoutreads += queue->timeout.numreads - readcnt;
}
return(0.0);
}
static void ioqueue_clobber_overlaps_subqueue (subqueue *queue, ioreq_event *ret, double arrtimemax)
{
iobuf *tmp;
ioreq_event *done;
int read = ret->flags & READ;
while ((tmp = queue->list)) {
if ((tmp->state != WAITING) || (tmp->blkno != ret->blkno) || (tmp->totalsize != ret->bcount) || ((read) && !(tmp->flags & READ)) || (tmp->iolist->time > arrtimemax)) {
tmp = tmp->next;
while ((tmp != queue->list) && ((tmp->state != WAITING) || (tmp->blkno != ret->blkno) || (tmp->totalsize != ret->bcount) || ((read) && !(tmp->flags & READ)) || (tmp->iolist->time > arrtimemax))) {
tmp = tmp->next;
}
if (tmp == queue->list) {
return;
}
}
ASSERT(tmp->reqcnt == 1);
done = ioqueue_get_specific_request_from_subqueue(queue, tmp->iolist);
ASSERT(done != NULL);
done = ioqueue_remove_completed_request(queue, done);
ASSERT(done->next == NULL);
done->next = ret->next;
ret->next = done;
queue->bigqueue->overlapscombed++;
if (done->flags & READ) {
queue->bigqueue->overlapscombed++;
}
}
}
ioreq_event * ioqueue_physical_access_done (ioqueue *queue, ioreq_event *curr)
{
ioreq_event *ret;
/*
fprintf(outputfile, "Entering ioqueue_physical_access_done: %d, devno %d\n", curr->blkno, curr->devno);
ioqueue_print_contents(queue);
*/
queue->idlestart = simtime;
if ((queue->pri_scheme != ALLEQUAL) && ((curr->flags & (TIME_CRITICAL|TIME_LIMITED)) || ((queue->to_scheme != NOTIMEOUT) && (curr->flags & TIMED_OUT)))) {
/*
fprintf(outputfile, "Checking the priority queue\n");
*/
ret = ioqueue_remove_completed_request(&queue->priority, curr);
} else if ((queue->to_scheme != NOTIMEOUT) && (curr->flags & (TIMED_OUT|HALF_OUT))) {
/*
fprintf(outputfile, "Checking the timeout queue\n");
*/
ret = ioqueue_remove_completed_request(&queue->timeout, curr);
} else {
/*
fprintf(outputfile, "Checking the base queue\n");
*/
ret = ioqueue_remove_completed_request(&queue->base, curr);
}
ASSERT(ret != NULL);
if (queue->comboverlaps) {
double arrtimemax = (queue->comboverlaps == 1) ? simtime : ret->time;
ioqueue_clobber_overlaps_subqueue(&queue->priority, ret, arrtimemax);
ioqueue_clobber_overlaps_subqueue(&queue->timeout, ret, arrtimemax);
ioqueue_clobber_overlaps_subqueue(&queue->base, ret, arrtimemax);
}
if (queue->idlework) {
ioqueue_reset_idledetecter(queue, 1);
}
// fprintf (outputfile, "Exiting ioqueue_physical_access_done: %f\n", disksim->lastphystime);
return(ret);
}
static void ioqueue_subqueue_copy (subqueue *queue, subqueue *new)
{
new->sched_alg = queue->sched_alg;
new->surfoverforw = queue->surfoverforw;
new->force_absolute_fcfs = queue->force_absolute_fcfs;
new->vscan_value = queue->vscan_value;
new->list = NULL;
new->current = NULL;
}
ioqueue * ioqueue_copy (ioqueue *queue)
{
ioqueue *new = (ioqueue *) malloc(sizeof(ioqueue));
memcpy(new, queue, sizeof(ioqueue));
ioqueue_subqueue_copy(&queue->base, &new->base);
ioqueue_subqueue_copy(&queue->timeout, &new->timeout);
ioqueue_subqueue_copy(&queue->priority, &new->priority);
return new;
}
static void ioqueue_subqueue_resetstats (subqueue *queue)
{
queue->numreads = 0;
queue->numwrites = 0;
queue->switches = 0;
queue->runreadlen = 0.0;
queue->maxreadlen = 0;
queue->maxwritelen = 0;
queue->maxlistlen = 0;
queue->runlistlen = 0.0;
queue->maxqlen = 0;
queue->numcomplete = 0;
queue->maxoutstanding = 0;
queue->runoutstanding = 0.0;
queue->sstfupdowncnt = 0;
queue->lastalt = simtime;
queue->num_sptf_sdf_different = 0;
stat_reset(&queue->accstats);
stat_reset(&queue->qtimestats);
stat_reset(&queue->outtimestats);
stat_reset(&queue->critreadstats);
stat_reset(&queue->nocritreadstats);
stat_reset(&queue->critwritestats);
stat_reset(&queue->nocritwritestats);
stat_reset(&queue->instqueuelen);
stat_reset(&queue->infopenalty);
}
static void ioqueue_subqueue_initialize (subqueue *queue, int devno)
{
addlisttoextraq((event **)&queue->list);
queue->enablement = NULL;
queue->dir = ASC;
queue->lastblkno = 0;
queue->lastsurface = 0;
queue->lastcylno = 0;
queue->prior = 0;
queue->sstfupdown = 0;
queue->current = NULL;
queue->readlen = 0;
queue->iobufcnt = 0;
queue->reqoutstanding = 0;
queue->listlen = 0;
queue->numoutstanding = 0;
queue->vscan_value = 0.2;
queue->num_sptf_sdf_different = 0;
stat_initialize(statdeffile, statdesc_accstats, &queue->accstats);
stat_initialize(statdeffile, statdesc_qtimestats, &queue->qtimestats);
stat_initialize(statdeffile, statdesc_outtimestats, &queue->outtimestats);
stat_initialize(statdeffile, statdesc_outtimestats, &queue->critreadstats);
stat_initialize(statdeffile, statdesc_outtimestats, &queue->nocritreadstats);
stat_initialize(statdeffile, statdesc_outtimestats, &queue->critwritestats);
stat_initialize(statdeffile, statdesc_outtimestats, &queue->nocritwritestats);
stat_initialize(statdeffile, statdesc_instqueuelen, &queue->instqueuelen);
stat_initialize(statdeffile, statdesc_infopenalty, &queue->infopenalty);
if ((queue->sched_alg == VSCAN_LBN) || (queue->sched_alg == PRI_VSCAN_LBN)) {
/* queue->vscan_cyls = queue->vscan_value * (double) device_get_number_of_blocks(devno); */
} else {
/* queue->vscan_cyls = queue->vscan_value * (double) device_get_numcyls(devno); */
}
}
void ioqueue_resetstats (ioqueue *queue)
{
queue->timeouts = 0;
queue->timeoutreads = 0;
queue->halfouts = 0;
queue->halfoutreads = 0;
queue->idlestart = simtime;
queue->maxlistlen = 0;
queue->maxqlen = 0;
queue->maxoutstanding = 0;
queue->maxreadlen = 0;
queue->maxwritelen = 0;
queue->overlapscombed = 0;
queue->readoverlapscombed = 0;
queue->seqreads = 0;
queue->seqwrites = 0;
stat_reset(&queue->intarrstats);
stat_reset(&queue->readintarrstats);
stat_reset(&queue->writeintarrstats);
stat_reset(&queue->idlestats);
stat_reset(&queue->reqsizestats);
stat_reset(&queue->readsizestats);
stat_reset(&queue->writesizestats);
ioqueue_subqueue_resetstats(&queue->base);
ioqueue_subqueue_resetstats(&queue->timeout);
ioqueue_subqueue_resetstats(&queue->priority);
}
void ioqueue_setcallbacks ()
{
disksim->timerfunc_ioqueue = ioqueue_idledetected;
}
void ioqueue_initialize (ioqueue *queue, int devno)
{
/* fprintf(stderr, "ioqueue_initialize:: devno = %d\n", devno); */
StaticAssert (sizeof(iobuf) <= DISKSIM_EVENT_SIZE);
ioqueue_setcallbacks();
ioqueue_subqueue_initialize(&queue->base, devno);
queue->base.bigqueue = queue;
ioqueue_subqueue_initialize(&queue->timeout, devno);
queue->timeout.bigqueue = queue;
ioqueue_subqueue_initialize(&queue->priority, devno);
queue->priority.bigqueue = queue;
queue->devno = devno;
queue->concatok = NULL;
queue->idlework = NULL;
queue->idledelay = 0.0;
queue->idledetect = NULL;
/* queue->sectpercyl = device_get_avg_sectpercyl(devno); */
queue->lastsubqueue = IOQUEUE_BASE;
queue->lastarr = 0.0;
queue->lastread = 0.0;
queue->lastwrite = 0.0;
queue->seqblkno = -1;
stat_initialize(statdeffile, statdesc_intarrstats, &queue->intarrstats);
stat_initialize(statdeffile, statdesc_readintarrstats, &queue->readintarrstats);
stat_initialize(statdeffile, statdesc_writeintarrstats, &queue->writeintarrstats);
stat_initialize(statdeffile, statdesc_idlestats, &queue->idlestats);
stat_initialize(statdeffile, statdesc_reqsizestats, &queue->reqsizestats);
stat_initialize(statdeffile, statdesc_readsizestats, &queue->readsizestats);
stat_initialize(statdeffile, statdesc_writesizestats, &queue->writesizestats);
}
void ioqueue_cleanstats (ioqueue *queue)
{
double tpass;
ioqueue_update_subqueue_statistics(&queue->base);
ioqueue_update_subqueue_statistics(&queue->timeout);
ioqueue_update_subqueue_statistics(&queue->priority);
if ((queue->base.listlen + queue->timeout.listlen + queue->priority.listlen) == 0) {
tpass = simtime - queue->idlestart;
stat_update(&queue->idlestats, tpass);
}
queue->idlestart = simtime;
}
ioqueue * ioqueue_createdefaultqueue ()
{
ioqueue * queue = (ioqueue *) malloc(sizeof(ioqueue));
bzero(queue, sizeof(ioqueue));
queue->printqueuestats = 1;
queue->printcritstats = 1;
queue->printidlestats = 1;
queue->printintarrstats = 1;
queue->printsizestats = 1;
queue->priority_mix = 1;
/* queue->base.list = NULL; */
/* queue->timeout.list = NULL; */
/* queue->priority.list = NULL; */
/* queue->base.surfoverforw = FALSE; */
/* queue->timeout.surfoverforw = FALSE; */
/* queue->priority.surfoverforw = FALSE; */
/* queue->base.force_absolute_fcfs = FALSE; */
/* queue->timeout.force_absolute_fcfs = FALSE; */
/* queue->priority.force_absolute_fcfs = FALSE; */
queue->base.sched_alg = FCFS;
queue->cylmaptype = MAP_NONE;
/* queue->writedelay = 0.0; */
/* queue->readdelay = 0.0; */
/* queue->seqscheme = 0; */
/* queue->concatmax = 0; */
/* queue->comboverlaps = 0; */
/* queue->seqstreamdiff = 0; */
/* queue->to_scheme = 0; */
/* queue->to_time = 0; */
queue->timeout.sched_alg = FCFS;
/* queue->pri_scheme = 0; */
queue->priority.sched_alg = FCFS;
return(queue);
}
/* ioqueue contructor using new parser
* returns an allocated and initialized ioqueue on success
* or NULL on failure */
struct ioqueue *disksim_ioqueue_loadparams(struct lp_block *b,
int printqueuestats,
int printcritstats,
int printidlestats,
int printintarrstats,
int printsizestats)
{
ioqueue *result;
result = malloc(sizeof(ioqueue));
bzero(result, sizeof(ioqueue));
result->printqueuestats = printqueuestats;
result->printcritstats = printcritstats;
result->printidlestats = printidlestats;
result->printintarrstats = printintarrstats;
result->printsizestats = printsizestats;
result->priority_mix = 1;
if(b->name) result->name = strdup(b->name);
/* unparse_block(b, outputfile); */
#include "modules/disksim_ioqueue_param.c"
return (struct ioqueue *)result;
}
static void ioqueue_printqueuestats (ioqueue **set, int setsize, char *prefix)
{
int maxlistlen = 0.0;
int maxqlen = 0.0;
int maxreadlen = 0.0;
int maxwritelen = 0.0;
double runlistlen = 0.0;
double runoutstanding = 0.0;
double runreadlen = 0.0;
double runwritelen = 0.0;
int listlen = 0;
int numoutstanding = 0;
int numcomplete = 0;
int i;
statgen ** statset;
statset = (statgen **) DISKSIM_malloc (3*setsize*sizeof(statgen *));
ASSERT (statset != NULL);
for (i=0; i<setsize; i++) {
if (set[i]->printqueuestats == FALSE)
return;
if (set[i]->maxlistlen > maxlistlen)
maxlistlen = set[i]->maxlistlen;
if (set[i]->maxqlen > maxqlen)
maxqlen = set[i]->maxqlen;
if (set[i]->maxreadlen > maxreadlen)
maxreadlen = set[i]->maxreadlen;
if (set[i]->maxwritelen > maxwritelen)
maxwritelen = set[i]->maxwritelen;
numcomplete += set[i]->base.numcomplete + set[i]->timeout.numcomplete + set[i]->priority.numcomplete;
runlistlen += set[i]->base.runlistlen + set[i]->timeout.runlistlen + set[i]->priority.runlistlen;
runoutstanding += set[i]->base.runoutstanding + set[i]->timeout.runoutstanding + set[i]->priority.runoutstanding;
listlen += set[i]->base.listlen + set[i]->timeout.listlen + set[i]->priority.listlen;
numoutstanding += set[i]->base.numoutstanding + set[i]->timeout.numoutstanding + set[i]->priority.numoutstanding;
runreadlen += set[i]->base.runreadlen + set[i]->timeout.runreadlen + set[i]->priority.runreadlen;
}
runwritelen = runlistlen - runreadlen;
fprintf(outputfile, "%srunlistlen: %f\n", prefix, runlistlen);
fprintf(outputfile, "%srunoutstanding: %f\n", prefix, runoutstanding);
fprintf(outputfile, "%ssimtime: %f\n", prefix, simtime);
fprintf(outputfile, "%swarmuptime: %f\n", prefix, warmuptime);
fprintf(outputfile, "%ssetsize: %d\n", prefix, setsize);
fprintf(outputfile, "%sAverage # requests: %f\n", prefix, (runlistlen/((simtime - warmuptime) * (double) setsize)));
fprintf(outputfile, "%sMaximum # requests: %d\n", prefix, maxlistlen);
fprintf(outputfile, "%sEnd # requests: %d\n", prefix, listlen);
fprintf(outputfile, "%sAverage queue length: %f\n", prefix, ((runlistlen - runoutstanding)/((simtime - warmuptime) * (double) setsize)));
fprintf(outputfile, "%sMaximum queue length: %d\n", prefix, maxqlen);
fprintf(outputfile, "%sEnd queued requests: %d\n", prefix, (listlen - numoutstanding));
for (i=0; i<setsize; i++) {
statset[(3*i)] = &set[i]->base.qtimestats;
statset[((3*i)+1)] = &set[i]->priority.qtimestats;
statset[((3*i)+2)] = &set[i]->timeout.qtimestats;
}
stat_print_set(statset, (3*setsize), prefix);
fprintf (outputfile, "%sAvg # read requests: %f\n", prefix, (runreadlen / ((simtime - warmuptime) * (double) setsize)));
fprintf (outputfile, "%sMax # read requests: %d\n", prefix, maxreadlen);
fprintf (outputfile, "%sAvg # write requests: %f\n", prefix, (runwritelen / ((simtime - warmuptime) * (double) setsize)));
fprintf (outputfile, "%sMax # write requests: %d\n", prefix, maxwritelen);
for (i=0; i<setsize; i++) {
statset[(3*i)] = &set[i]->base.accstats;
statset[((3*i)+1)] = &set[i]->priority.accstats;
statset[((3*i)+2)] = &set[i]->timeout.accstats;
}
stat_print_set(statset, (3*setsize), prefix);
free(statset);
}
static void ioqueue_printintarrstats (ioqueue **set, int setsize, char *prefix)
{
int i;
statgen ** statset;
statset = (statgen **) DISKSIM_malloc (setsize*sizeof(statgen *));
ASSERT (statset != NULL);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->intarrstats;
if (set[i]->printidlestats == FALSE) {
return;
}
}
stat_print_set(statset, setsize, prefix);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->readintarrstats;
}
stat_print_set(statset, setsize, prefix);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->writeintarrstats;
}
stat_print_set(statset, setsize, prefix);
free(statset);
}
static void ioqueue_printsizestats (ioqueue **set, int setsize, char *prefix)
{
int i;
statgen ** statset;
statset = (statgen **) DISKSIM_malloc (setsize*sizeof(statgen *));
ASSERT (statset != NULL);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->reqsizestats;
if (set[i]->printsizestats == FALSE) {
return;
}
}
stat_print_set(statset, setsize, prefix);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->readsizestats;
}
stat_print_set(statset, setsize, prefix);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->writesizestats;
}
stat_print_set(statset, setsize, prefix);
free(statset);
}
static void ioqueue_printidlestats (ioqueue **set, int setsize, char *prefix)
{
int i;
statgen ** statset;
statset = (statgen **) DISKSIM_malloc (setsize*sizeof(statgen *));
ASSERT (statset != NULL);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->idlestats;
if (set[i]->printidlestats == FALSE) {
return;
}
}
fprintf (outputfile, "%sNumber of idle periods: %d\n", prefix, stat_get_count_set(statset, setsize));
stat_print_set(statset, setsize, prefix);
free(statset);
}
static void ioqueue_printcritstats (subqueue **set, int setsize, char *prefix, int numreqs)
{
char prefix2[256];
int cnt;
int i;
statgen ** statset;
statset = (statgen **) DISKSIM_malloc (setsize*sizeof(statgen *));
ASSERT (statset != NULL);
/* check for printability is external */
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->critreadstats;
}
cnt = stat_get_count_set(statset, setsize);
fprintf (outputfile, "%sCritical Reads: \t%6d \t%f\n", prefix, cnt, ((double) cnt / (double) max(numreqs,1)));
sprintf(prefix2, "%sCritical Read ", prefix);
stat_print_set(statset, setsize, prefix2);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->nocritreadstats;
}
cnt = stat_get_count_set(statset, setsize);
fprintf (outputfile, "%sNon-Critical Reads: \t%6d \t%f\n", prefix, cnt, ((double) cnt / (double) max(numreqs,1)));
sprintf(prefix2, "%sNon-Critical Read ", prefix);
stat_print_set(statset, setsize, prefix2);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->critwritestats;
}
cnt = stat_get_count_set(statset, setsize);
fprintf (outputfile, "%sCritical Writes: \t%6d \t%f\n", prefix, cnt, ((double) cnt / (double) max(numreqs,1)));
sprintf(prefix2, "%sCritical Write ", prefix);
stat_print_set(statset, setsize, prefix2);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->nocritwritestats;
}
cnt = stat_get_count_set(statset, setsize);
fprintf (outputfile, "%sNon-Critical Writes: \t%6d \t%f\n", prefix, cnt, ((double) cnt / (double) max(numreqs,1)));
sprintf(prefix2, "%sNon-Critical Write ", prefix);
stat_print_set(statset, setsize, prefix2);
free(statset);
}
static void ioqueue_subqueue_printstats (subqueue **set, int setsize, char *prefix, int printcritstats)
{
int numcomplete = 0;
int maxlistlen = 0;
int listlen = 0;
int maxqlen = 0;
int numoutstanding = 0;
int numreqs = 0;
double runlistlen = 0.0;
double runoutstanding = 0.0;
int i;
statgen ** statset;
statset = (statgen **) DISKSIM_malloc (setsize*sizeof(statgen *));
ASSERT (statset != NULL);
for (i=0; i<setsize; i++) {
numreqs += set[i]->numreads + set[i]->numwrites;
numcomplete += set[i]->numcomplete;
runlistlen += set[i]->runlistlen;
runoutstanding += set[i]->runoutstanding;
listlen += set[i]->listlen;
numoutstanding += set[i]->numoutstanding;
if (set[i]->maxqlen > maxqlen) {
maxqlen = set[i]->maxqlen;
}
if (set[i]->maxlistlen > maxlistlen) {
maxlistlen = set[i]->maxlistlen;
}
}
if (maxlistlen == 0) {
return;
}
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->outtimestats;
}
stat_print_set(statset, setsize, prefix);
if (printcritstats) {
ioqueue_printcritstats (set, setsize, prefix, numreqs);
}
fprintf(outputfile, "%sAverage # requests: %f\n", prefix, (runlistlen/((simtime - warmuptime) * (double) setsize)));
fprintf(outputfile, "%sMaximum # requests: %d\n", prefix, maxlistlen);
fprintf(outputfile, "%sEnd # requests: %d\n", prefix, listlen);
fprintf(outputfile, "%sAverage queue length: %f\n", prefix, ((runlistlen - runoutstanding)/((simtime - warmuptime) * (double) setsize)));
fprintf(outputfile, "%sMaximum queue length: %d\n", prefix, maxqlen);
fprintf(outputfile, "%sEnd queued requests: %d\n", prefix, (listlen - numoutstanding));
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->qtimestats;
}
stat_print_set(statset, setsize, prefix);
for (i=0; i<setsize; i++) {
statset[i] = &set[i]->accstats;
}
stat_print_set(statset, setsize, prefix);
free(statset);
}
void ioqueue_printstats (ioqueue **set, int setsize, char *sourcestr)
{
int to_scheme = 0;
int pri_scheme = 0;
int numcomplete = 0;
int i;
int numreads = 0;
int numwrites = 0;
int numreqs = 0;
int seqreads = 0;
int seqwrites = 0;
int printcritstats = 1;
double idletime = 0.0;
int subcheck = 0;
int switches = 0;
int timeouts = 0;
int halfouts = 0;
int overlapscombed = 0;
int readoverlapscombed = 0;
int base_num_sptf_sdf_different = 0;
int timeout_num_sptf_sdf_different = 0;
int priority_num_sptf_sdf_different = 0;
int base_num_scheduling_decisions = 0;
int timeout_num_scheduling_decisions = 0;
int priority_num_scheduling_decisions = 0;
char prefix[80];
subqueue ** subset;
statgen ** statset;
subset = (subqueue **) DISKSIM_malloc (3*setsize*sizeof(subqueue *));
statset = (statgen **) DISKSIM_malloc (3*setsize*sizeof(statgen *));
ASSERT ((subset != NULL) && (statset != NULL));
for (i=0; i<setsize; i++) {
if (set[i]->printqueuestats == FALSE)
return;
if ((set[i]->to_scheme != NOTIMEOUT) || (set[i]->pri_scheme != ALLEQUAL)) {
to_scheme = set[i]->to_scheme;
pri_scheme = set[i]->pri_scheme;
subcheck = 1;
}
statset[(3*i)] = &set[i]->base.outtimestats;
statset[((3*i)+1)] = &set[i]->timeout.outtimestats;
statset[((3*i)+2)] = &set[i]->priority.outtimestats;
printcritstats &= set[i]->printcritstats;
numreads += set[i]->base.numreads + set[i]->timeout.numreads + set[i]->priority.numreads;
/*
numreads -= (set[i]->timeoutreads + set[i]->halfoutreads);
*/
numwrites += set[i]->base.numwrites + set[i]->timeout.numwrites + set[i]->priority.numwrites;
/*
numwrites -= (set[i]->timeouts - set[i]->timeoutreads);
numwrites -= (set[i]->halfouts - set[i]->halfoutreads);
*/
seqreads += set[i]->seqreads;
seqwrites += set[i]->seqwrites;
idletime += stat_get_runval(&set[i]->idlestats);
overlapscombed += set[i]->overlapscombed;
readoverlapscombed += set[i]->readoverlapscombed;
base_num_sptf_sdf_different += set[i]->base.num_sptf_sdf_different;
base_num_scheduling_decisions += set[i]->base.num_scheduling_decisions;
timeout_num_sptf_sdf_different += set[i]->timeout.num_sptf_sdf_different;
timeout_num_scheduling_decisions += set[i]->timeout.num_scheduling_decisions;
priority_num_sptf_sdf_different += set[i]->priority.num_sptf_sdf_different;
priority_num_scheduling_decisions += set[i]->priority.num_scheduling_decisions;
}
numreqs = (double) (numreads + numwrites);
idletime /= (double) setsize;
numcomplete = stat_get_count_set(statset, (3*setsize));
fprintf(outputfile, "%sTotal Requests handled:\t%d\n", sourcestr, numcomplete);
fprintf(outputfile, "%sRequests per second: \t%f\n", sourcestr, ((double)1000 * (double)numcomplete / (simtime - warmuptime)));
fprintf(outputfile, "%sCompletely idle time: \t%f \t%f\n", sourcestr, idletime, (idletime / (simtime - warmuptime)));
stat_print_set(statset, (3*setsize), sourcestr);
fprintf(outputfile, "%sOverlaps combined: \t%d\t%f\n", sourcestr, overlapscombed, ((double) overlapscombed / (double) max(numcomplete,1)));
fprintf(outputfile, "%sRead overlaps combined:\t%d\t%f\t%f\n", sourcestr, readoverlapscombed, ((double) readoverlapscombed / (double) max(overlapscombed,1)), ((double) readoverlapscombed / (double) max(numreads,1)));
if (printcritstats) {
for (i=0; i<setsize; i++) {
subset[(3*i)] = &set[i]->base;
subset[((3*i)+1)] = &set[i]->timeout;
subset[((3*i)+2)] = &set[i]->priority;
}
ioqueue_printcritstats (subset, (3*setsize), sourcestr, numreqs);
}
fprintf(outputfile, "%sNumber of reads: %6d \t%f\n", sourcestr, numreads, ((double) numreads / max(numreqs,1)));
fprintf(outputfile, "%sNumber of writes: %6d \t%f\n", sourcestr, numwrites, ((double) numwrites / max(numreqs,1)));
fprintf(outputfile, "%sSequential reads: %6d \t%f \t%f\n", sourcestr, seqreads, ((double) seqreads / (double) max(numreads,1)), ((double) seqreads / max(numreqs,1)));
fprintf(outputfile, "%sSequential writes: %6d \t%f \t%f\n", sourcestr, seqwrites, ((double) seqwrites / (double) max(numwrites,1)), ((double) seqwrites / max(numreqs,1)));
fprintf(outputfile, "%sBase SPTF/SDF Different: %6d / %6d \t%f\n",
sourcestr, base_num_sptf_sdf_different, base_num_scheduling_decisions,
((double) base_num_sptf_sdf_different / (double) max(base_num_scheduling_decisions, 1)));
fprintf(outputfile, "%sTimeout SPTF/SDF Different: %6d / %6d \t%f\n",
sourcestr, timeout_num_sptf_sdf_different, timeout_num_scheduling_decisions,
((double) timeout_num_sptf_sdf_different / (double) max(timeout_num_scheduling_decisions, 1)));
fprintf(outputfile, "%sPriority SPTF/SDF Different: %6d / %6d \t%f\n",
sourcestr, priority_num_sptf_sdf_different, priority_num_scheduling_decisions,
((double) priority_num_sptf_sdf_different / (double) max(priority_num_scheduling_decisions, 1)));
ioqueue_printqueuestats(set, setsize, sourcestr);
ioqueue_printintarrstats(set, setsize, sourcestr);
ioqueue_printidlestats(set, setsize, sourcestr);
ioqueue_printsizestats(set, setsize, sourcestr);
for (i=0; i<setsize; i++) {
statset[(3*i)] = &set[i]->base.instqueuelen;
statset[((3*i)+1)] = &set[i]->timeout.instqueuelen;
statset[((3*i)+2)] = &set[i]->priority.instqueuelen;
}
stat_print_set(statset, (3*setsize), sourcestr);
for (i=0; i<setsize; i++) {
statset[(3*i)] = &set[i]->base.infopenalty;
statset[((3*i)+1)] = &set[i]->timeout.infopenalty;
statset[((3*i)+2)] = &set[i]->priority.infopenalty;
}
stat_print_set(statset, (3*setsize), sourcestr);
if (subcheck) {
fprintf (outputfile, "%sBase queue statistics\n", sourcestr);
for (i=0; i<setsize; i++) {
subset[i] = &set[i]->base;
}
sprintf(prefix, "%sbase ", sourcestr);
ioqueue_subqueue_printstats(subset, setsize, prefix, printcritstats);
if (to_scheme != NOTIMEOUT) {
fprintf (outputfile, "%sTimeout queue statistics\n", sourcestr);
switches = 0;
for (i=0; i<setsize; i++) {
subset[i] = &set[i]->timeout;
switches += set[i]->timeout.switches;
timeouts += set[i]->timeouts;
halfouts += set[i]->halfouts;
}
sprintf(prefix, "%stimeout ", sourcestr);
fprintf (outputfile, "%sRequests switched to timeout queue: %d\n", sourcestr, switches);
fprintf(outputfile, "%sTimed out requests: %d\n", sourcestr, timeouts);
fprintf(outputfile, "%sHalfway timed out requests: %d\n", sourcestr, halfouts);
ioqueue_subqueue_printstats(subset, setsize, prefix, printcritstats);
}
if (pri_scheme != ALLEQUAL) {
fprintf(outputfile, "%sPriority queue statistics\n", sourcestr);
switches = 0;
for (i=0; i<setsize; i++) {
subset[i] = &set[i]->priority;
switches += set[i]->priority.switches;
}
sprintf(prefix, "%spriority ", sourcestr);
fprintf (outputfile, "%sRequests switched to priority queue: %d\n", sourcestr, switches);
ioqueue_subqueue_printstats(subset, setsize, prefix, printcritstats);
}
}
free(subset);
free(statset);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wjh731/disksim_original.git
git@gitee.com:wjh731/disksim_original.git
wjh731
disksim_original
disksim_original
master

搜索帮助