From 9192ca5ea078d6412af8ddc133aeea8770ec2c0a Mon Sep 17 00:00:00 2001 From: rissadmin <floreal.risso@univ-tlse3.fr> Date: Sun, 18 Dec 2022 08:44:31 +0000 Subject: [PATCH 001/125] Refactored project tree --- .gitignore | 3 + makefile | 53 ++++++++++++------ mojitos | Bin 37696 -> 0 bytes counters.h => src/counters.h | 0 counters_group.c => src/counters_group.c | 0 .../counters_individual.c | 0 counters_option.py => src/counters_option.py | 0 frapl.c => src/frapl.c | 0 frapl.h => src/frapl.h | 0 infiniband.c => src/infiniband.c | 0 infiniband.h => src/infiniband.h | 0 load.c => src/load.c | 0 load.h => src/load.h | 0 mojitos.c => src/mojitos.c | 0 network.c => src/network.c | 0 network.h => src/network.h | 0 rapl.c => src/rapl.c | 0 rapl.h => src/rapl.h | 0 temperature.c => src/temperature.c | 0 temperature.h => src/temperature.h | 0 20 files changed, 40 insertions(+), 16 deletions(-) delete mode 100755 mojitos rename counters.h => src/counters.h (100%) rename counters_group.c => src/counters_group.c (100%) rename counters_individual.c => src/counters_individual.c (100%) rename counters_option.py => src/counters_option.py (100%) rename frapl.c => src/frapl.c (100%) rename frapl.h => src/frapl.h (100%) rename infiniband.c => src/infiniband.c (100%) rename infiniband.h => src/infiniband.h (100%) rename load.c => src/load.c (100%) rename load.h => src/load.h (100%) rename mojitos.c => src/mojitos.c (100%) rename network.c => src/network.c (100%) rename network.h => src/network.h (100%) rename rapl.c => src/rapl.c (100%) rename rapl.h => src/rapl.h (100%) rename temperature.c => src/temperature.c (100%) rename temperature.h => src/temperature.h (100%) diff --git a/.gitignore b/.gitignore index 5761abc..f5893ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *.o +src/counters_option.h +bin +obj diff --git a/makefile b/makefile index 433b76f..064dfca 100644 --- a/makefile +++ b/makefile @@ -1,30 +1,51 @@ +.PHONY: all clean mojitos mojitos_group debug format + +SRC_DIR = src +OBJ_DIR = obj +BIN_DIR = bin + +OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters_individual.o rapl.o frapl.o network.o load.o infiniband.o temperature.o) +OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) + +CC = gcc +CFLAGS = -std=gnu99 -O3 -Wall # -Wextra -Werror -Wpedantic + +ASTYLE = astyle --style=gnu -s2 -k3 -n -Z -Q + + +# depending on the context it may need to be changed to all: mojitos mojitos_group all: mojitos -OBJECTS = mojitos.o counters_individual.o rapl.o frapl.o network.o load.o infiniband.o temperature.o +mojitos: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS) + $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos $(OBJECTS) -lpowercap -mojitos:$(OBJECTS) - gcc $(DEBUG) -O3 -Wall -o mojitos $(OBJECTS) -lpowercap +mojitos_group: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS_GRP) $(SRC_DIR)/counters_option.h + $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos_group $(OBJECTS_GRP) -lpowercap -OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) -mojitos_group: $(OBJECTS_GRP) counters_option.h - gcc $(DEBUG) -O3 -Wall -o mojitos_group $(OBJECTS_GRP) -lpowercap +$(OBJ_DIR)/counters_%.o: $(SRC_DIR)/counters_%.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h + $(CC) $(CFLAGS) -c $< -o $@ -counters_%.o: counters_%.c counters.h counters_option.h - gcc $(DEBUG) -c -O3 -Wall $< -o $@ +$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.py + python3 ./$(SRC_DIR)/counters_option.py > $(SRC_DIR)/counters_option.h -counters_option.h: counters_option.py - ./counters_option.py > counters_option.h +$(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h + $(CC) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(SRC_DIR)/%.h + $(CC) $(CFLAGS) -c $< -o $@ -mojitos.o: mojitos.c counters_option.h - gcc $(DEBUG) -c -O3 -Wall $< -o $@ +$(OBJ_DIR): + mkdir -p $(OBJ_DIR) -debug: DEBUG = -DDEBUG -g +$(BIN_DIR): + mkdir -p $(BIN_DIR) +debug: CFLAGS += -DDEBUG -g debug: all -%.o : %.c %.h - gcc $(DEBUG) -c -O3 -Wall $< -o $@ +format: + $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h clean: - \rm -f *~ *.o mojitos_group mojitos counters_option.h + \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* + \rm -f $(SRC_DIR)/counters_option.h diff --git a/mojitos b/mojitos deleted file mode 100755 index ab3f7b4824740935e193e4d9efee35d0f20849fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37696 zcmb<-^>JfjWMqH=W(GS35HCR!BH{p{7#zBx3<d@U2L=lUUIqsS1qOKrHU<U;7O)sZ z9<Cn3Ww^lvVZdk(2$z8ws!syMU|?WCr)8k(U^K{0AR!P9vJb?@hJQ#xL}4_80E7?H z#|mO9fCvT#1~fVn>R%X*tPgBo08}3u9Uuk~htbITKw)zs4I+P`43*x%4dMTgg3vI1 zpx^@Q%Y}$vs70kefIPy$zyPCR;R$jh2wOnI6P-r$E(5y02&g`E+67`g1B?dQ0TK#+ zT9N`{quT@H<FYRRs?Q)AWC{ZVI^6>GAB+as0a6+Gv?K)-E+95B7#i&iK~Vc}#e)GS z#55QUwVpvgCo{>+L_a4*HzzZ%v_iMS!c5o9M6Wns&j_pm<SvjMpfu&~7s|lYz;FO0 z2Gb8>i!d;N(>X|<LwDAcaM7TH>#eRm%;_wd(0cP_BS;O%43Hj>8j!)DXaJ=F5F3O+ zd}9U%aGnJFpRtjFfl-19BxcIMz+lF}z@Q=9BXcqJT(0G(ZW-ev--ST>aN!q>3=G&5 zfZPC!Gi1Fd7_h7VghRXshxxuZ#3gZv&&DBMgTvm{IK&ljn3IG<JOhWg9}aN`9O8#? zh@ZnDUW!9p2#5G_9OAEWgu^Tx>NnyLmqjWfk<$Y=4)tz0#Eo%?hu{!Dh{OGVaEQC% z5Z{Tz{2MsbU&kT-1cx{a4)Y)25ZA#W9*e{LJRIuZ;t)TGLtGt)_<0=me#N1_6^FPE zj&#zG!~E|!#OrXFZ^_8OAjlxi(9i@)g|K>S5hDYG5=01vjE1UTfTsQ~1H_yTs5q$X z1#67=4DpRmNi9lE&nzxUEei2<&dJY94M|MONo9zSPtVQIi!UxoEGmhQX8<e3s<0rx zJhdn}u^_%Eu^=ZtJ+&l0FEKZj0gG^HZhS#va&}^RYB8F0W?p6qnh?mK)V$Q9^vd|s zEHt^4)Z&t&{7Qzjw4Bo742I&8qU3@~hT?*v%)F8`hP3>G)I5g#f|AU<6o!J-qN4mF zhT_chyu=)ag3^*=hP3>mY=)xL#GIV`WRTvH{A>u7!;lOY%t_5-$W6^HPAy?b&&f|> zNKY-vFDPLsNGvT*WhgF5$uBKoNGm8UNd~C`*`Ai1lV6<5kP9;*CAFxCAu~U@B!?k0 zFD12tA+;hkxvT(UQ)x~PLuqkNYH9&PT6s}sNh(8fPJVJWDD+A)b5j}8pk9fOPp(Le zPs_|p%*m`uWhkyJ2Dy--IJKlKsWgqDpeQvl1!Q7!ZUIAld`@OkGBm<+6EpL`%JcKm z7}APTLGcMPDzPNBBC~`cCo>5aKcH&e03?tMVwo|x`*=Dz#~bMxnZuceCI}`%)JP9h z2Qx7+GB7bPF))Kk5D&r!iD6=p91Bz>NG+-gkSs`q6{>;}YBop=gc%uF7`T}jV9iB_ z_KDNj7#LU?M4@6+z<d@41t@<yn9t0h4ds_gWpXkwFfo`x8yT>6DJ)+(Xn}JD!wqPA z6(-IA6@P#x?i>P9{{u~25-KiG4v~kM^CcL<*FY0zg{pTz6BmMtN1%zTLB$Ku#7&^$ z9cbeAQ1Jz5;(k!^9cbb)Q1J_B;#pAf7ii)YP;rI|i2q>zZG(zSpovd`iW{JbFM^7D zpoy=CiYK6n?}3U}poyP^icdfjzXlawfhPVKDt-V>`~y_{2AcSPsQ3poalTNf|0|(1 zgkq3|iYuUr>p;aV(8R5w;sI#lUQqE2H1SBNcmtYv22^|ons_->d;^+z8&v!Rn)p<x z_yaWYB~bAnXyTio;sRBW0Dz^315j}dH1Ts#aR)T<J5ccmH1StZ@d7mQA5ifQG;#JY zh&vXbiHkwScc6)@Ld7qjiJL&hU!aLQL&X`YA@;!h8w3@XKod`aiW{JbmqEon(8N2S z;t6Qtv!LP?XyR+2;uFxs_d&&1pow3BiXT7|e+3o4fhNun4)Ny)G;uMgI0vYs!oUFU zXX`-470|?;pyC#2;!#lX05tI;sCWjNco$T>0Zn`nRD1@S_%5jU1~l<YQ1KIJ;&-6p z575M)L&blfiGPNQ3qZ#&VCjJ+0upW-XyU?9aR)SUWvF-rnz%7kyZ}wy1uEWwCLRhE zUw|ea4He&kCY}ZrU(pD0FU<Wg{sA=c+9-&+6KLX1Q1J_B;_XoJ8))J^P;mxmI~8W{ z&q#>*9BAU&Q1t?6;{TxPCD6oKq3RXT#JQm28ffC8P;mn^aY3lK1)8`dRNMhgTplX! zfhMjB6;D7DuYrnZpoup^#S75H+o0kVXyV;a@dNdc@B@vZK$|{bffGpLf?yE{aREtO z0wM$^Zy<^5gGC_310-=1h!B{B^;<yWM4&Mnupk2i1FRnc5(kapz{Fww7LYioZ3z>X zXn?TTp<_W19s`2{k~nCr2qvz9Bo6QEFfcF}Ac=$QfT_1Y5(kA5OxyuU9Ar04+yhA* zmPSEx0Z8J|p*4^&Lj;mI7gz*BBp``HheW{=8A#$hU=avWfF#Zf5dxDHNaB285eU(M zB+d^J0+Ss`;-E1&upk2i!vrL8<Z-eYNaDgU#S9D#3y{P?<9#rx6-eTuFhK?eh7CyK z(4k|n><%Pxaj*!4IDjM$9ohy<oInzX4IzUhE+C0Zg9M=X29h{zOdTZk07)D)<^vJ~ z;TK5aav%XH{(vMd4;2GZKaj*x#u1_A8z}84f)qkA2a-5)KVASyTp6ksL`fittAGTc zSOG~~6)FazG?2vAKmt%~fF!OC6$4QgNa7kG0VsAr5{FI^fMq<8#Gzdyuy_EHxHeb> zLPQ{mgT_oCq6`cPNaDIMK?Vkf3?y+qB=G_yaRVgr3M6quB=H6$amdIulH@3JGz3ON zU^E0qLtw;)fJgHi4v%iuqwx$39<2vTnEqezXg<Pm7#<$~O&`TGF#K1263@WEFYmzc zUlqj90Lj06@c;k+|Ejm*85lsbW(+Scfccj|d{7hn<pD7N6o?OMn!els<{tv_K~2(^ z3&8wcAU>!m`f>u8zX`+#H9=oCfcdLHd{Fb@WdWGK2*d|9IbSA#`LjTLP*d||0GK}s z#0NDoUpj#KT_8TFY5CFs%x?nmK~2h+3SfQ}h!1K?z7zoSi$Hu(6Y?bkn4bmWgPM*n zKl}svHwnZCH5p$%0P~|jd{Ecn<pnT52*d|99bX;*^SwZPP?PcH1~A_V#0NDMUoHUi ztw4NG6Y=E)Fy9Eo2Q>{}Hh}qBAU>!`__6@ZR|4@tU6PjxV7?TH4{92|3;^?mKzvY> z@TCKo&jsRxnu0G4z<eeUAJhbVsQ~8xieq5N05$zy3V`{aKzvY>?<E76{|dwhHT7P8 z_zUv?BM=|d#C!Pw%)bTVgPL|PFM#=%KzvY>?&Se6{}hN1YRbLb0OlV8@j*?vmkYrB zT_8TF>GpC0n7;|c2Q}GVHh}r7KzvYB?PUR&zX-$!HPK!sfcdjPd{EQuWdN8z3B(6A z$zD2u`CTABs44c+0L*U!@j*?nmkMBh6^IXNdc70?^H0SvFr-ZYC2$aS40jB340Q|% z_2~Q>?9u$jqxnB0e~TO&1A|95t9?8JgJb6(k6v3<b_NDl!~c%^KuN}@SNFU=1A|Ae zESmuXgGVQ8eLMrhi%Y5?A=B4v3=I20$?3(#zyJRqcTwR1O}!s?Q2`|>hT|?O93Xxg zzkCbGdIq1)S00`3Tsoh>SoH7z|K=b6`CEQ7GBEhI{^xJ~#K^$V{36-a@PG3UA^!GG zRt5%-WR_+R#vA`1`1G=Vlm%JHn<dS_VEE0|@V`f|=sU2GZMhT!!wVyJ28P!QJd#-( z;}{rrfijHYH;?X`qYN)H{{H{J3*?ICAB>VGLB=0sY(2p5dZE)tMW8c8h2v$~|NsAe zdRh02fNhu|jIg0b6eMK(Re*uv#RWD7hL_g=|Nr+$W|fI!VDRZ>_2mYKlSeOaF+WJ5 zsEz<ABukDmc=Xyb@G&sFm<`gz2GR697No|sUJs%P?6~N^|Nnb*vg*V!Fuc6~@Be?p z121;4GcXwbfAJ9{lgzp)7HpHV1VmFWuctW36wyU;2%Fku85mv|f^3@e5A3|!Sa=wK zLJDkC;-CNjJ6%+GURFTVL_%C6#md02AC%vHdO?B3{pbJxmthbU<`An-h{LQtCkD3q zJIDpy5KnrGGBCW@#>&9(Qt=-+5VMp(YIr{@A_8$cSjhH(0t3T~ZjjP%fB*k?HT?GS z9mtE_w)(LkwL3v;m<->7W6GmfwoI3S;f3s<|NnP^3OkQ(Ud~tshJB!D^yszq1xY^m z^Z$Rd?a3Gh28I%SetB?@&7+%jV+<%@Y;S?6&U+r+A}<UNcr+hneBto>|9?x}SuqR@ z<u_bgzwx(xW&)`+-4MgTupg9QUhMnz|9`iO3J3ps7ZsjP7Zs7#1N?oUB_JNhT~t72 z6ocVgpWYM|1CL(W_c{y=E}bPR9Q^Vw3=I204)f`J<_b!hZ(m&f`Tu{nt$z#yL+k$% zbAEYH?y`&lX?W$;ZSujRo0S>lyk46N9^I@GF$@e&|3yA{HXmbjWIXC(X(|SC;~7w< zXaP+CzYzQL|9|TN{+1Lb28I_qfBpaO(OaUT0Jif**3bX{J-U5VG(5UpR4hC!5Ayev zGlKkOdm|b|g{UZaXdW~?;GrD?a<{3D4g<prQ;<hR`=db-`?mE`i6Jb1dUUg9g0<Ps z0#Tj!yujh-2?{@kU;qERSn5VbGcc522L%(zNv|0|mYC*5!@{uY=l}n{t^Z3Sklc9e z$N&F39Gv(Wzz&`Hy+(zn^SH;3^WTFXFP(iv!Q=Z&kApw$JvuLV9Q?uVp?Sh1`Mk$W zkMBP<ufNd#{r^96j*5U~j*19>|5Q*8x!r901vCs+qMJ6sqnq_%6vzcOH$1vok3}&s z{1>^=&3Y9i)_j=J@<#dH)&u;lpk+TE%||>84@Ad0#yG}0#yQ3x2G#%FB`O>sM_IIf zD=GEp1_e>K?R=2#UQ;G*1_r|eFF1ex|Nrv*zyJS1>Oo2*Ji2XbAWGhAft5V_@&EtJ zZ~y-Pp8%3q@Mt{9aB7w{EW~$dfgEV-3DTl@(4+Ykqv3%Un?YJCLHP_3mGi%YqS6Hv zl|G=TJW<Q$!3s7>^MpsIi;Bd{C{RJtZTl>ef#HQCShejX5Ze^O-Uec8LfDHyY*`3< zABZjZ{r~@$-$6EZ^X`pgVAus}WWX{Mj}`;Ni++$#U;p|4-?Q7^r}N(n`Jey)8~%Th z0ZL(=?_U@&GB6mv_3XSD=h6Adqxs2)fDoTv)?M=8{2mOZZ0G#^|Np<JT^Iwy7jVAt z=(T+r0aC#F2t--_C=vDOW(CdCfSPBV{~ti}?O`bG(QCUCq_Ed?6Nu9M=h6AW<KR1c zkApv$Js6L9T>Mue;?d3eHWbpn<M{s|4Qvlg|7U)=Uk$c%L8INJ+MyoJwx>W7NFJR} zOL#oGZQH^b7+$>m@&Esel>h(#A7d?zU|?X3J<Ko9fUN&z`F~JkgUge{X=!?}yaA5? z<~JOM|6hdu0I6_cV1TqYZF3_S7+yF)0y`1p@a7{NFCTpU{~sc6Zg{|>*EU0yf#Jn# zkYKOv7Z7_sge{=P!0=)+gdM2C!0@6S!qxzZS3}q?Aa*{4y#mBehOn=I*x?YihB^bo z3vUR!2E?|9uvdWC#t`-q5L^8#I9?}w|Np<6byYY6gJYOy=Qqbt&(6Od-L?}!0wKKx zjGmomLVY@q277c~?lf%<XJGI+_>B2Q*0=xvyG2XF85n#zzk77DCWSLFG{0i>=ry_E z`2Q-XNC0KFZqp!;hHhJHkZGMq!CLh}T1_n>5>g<llT|vLfuT3-KS<uEQ{}=7Zjc&L zQIKS}?XxgYk@?P}ll4s)0|T?^y)cMf2cI!}bn0Aqaqlb0Eib~rt&*K#3=F+q|2?`z z&w~WIO-^--t_87rZ7%%3?9%zpquaI@Y|M0!D9A7KzW)Co?ZT+r7RJC3>lowF$(j?! zzyK;9VCkWowF{)U+qN2Hdcprr(<%@jq&X3!Io6|-H36gtT&NtL5E|^!D;w?wO7W{d zfLc|}Z#cl|rrX-1`LM)`HJ|_g_pp3j`X1CRiH<$&81C8m9~%6QA)cLALOqgS27C0{ ztOYffK&j`&%`c$x-sUYxz_XLxqx0~KV_*LN_v~bAeOqT_c*&#J_L(OG10)}KCi6`3 z=;iVB=;b-@(OoFe?aATMX>y^HXR=50Ax00&tEG1#Hp5FnlmyNIY9IRanr5moFo4p- zRgjy$go0X%9LGVO7zUrtZyv`%-64h-2f(g44$8;{usq_?s~hRbz+ia$wIDcOHXmm6 zXg(^@{M)M}#iP5H0aUEa`27EW>w(fIj@>LOp53(!%?B7AJ6TjbW_a|Pw1Ry3f(>MH zvWSY|f1l28o}I1?oiP*sya)h^c7p6Hoq_HNxc%L>Geba0^Or}jX*#5I_W1n&Kcudl z_vQb8O#g!0!<~QkgO&gUdo;e;0jknEOH>3rIzv<>Uc3ZFS#OAn!%k2y>bQ%F38-Z7 z=)CUHc^K55GCc6vWA%Pe3;vjkN(AEz&Cmb;r}5_<PUFuz+j%>UKk1-n=aDr2YYZOA zM?HFNj)Hs$D$NyM{Qm@sMi&(hkIq9Ly)1JfGAt^sZ~6NcfgKT}qTy=z&8Ig<#lW-k zI=CI-q9WkYZKLAVtMe74-l>~qL#K<10jTzu@aksy05aO*#gb3||9f|`eD8Kq;b}ck z;^EU>qoQGWdxGHs$DN?grsED!%f9pGE)eC@`EI`!BLl+=y-%PL>&O2R8_(_#P{qij z)yXo`qxmqSkLB;u!=9bjJ)4g)`dF8!DDbxyg6g8iBcRao>3o1xuX^;_YO63XyqEwo zt=pC}7*zd*s91msK~qJL%(joP7~ug07NUrq;27#^_!itf`3p{T-Qg^)m+AuH{fBN> z2ESeva9%LH-Fl!-0akBxyK;DSvnX`i%m6v}#gh;J|69f~)Iay=cI5!IUc9<(6khOs z0JUIpS?YIqbk}mc`2QYM-_{De_y%D}ym$*?D7<(AVl*G&@aTLG@!88u@BjZ#o6zmf z(t4mS6T_M8tq1Bn_~nrt2g#2h>kTjMV^CpWfI1J<7(LARLixl0|J|+(mN)9}IQE7z zT86UJf!*19pnf+ZaUVvnf5^0-8N>d?@5!<sR6c<73n+Fpy2DvKKuzG*OZ<JH3FmHh zP-zBkQ-IQ}MA`&+!`ZJ_<?E0Cpp0LaYIxi5Ei~RdyWKf<ffA%o=R0Tsz3>2sJ*aC4 z+N9yw%?^rD59S;d3CkPx=Nv(ncKfJscy;D{{NZBxsg4blC|^(YXg;C=i7RmH4wNA{ zypFqk_yNi$Aa(aTFSuxaXnw)yXnD;y`I}EK%TbWcJ3xdFzwZIC4v;B^-=br^dTl;9 z#`ts|0@VhN@h_9#fzk@EO#lPKF3@NQ*pnW;wmFIn3@^eyz|ynL2b2<K0;qid4()P- zgACLv7V+o}QIUWL&5L$Wi#|C=MZ}{!MnwWv`1|zgfYZ5W=erkI-~IpZ)A`=B^T>-+ zAcyptes*SH@a#Nbc%b!dogN|sc_fQ8d-RF~dGv~0^XT>x=nmrW?BqG%*eTND(R_f> z!}3Mx9iPr;KAneLI=}mLx~Oox`1uQD_H&QUqc7gQ0eP}Uh2zB&5UVp*!Kd^6iwKD2 z9-XcNAP0DY9MI`1(d`P#3gO+Z46cT6TMyKEg6cU$<|LH<-=d^H>rj?jc>4G0P8IO! zeCE;l{zcDUP!XvQiWQg64@l7qO+S!vjLzR4o$o=FrAK#}#EXc(|NnP~vUqftN_ceF z3bbCTOY-P-=kTyR?9uDS!9Vq&hvi}ZsRvpPmL&E%{crxkSQgoN(eS{<mmUWnvOvxK z%%9J~_L)DQhdqt|_d$L^7G{s;0|FkFCrY1oUTA*s@7p0pP>Yi1n1?pcagR=(!yd_( zJPtl$e!&g)7Yif{AD-aYdBN}ixZFlk+I)b~)AB&+>({3ycqIF=w4SWf^yzj}0GE%_ zPN0EF2G3-X25>xfi(K>Q6gduwyo06B4<q6l6yDu#pyJ&VR89W@hlSy7aJ}o%?JD8Z z`N*^R2uHWc43BPCg>Dvb$>`C`(%{i+)8KLNIg1B#EyIgdZ$Tv`Px)C;;9`_Fj^X<) z7(fj~Xr^y`0~*f(WqOGh4sSpe-TMQ_9YDj644$3G`2`&$Ufg{1|G#6WI|ryKsK>;> z(0Rb{t>JBCdtb1<0mUl2N9VEEoRD<l*=_E@_|EWB=lvHqUx7*q{?<E;3=EFl?i`>d zMB~v3j0_BxH_ESj9(M<iEE(Pgb;K1wmS{49f($ag)Oo|F*Hm2@)cykbQ>Ve>;8PZl zP8}83Zaq-7xif_U)H-<N$!zb^`R>Kq*I>K)K$Wsb?-~`*I9caSpUy|%xHteBx9EKT zA{^wSZg(Ef?s|dV0!GKqavo57^+o(^(Adp;&rWv%P^~NQ;@`{v{~f!_c|3Y67&}W; zcwWf9{{O$bM1=>`EfnzVJmA?~FVX7;YV9)lbg~=*%Y!s{cGoL-cDhS=9DK&~f&*;q zJI_vc1;=i8p5B1}p55-CO8>%(Sg-{!F$tGWoe2mf3Y{_&Je!ZPc=WOwDlss4S{~zX zW&QvEfAe8RN6UB){&vv#l52N9&wfyeXL#GE^PO+!n-@P{g7W`6u%KtBy9THrc={3) zLGA{wt#3=LK<Ui0+g-w=^OZ;QQBZpF>~_bNo;;cDUqrwD|KGJcoyXDgPWdTNi7MgK zY2nd$1e9!C(3=T*pu#ir)&Kwd|NsC0|Hc1Tpq8%f4bV7I@T>p-o6rA$@%j}?feKEB z(6LL7ZdV?U?lJ>V8u-EhDh~g6c76qA00#z0`hVpKaWCHV{|Z!E@L1j|KizrJqr23= zqq|nar<dg{sM=_~RFViPG(0Vj^g8`_<ez%5`3EEa^aGA92TM{wg^H);k&<Xc=`jJd z+;HR<WMP3798bUnNAn}b5<ZU^9^E3xJhVlQdv=N(@##GD;>rt9amWKHHb8Cj!;pMo zcmP5ptA~{ZuU{XX0CKFW;epq?q2(5|>C_$0(R!)G1e8fs|I33r2ax>X(aSO$CHq%D z2jzg$a!?&>8Ou?AuiF(=qR4`R5!Ao!b_J!p8zAWy=bu4}idUdw^~J$wpvt0_;l&OJ zL*m7H2t(n;G6+NC#asx(;Kh_@|NlpObiR*ujCtAd4AgmsxW}jSIoRlw7a*fK_}ioZ z|NsB8;y<Wl0gbD9bpGnD<7xe0lJC*&C*aZR$l+mmsKm3^{eSZhrZUIQe})GxzVkTv zj0Ng{Q1~<Q3$idlLj6POyUriY5B@bjXDrbLg*wkck4~OLpumOLj|g9rgC3nGhah2l zy!1Ut3CRDg-%64}J)ys#BKAvYu;Fcw#y1_{#`#mnZksuVCwGCCN_lj?dm-@R|9{xP zbLaaP6Q6<dkjq^LkOw`Qf3uXH_h>u<(z*jQT?8s_9YJFcpxy+7;eo^8a@+8LN9%w7 zmQYaH7mm~~{1Xc5nap5eU}&(9@abKnvVehsfxqP{$RWL~d7!c2US4}S28R6s4502; zng@U02@rA6qnCBQ94K=<Pvg%y=+VoYDaXJ7lDWXI$)W;c98BZSImEB&q9X7j7ZhKe zM?Jeu;(a<F`E<TFJn$m&`Tzfh-ym#Ie0I9XI(Rf6X7OnLEl_&Zvr`Y0%2HGmx@%+| zprPT@`RoPLb9iX@bUuI4{1jAHy2OG)1ELia8XylLg$B6c1`daYdPWBRR>l7yt37&c zndKN5UMM{K|9{tWW>ES4uJd^3(HHVhK_%Dwec-X%M^FC$-v=7f^65=r1lf4;$^ZYI z?~gGsytw}4|Noa)|AE@?=<R98FrVHs1!x3AD^QQ-BMqLNPtg2h1hO4u6DTa6zu5c) z;vWTgP@MPZ4dw9ZeBq&a!K3+yLRrXX{(M)3&;0qZ3~Bto4?FS;x-x)-3_kPcrwXL; z|2_f|68OxY@2da~1AakYhR=@t`C$V5f}sK)&2JhYX~Z!Olo%oD6;zUWXuC3iI>jE{ zt{NWNt{k47t{fiSt_B|3paz<&fJe8hg@?AQglDI##Onp9{augN|0UXvAwIq70ihn9 ze}g@G;~l_56D%(_KK}pT$MSLM2UtFR@aX@4^zicNWlaQS3(MmrGHLwztUfLb4E%!Z zY5e)TfncV;0C-&0qnp(bq^^_I2tpY{C=&=}>cRjTa&usC3^P2r>pwGOwBc{Jt&9r; z1E>t^)irWuU<d|ftDR5&|L5Pvs^kiq9Wt=t<ZlCIxE-JY_p}N8+e%m&IuC=gZEx6x zhF_fJZ+&}H1K|BdpXATbEa}x-W6JR2&m&N#bY*bj-{xY<(EP%{hO=C**O}2{2Be(j z-{u21FA!v2*;`N@(tMcF*YZv2MtFo6-hMqDR4+P)8GiHVwJiosN*#byPQAM2E({F8 zFA5+3{}1(?M<*!3vf4W{FuZv680?*37r1voV;*4d@XIq`@sCfhZkq=K1K3*=(EX!B zp?`LOQZ#f({IKEe*OO3^ivxpWIMfTEK8#PV?i^=O{CIZ$@#%aA85Zic&2VC1cp(h& zR*f^<Tl!243{Y=5FgRj*?2S*asjoW&gJ*9Za(w-U#+P?*jV;3qpNF9MVsqx-=3)zt zE(LIOLCbqb%m{nq*?bJtX!NvvSGvKYm-V9?s4aAazvT|3uyh33X?cXd<qQL;V$5ef z;Rd3AvnseVFo0@o6;Q%H3>B1y2)d{UfJFB~MMYtv3Lw$#P*HxEr~ycHBUF?VCh7pn zCDCBfe9>e#1_p58r}5{@ra=T%^B}ZtnHvKGzb0=#m=c`<reqg_Db-bAN_VpxXz=+6 z2P{Q8#vk_RX8r5Rz~G_H8V2$*Xh^M_^)p1o2P^^_YU*Zv0TFV93JG|0v)+XWnL&jl zJi1vgL4>rSLJA(;tj8fj3Q!>pk8ajI5Ft^hkO64^4I;z^6|(T?W?cpm`tJ&=hg?(~ zJi1wDLxjFSg*;w@8mET0Uq1hf(%$Q~<#J$Pcqw`x)MNma9lflI4h#$)md8t6K!MET z055+8!AyTpJc){e+2Nqrk(C6q<3VwvDhp<(I~+!g7qXtT2M-^gf>5U+)ENkM7DAna zQ0F1k1qgK!LS2GTm+cuC4yR23*WRE_p`d{hPtc$`s5Ao=w2f~xV6}IOibAPAsD>-m zG`s{ZKdy>{YPE+i?%x0ZA2dKzqoTmT-!dDNV7tNdK^h*ttSO*rSIGP?wpu=092B~+ zTHZq(cP-z350t6EwY*2?E1%Bih6i30gKYi=VQ;?&>cJsb^H+R3^*nn^9YDhYFTef& z53a8~8jpaygp>l)CKw(-t})Ukc=WPfw1dPKxW3q92am6VU?!rzSO`+r$+`$aErw7_ zAk<PjSbY&<cp$X%YOqJ=XTxtV_`nW5(){CpiLyuXRgcbloyT8r-UTl#D3SD-;nMls z)$qwN7G{PQm+$=l5AA;(cIkZXxCh+h*n8*y|JN^&$~@$jKyMVINAhitgO8aZLkspE zo%dd3-v!nC??Lr1XfTB54yemg!T7=$EdI{3(?#Y7s1@(gc^ncjFIV0MH)bLAw_~{B z0Z>uuxEEA^fhuBEPEQ5~P|L%k*Yt-dsLtz^{RWyqXnv#7E&9fXfuXZTg~y}w{)-ED z|Nr+%{@~TiV(ih$q5^Iwb%&_%xOBes=rz403Yv-pHGEcp)O9{L{APII#hW|-|92j5 z1`VdEgJ*?JRCa;7z@4Dh-u>JE|997@2!N%T!O}b`9y5G;ZA-mCGsEAGu`n{cn0fpE z|JUNs^45l{l*REFI|FFQ&9nJ9BgkDGw?Peu4`srR{M*=V6iRP99%GMxeHY?BP;;b~ zp*MgLIzZylc?~kGt^^9X&ifvnt_+aQ^TAutpnP!~)UogZjdO#B$vW?ObRPHUbP@dV zBJS4z|4<);Iu5<2tYA+&HXmhtvFQ$|2PFU+*zGM~^ho{&?o00hnUx$W0B*E-fEr4@ zA`=V`fSe%k;yg&QJ48jGld0KNfbr$}fB*l#Sas|F|7O-=Zw3ZN(5Mq65}^%KP<^-` zv<|>A%yVCIeo<;kYHk6j*7xaEb#i532sL~Qn*T9(29?ckEI`8~9H4<vffpj+MDYHA z;U%BWcl?43pt7q#1eEEYgW~eI19(uwV~2i5d2W85Y6>Vw6n3P7YN$>Z6&=F^$6Zu3 z^z#yPA?@^|pg0lbmuF}`%IMSi4xDW}U%gm&8`NF~^Im+q1<J&rs4sB^kFY{=$LpJr z+@T4|9sj{uW5-QU{27;SZm?}}Vqjn>UFFejqSE>Ph5z6G|6k8_>HPm<>P=9Tu&98h z$~inb8M_?>JerSKpac%MAJgq7(0ZUQ5}J*CdR4U@AgLSFaRRT+bLB8R2~L7OozJ>$ zX1us{3#FeBeG^nRx!h#{bv(f{`1Pkj`3Yhb#`qMZ5!?KRquU*1v6kU&NITA>+m*qi z+vdg#=^G%IyK=xL22S4qbu<O)?}28cUi`fdlC9-<@dd<yjrYHNb{(8$LG=x&|0&S= zzb?Jk{l7;yAE?*q4C{tkA$LC^`5RCFQ`Msz+WX{}XTa0%M44}P4EO1^{jLidf%ELV z1`5`%jv<bne?mQabzkT*Fa-N({somzFPK3dIQW;jL>km{XYlF#<O5!3<@jIZKDYyF zdAIZxA|Rm&n&B|=a3aXR-J*#Wpw&1pjc)$`4^GA$AYF(Rl%QdeQ9K#~qaiRF0;3@? z8UlkW1VHDFfLs(>oS2@fV5Oj1tPrhRq5wL9B~~F?H%%d}D76s8DgqG&3I(Y}Y4JIk z#U&ta4u~iP5y>DTMIkS>q&&YUJ3b|~EHgP3B$la=nU|KCmzk89ml9u)Sdsw}%vZ?C zPfyFt0jo$=NY2mAP0UMCNGwV(%}vcKDb~}|iv^9dFfcG=rh(mJYipoTl98IHkdvQZ zPz*J*B(p3v2YT*8W}1R-szPS5LP1e#acW+P4p^H4$XJjM6cUS474q^+6iSOzLCtvv z-2#Qg<dV#?#FErvu&45iauf5CL5?ZSD@iRX1_cV}Y$FA*EZEB+<CF7q6BUY63lfVG zOHxx5Kp~-!p9WTgZh}I2W=TeVX^BE{L1J>Mo`P$Il|p7-aY<2Wa!F=>Ua?McVsb`m zd~RlOaVpF@2HhO6nZ+RADiq`w7iT8rq+&N7<hR1o%o4C(-4rDMK%+q+H$N}4B)=## zFI_<+GYu_vK)#94Q79?OOf6O@$yZ28ElEu-QOGP&NGvVM&rK}JOis+nsRXU8XJBB^ z%|tRE5vAx>AY{OiO}rht#YpBCmn4>C7MElu7lXn!zbv&VBQ-HaAu~@QFEKB_I5jyx zF9qyt1_s?yBz;Ax1^GoKAU(yE#U-h^3OV_S;Mith&`rjwuAnGCIkmVrzeoYpGf6E< zEGaEYWza1`QXJ$M;KNX!#E_Yjk(^eNlA2#oR9woS49X$JC5gEO3Jj{n3Jh>ZGN|UH z=&2f5=A<YvsOFS{h!h0|2JuV(|3A9;|NnuD|Nqaq`2YWhs}P)y#EwK_8(sYW|L+Be znoAe{|986d|No2&|Nj?U`2SxAbfQyQd}>*0UP(OopeI+*0Z$4bCMd3RQWH~BixgCI zaw@nOoD=gv>AnaQfJLdrr8y-GkaSm+nwDCWnwOkf3>APT#H6CcyyT2{<dn()6@#fL zEsjsFOwLIyW++Nci%%{ng>fM!=NP8M7sV$+jfL=Xk$B}Oa^>;Jas?=I1qituWFtWw zxUQUdBm+SlBpD>*a^exDrIh3(A(;o|!t{Z;2s5Ev6j_A1U|EF8nW!d1xiGz8F2ZCe z7ey9fGFTR2a#BGll9M4km`)H6VJw7)EQc@@B!@6FFFz#}$xtX4rW4FX7z^d1$RZ2| z%OXt9FNg;vIV8goA}|wRA_yxGBIs%m7Qxh@*i`^Z%_YehsP-X=BAEvlMX?u26q{NU z`{8O4Zh&O1_{3yTaf0Luba9y3sNx8hpo?Qyk8lmDda!#y*%5S-8be89adtfTP&I~v z#Prnow8YY!l46GB{JfIXijw%^^30Ot3{dtjD2>m}OfO0VS4+rh<8w3fQ2B{j42e0J z>3N`f8fIW>ZfOo!FH9h%G&i@BA*moOKEJf2ptOV`IlU;qv;biv14C$Dc3ysY9=4hd z)Chsr{tOIx`3kV}@)XkYOY>3`G;$LwlTyL;V|Hp$UTTg)ZhlH>4yf|aQ!fD*`Kc-P z&}s|q&^*u?dpZiq8L7$H3XrH$&?w5!FHy)#O-)HnQLxu!P%Tz1Mbia4Y7g2Z0H4JQ z+RzBX`o)#S`pG$o#l`x0sU`ZV#rlZKOTVZBeAr)VNihQ<bxD;a;6?ymbtOcaS5grV zF;5><zkwZAlwVqs$^hYmT*y#boLU4r9j_!cmmxDHCzT;HzdSLsgrPV;tt7LkkfFFF zH8F=Fy)?DB1VYB=WhSRGs21yk>e%?A<TAM5ki}9GOA_IVDsnSRFjRpB!OAj=Dhe1f ziz<>BGD|?Ll8Pkca6+^t^tHg27VB&2C+9<&XZj2wsksI5swwdduyI9j^dN;Fcw`VZ zKBy0>-&IrMa}twMa~K$q?ZK)pGY^z*G1W0jGh2hsCI+4T^5Mw;{}&h;7#<w||NjRg z1H*^o|Nn1bVqh>h_y7L_Mg|6j^Z)+~fcWSC|5ssRU~oA9|Gxzj14F|3|NjF(OTsVw z{}0-s6maqXf6zg}4Hy6a*I;H~5V-XJe*q|QUH<=n4>JS9ge(95^RO^57+n4T--U&N zVZ+t`|64%(YybZrVPRlMxc>jY1}g)@fgAt-m#{K0G~E3Ee*uVp^Z)-HtPBhaxBmZs z!OFm};m-g67HkX*pmFgMHU@?T_x}H1!p6X$aR2}R9c&B?6Yl^2{{ysW{o()r0qhJ6 zA0GbyKZTuv!Qj#V{|DF^7#be^|9^v>fx+SN|Njyk3=9fS{{N5QU|?AA?En8I91IK_ zp8fw1S{xei{Qv(891IKzFaG~m;ACLf@Z$e}3r+?GftUaPr*JYb6ukWZe-0-DgTd?n z|6g!2Fa*5$|KEU%f#JZL|NnEi7#I}Z{{KIPi-BRm+yDPpfJ%aQ|NnpBVqg$>_y0c! zXmc9_0|RISEhxentAZF9D+Cy&dDuB7FtQ7P#6g=|JI?(758CtzQUk&uaS)BFo&mJZ zm;t0-;_(0fA3$-!C*Z~>;l<Bg&e6bNFJ-M|tODB03bqe)2KIxa|NnzlgMrKfVbCyi z4CtJ%v;Y5tW+-4{1)%fI&;I`pcCHH_*j?Ze&$IvkD}WTa@Ck(Tae&WpoCDPlTB5?> z!YAMXIwyvKfnmzo|Ns3#hI;S`^f9^eN%S)N@G11LxbtbWvAXaXG_x_?=i<}w;8Sqo zlknsdaN^_e;7;JvaO6|)<dbj$3-~ZFFo4d^wK)3!zXK?4o%jU$nVk3}`k0;g6na^l z_%wQ09r+B}*j)H5n%Q0W8W@@1v2gKOIP)1e@@Y7M&4w7|3i1nR<E{^A=HuM||KRgS z9Qg#=m>l^enwf+66e9T~9Qgzs`8dGmg_kfgFa(_Y{~vrL6WCr?kiD*aFne9#_WJNS zFop72IAT}|3X46A3=A{Q{r~?66mDR1!0z`1nd1s_KiC{ci2EIwCURjj$cvi+6c!vz z3=B5s|NjT&VFrX*Xkp<2GRvLs10%B@BNv~A3x=~CL16(p=P81TfuZKY|Nrx#ZtDfb zQxCHvpF$gp3!g?aD4v)a_%vMj6dYl3Vgov7h>3yW$%X&_3qkrk`2?`)3j)U_T%Y6N zV`o6C>_GZ2FflNwTqI9_0s{ks05bza%EkZxRY2(rXE;E^GyzALI&xRTQ;Hj(f-B5} zuG|cucq?IMU@*A!|9>Rh4siUVg*D6$W-CT)A<e+R0NN^YfSG~8<?{dk`$6FaPIE4x zH0Q;qz|_kHOLb1%;C%XqnStTP<^TVY&$|I__+|kuBfIkde;~*VPd<SjCKo=5Hf9$- zg=Us&uo+H#9H2l3EqP^NU@!rdu~+{8Zv~YL;4pFrrC)6Bcjr66#B9!lJFS2g1%t}$ zf@}Z(gU&n$rM+HIK15F|*SJt4-JP2O<aW^E@*&s%|33wCyA#Omj&Qd#P2=K|Z~<p` z(Ee(0neu^!fdMo}13jjZ0hDG~SQ!`+Zv6kB4Kl+Wp5|OYY1I*wRz3MPFjn(vxFMxg z4``YL?e%eCWnh?a<NyCeP<;Br%Mn*Tl>7{iPj|ixoJ<$F_$=HovW^=!Qv@Fe$k=n| zL3c?oFw9|PU|4Yzk-z(x+(2cWE2yk<gqL-0d>a^<+PJ{xIU*HHUfiJc@qm?qA>`Ko z|KPKa+(F^v3J;&q!+a7h$M^)C&hT-7>H!`$28N7V|Nn!^15i+aFerRfKy~7+|Nr-Z z1e`!+t|!PH-f(w#fXm#8kQj1;rFL*x0MZY-pg`gF|Nj@^`h7wAozV0z;{pdUs(w&@ z0oBC^ZvX#Z3QupI@bu;hD(Bom<s~?LUHBZB>p?{mW{K&@4XTqsd+EO1h1NgN`jQ1y zr{9H^RUkJ))42>g14G5V|Nogm@#>8wUJ><!JKqBirpwsMS7%6!g2Fe4oq@sPK5F=a z;;4n4fuZ33|No#Jrl9oS!{iK#BWF<ltAu1?PzK}%m8%=r85ow_|NkF+jHDAhts=@* zKR$ze)M6D}=Dc8MU^sLC|9?=O0kWeXl*gfUod+lkJwRdT4JzNg`4X6$8L|0=fdO29 znQ$;LI6Oq;*M25&{`Y~Wcd%K`5VH!H9%3^Jl<#Xe7#JiT{r{f`3UfqR?*Ynp;5x#M z&!7@D*Mmx-v!J>b)SmKr^#4C-|26}n+;ibm06E45T-k!+`vC_7L(8N8|BFC&K;8d^ zgMs10qyPUwXUs#w0-T;)`4oCt5cMXsu5-x3=6rB@YQxFE!0{N-z5!VQvNHs<di3%C z|DbJtAhE%KVdq!F&Z~x<PmS(2*!k2jaZu6+v0>*^gV-Pp%8DQwc0M(T4Z@)2Ifxbl z6^tMT6oaZ55EFJjHHZzupaX6|H0*q85F3O+O)?M-JD(cF24PUpf@s+J)G+%%Vjv7V zpBh~pc0M(_IP83CbaB}E)ac@{^QqCrVdqoB#9`qBJD(a|9Cki6x;X57YIJef`PAs* zu=A<W#bM`D!^B}U?0jk%A4bE@r-t!iH0*q87#~K%&Zma)VKnS~Y8W3zdw~l#$h|M1 zc!H$|*!k2jbue+*`PAs*u=A<W#oKV04?CY4T|Ml4YM3}I9m3A1Mi+;jPmL}PJD(a| z9Cki6x;X57YIJef`P49RSo(*ZPmL}PI{5$;j_BgB^QqCrVdqn$i^I;RMi+;jPYn|X z*#*L|^QqCr%b@2$ql?4Nr$!f_g+u)s9OAI^sbS{8@)zuUYIJef`PAs*u=A<W#bM`D zql?4Nr$!ftolgxD2Zap?!_KEh7l)lsjV=y5pBh~pc0M(_IP83CbaB}E)Ufgz<Q5Qy zolgxDhtaU}sbPFrc*4%7hKa-Mft^nc6Nlwf*!k2jaacZrolgxDhoxuO`P49R&;e#3 zcf!u6hKa+*5@6?3!^C0bKkR&Jm^f%S1Y{2Ed}^3Ds6Pr4hw*<w8Bhv*X9P$dyz>ym z01rYiFn|s|191a9K_ml%B!pss-3tLaI1D5Nb0_FvF%TbiKLlv(1jL8QfBpAAAH-h( z4NzD(F+e>83!fWMd6<8kpb-P}2WZhC$Q)4+frO#j7#P5-=NK5E+86?$5d~_0f|SF; z8+33Qh`$1A5KNo_8W1pduYkG_N-@Cf|NS50AJ7mD$ee#rKJ5Os|4=?GoIgPMPEe2h zg!1D-ng=0<-7kmkG&5-WaD&oeP&y4tmqF<^C_N2IFN4zCp!6{)eGN)KgVNuiG#lvT zI0gm=F(|DDrOlwU8<Y-%(rHk-3`(~_>1j}U8I;}zrH?`BYf$<bl>P>#*}$WF3=CpW zS`A8@L1{NA9R{V-pmZ6OZiCX(p!6~*y$wnqgVNWa^fM^^4N9|tPR2tId@Ov}x%22! zuyf~O=gh;-m4}@p4_dX2t_PV9J69fdjy&w#c-T4duyf&I=fK0xeTSX%4m;N!c8)u; z*&sIP+$RtXJGUKnPCM*ec6VoID+LXg)TGSBJOx8TJ!3rsT|-SMiveBM2qbF+mNwD@ z4?lv;#)d)pk%i&oe{?xe{$^xgVW@!?B+z8Y06L%%n|jc}h}gtI{aGdkeufFKi6*E; zpo0fN;s?;gZ5cpi6+Z*4UjkLm0J;u`kwKba1$dAYa?c+~4pd$+GKez3%2|*Y2)9Aa zf%kJjf(#4{lfdV~i@?ims4&Au&^R=fa5xTDFUA17&j&PK0MY}x9}Sy-@8dA%B@Xcq zVDqII9zf5Zh8E8Zf5GC?3<>QZ+ZY%EAQZz-s5k?fI42|Meo@SL6vH778qWlU=Yd|R z!O#lAj1d&J(hLVc7n6acpyIAD@rfWokX;bk8zv4qQUfFeRUZTs?*s{gBLmEchKWPn z5387PrJoeAdSM2iG_ZCQ0$cbOF+$Rh1GJuo^|>oS37tU%Bb{`C%@=1tFW)Ca)x+v{ zn8nM$;zIEIIAP+Td-NDVtpaF$3lsNe2Dyg^agQog;ym~sH-3f#RuBR3SRn%g1L$x9 zAqIX11E~AK)-f<Jyn(7O0A(D|dMk)FhHqeTC<lpRX9C?v$<L4gRS&IZ8F-m6oC4OR z$ppFg4R#L$tiHEr0jZZ_SO86*V8sj!3^q{nFE~O(VCK7n#UWzIWE5DOpWy>&(29Y9 z0X(+Mz`y{S*8}<Y0n{Au`~U+3Lq1HsJH!<5xDEpYLnBl?0D9>Ic+8oBfuS2L4pECt zma#(owF6pi!2C4_>fZ-Yaag`v4mO9M;Q_SN1kXD#FfeQbizAy1VV{SZ^8#uP%=~NM zd&H#R_whkgGcYhg@7>#grv5Gt^FecMpnLsb_h7)>`3w~AOactB_9)DJW@b>l!*~c< z3@pyiFu@rj1{>2=X9k6j6a(y@7FaoN4psjEsvg>%W+-IAZa!$N7!;2NpaEV61_tmP z6axc;Bs)kwKSO{$#9r{2Edv9C6WDx+7%~|O7UySh0G%|8WKJqr99boVU5!J$59}{# zh8t+%JQauf<v7H5g2nk644{*w;CV&{28Me$;wu^~&d>0`9O6Fk90mge!x5-^PN2Ex z4A^{#T4eGbSe&0B05ssuz`y_-uYAu23QuH}5cUVKdI%et<iinP$}FIGmu6sShN^}p zEG-=BZCOBf>0y=wUO3dp;t(&uAr6}J0Udt?bq$;XZRCfgNw^>b1H*E#Is6P8pydf{ z4r?1&99boVeG=qfCMgE=_Te=g>R*7x`588VCY2Z%VAl*Wd;^)oAPBFJp~1$$$_k1X zeue~40|q)@0J2#aD((Q96lY+74L2~zL&X!o6EO@7p!yi3UKcD5VxeMtusA=%1!#Hz zk5w};F!+PTQPqNYNjSty!R4V8+(WQ-1?b*V0S0M?6VUn{WCjR3L&E`f&p9+3Fw}z0 z=V!QJ2~x$t0GmI14$bcqpb-L|(*)h)1GZO?!5|W%9@?#Bm<%=tB8E&ZX9cA<#C@hP zxy?A#p8|{XGblj&3E(+=1_p-nQ1J=SdJw#JfPsPGDp(w5DuR9q7UySZ0Bu+U-AfIv zfPaGBFU@cOntx&O&cX)CM;D;tu=1aq4U!%Lp!GX=E|GzOK?f|3un)$P0GlJl0K4A_ zmgco_sJF!-9)LqU8Hac|Se&0B02)3}?=m!j#bK^P&{J`UZ^0oBI@}RkzJ35!&(EL$ z%`ebw!0-+%j<65Tf~Knjpan$?3=FV#0zW$_`~?|opy>)0FA`Ao8=&Tc=PDT(7?i-` za8uz7&?(>8+<6{{d)&b0@G~$#(?58=8Pu);i^GkDGg3hAWWsC@6oA$9Gc-WkIpDc3 z1_p)(sCWWeJEWf-)E<Ky3uml^sxPpE2!ZET85kHgL&X<B%OCK39|Hr!DX=(1Ei(BG zEY8nh0KH5Hy#9lMf#EAV_IrdCp!wwk^wKWyx&zR<2@X*DM>ZM4R>UC=nnMJ&9}++p zRfF0M(1hp;R?pAS04;~1!NCyD0g88Nh6QN(jv+X?sKih&pCLXzF)1^?Br%;KH$N-0 zB)?cMnIXBTq`0IsEln?(0dbRYd`T{7@n>FYF++TON`5@(3g5(>_>_|TqT=|((h7#; z{M>?^)RNQ`Jp=42K$q@j#wQjPC053#=9LsxGNctH=BCC&mUqU-Bk|%h^D;|Nl)@J3 z#b@TFWR_*7lqTlrB|{djgVrBrCdX&yrR6h#E=<--W`OQk&`V|jE!l@s@oAYU3?;b* z@gTAIvc#Oy)M5t2szAMD2GF8D=%RhSWQL^Dw6xTsc+kcY(DloD#xN1^qCY(ohV0Zz zJyQm-oDoz`&k)7{1%g|UqpxectDj4JJOlKa;CNK8r7*<1MEW`UdO9<p$bj#NW{8h> z_X~}8^@xWU<lz#;5by5e@8swc@9*Xo>>3gu;^^e#8qWX@E~uwrw-zTCmx4o_0eqt~ z_>N-Gt;G)T+lci{AySZws1Y$8;)`@=HRN7q6ivxFsfl^uKm^~DTu_N38xOi=8War- z;9!ENgJ?ktUWkjq%0L%LqnMDF6knWQS_Ilj0NQ+05)X@e2JqrzkOiRK5^z0+<_yqv z!SSi!g`kjoqv7(PTb1*{S68D56_*s{q~@UrL0pVT5)6>_oyGC6pauD@xCFEV25n6* zC;}j<5weW}w2=o*32fOf<O*yQdqF7}loml(Tcb#TuenAMNlZzBh7JQbP*aN-z;|Y& zD1!I{Ik+)yvPMx~TvAk$Uz(GHA_z(T(EGblWa8sN!3?<;8=M4k3sB@CH-n=HL2uti z5rba6jUtA2MLNVI@c0M26V;XR@hQdm@fnGEpf$(2skzBW$<fdR5+x;-1*!4bsg(@z zp8oO0B`KMC@!)-15Yu6C3kunieDKaJ22dJ9Bs=g8<!H_XUknb)V&IsETv3jq1agr& ziV!q4K{Ez8@q>u?s(etXS_HX19aTqsQgJafpkcR*qg@IQzLvZcwA~JNhdGJ~Am@RK zM(Cb722kco%`46?DhA!ZUXoe_@hdD4piV^A0lxbk#Z1Tr@F+syn8`*Jsw_^<&r3rU z%S?wvRT0Sc{DKk`Su8$8zTX~l+dGO5$Yt)3q7_8~oHyXv7JR8Y7I}EW%1eSq0yyG9 z^#k~ddW05phGNM5@dzP3Q%DX3#|QMzc@)|B_z+)bXz33sIFR!rxO_*Xuz1f9-}s`` z^vvRt)FPDf7aV_J2Z7UPYHk6vf{HH&M<ZGx1F|PIFSRJWGQKp60aDk%eF+Jzw9LH3 zoXo0J6t|}37oo;pX>m?!Dr&X{I|aoP8TsY$i8(n4e-xLbq!tySn9QJ8T$x*vn8ct5 zN+V!81IEe(ZH+8o(96p&N!3fwE7dC~$}dPQDyc*gN-E9FNzu(rfeJY~dFp~%D`4dr ziNzTVdMTB8#g(}bx}=B!EK`<RRGgWghr)?3V$dr}%}E4lfU*j5N*MG&{$kK8$SKiF z&o5!n18rtu&;xBUWzZ|i2bFXTdZ`)E)=5T65rPNN3TdW5bimjkT_C&kit@qkO3ckn zW&jxvvW7tqB+a0gR9wuU2imNfnpXm8^-)fO=2t;YLg?@^g9LP50!G8;S7A1R)WX;x z8q_TW&1u5)TR`>0Xjp#>q!xrZKm-y7-93w}KLV;BMuXO%At`5o^+RA{py6C({jhlz z7>#Z}x_;35zHk5kgN8-HM#AQeVKj6YgaI~hjP8C=zXCKy3-dp0UKvJ%_C<gU2DuRw zb};?0`Q1!VUl=ir&j6dJhS9KjX^<Hp3^D^m!!T$Z6*LD7vmZ9^3#0R(3SsVtse{pV z3=E)aw&4DU%`3xb*f<8d`=Q1%fTlS>VG1)3Hm?n%Ve{HB`_cVB9Xx--zyKW<V1Uh& z!)VyNI!HfgZ2-Fdh2VJ`26+5{?j!=c4I1&V`FF4w)GinsM1%G|fWj1HK8UXX)d!<N z<HR6w7zV971hHZCay0t|Kp6tmPlM7h_k#3*FpLkQH=yZ<jkCaLJ<v^LAdOHAvlq%` z*oLMbHf{~0IbjN+G$^j1OfUuNzk~b_k3U$1Lumt0;s&dP5a{+Ff!Yt#Zx9Vp2cu#A zT!<)QehbFGgr<K7Xfq1~0|Shnf#v~NxWV*;&Ikm}ML~-V`26Dq=)4xXdKe!@zW^P} z3eAHcGhy?cH;B{^I>#6kelYuC^O+Bz`eE~$AhSUjn!G?vFlJ<gq+OVP*nHWAT(C65 z2aw?m3=E+B2NHp~8x{|%q2UM954&glKt4z{WbXom1tDSjVKf(bo({2I5Vo#`0knY# zG`<M6AEKLq0j3W|3!~|W&1WqD6-*2a3=d!$p)|VxLF4!!vtaIr&671i2j)FMSJgrF zf+%$Ta!~tW;};+`APmzF9i{>aficWG$TTeNf)zlC15o>4fD#u21A`m`0|O{4g4_yH x0xQ2k$rI*wkT?v(#>2B<8lVy|d!by=h&O2K9gGX7g}NY2&>?UT7KB9C4*-FpKac<b diff --git a/counters.h b/src/counters.h similarity index 100% rename from counters.h rename to src/counters.h diff --git a/counters_group.c b/src/counters_group.c similarity index 100% rename from counters_group.c rename to src/counters_group.c diff --git a/counters_individual.c b/src/counters_individual.c similarity index 100% rename from counters_individual.c rename to src/counters_individual.c diff --git a/counters_option.py b/src/counters_option.py similarity index 100% rename from counters_option.py rename to src/counters_option.py diff --git a/frapl.c b/src/frapl.c similarity index 100% rename from frapl.c rename to src/frapl.c diff --git a/frapl.h b/src/frapl.h similarity index 100% rename from frapl.h rename to src/frapl.h diff --git a/infiniband.c b/src/infiniband.c similarity index 100% rename from infiniband.c rename to src/infiniband.c diff --git a/infiniband.h b/src/infiniband.h similarity index 100% rename from infiniband.h rename to src/infiniband.h diff --git a/load.c b/src/load.c similarity index 100% rename from load.c rename to src/load.c diff --git a/load.h b/src/load.h similarity index 100% rename from load.h rename to src/load.h diff --git a/mojitos.c b/src/mojitos.c similarity index 100% rename from mojitos.c rename to src/mojitos.c diff --git a/network.c b/src/network.c similarity index 100% rename from network.c rename to src/network.c diff --git a/network.h b/src/network.h similarity index 100% rename from network.h rename to src/network.h diff --git a/rapl.c b/src/rapl.c similarity index 100% rename from rapl.c rename to src/rapl.c diff --git a/rapl.h b/src/rapl.h similarity index 100% rename from rapl.h rename to src/rapl.h diff --git a/temperature.c b/src/temperature.c similarity index 100% rename from temperature.c rename to src/temperature.c diff --git a/temperature.h b/src/temperature.h similarity index 100% rename from temperature.h rename to src/temperature.h -- GitLab From c9d740bd0d471c737b10f5ca1e4cc5655ef691f4 Mon Sep 17 00:00:00 2001 From: rissadmin <floreal.risso@univ-tlse3.fr> Date: Sun, 18 Dec 2022 08:46:38 +0000 Subject: [PATCH 002/125] Standardized code formatting on GNU style --- src/counters.h | 6 +- src/counters_group.c | 85 +++++++----- src/counters_individual.c | 169 +++++++++++++---------- src/frapl.c | 119 ++++++++-------- src/frapl.h | 6 +- src/infiniband.c | 50 ++++--- src/infiniband.h | 4 +- src/load.c | 33 +++-- src/load.h | 6 +- src/mojitos.c | 277 ++++++++++++++++++++------------------ src/network.c | 72 +++++----- src/network.h | 6 +- src/rapl.c | 124 +++++++++-------- src/rapl.h | 6 +- src/temperature.c | 124 +++++++++-------- src/temperature.h | 6 +- 16 files changed, 605 insertions(+), 488 deletions(-) diff --git a/src/counters.h b/src/counters.h index 751557a..af20717 100644 --- a/src/counters.h +++ b/src/counters.h @@ -18,9 +18,9 @@ *******************************************************/ -unsigned int init_counters(char*, void **); -unsigned int get_counters(uint64_t* results, void*); +unsigned int init_counters(char *, void **); +unsigned int get_counters(uint64_t *results, void *); void clean_counters(void *); -void label_counters(char **labels, void*); +void label_counters(char **labels, void *); void show_all_counters(); diff --git a/src/counters_group.c b/src/counters_group.c index bc9b448..f134823 100644 --- a/src/counters_group.c +++ b/src/counters_group.c @@ -29,28 +29,32 @@ #include "counters.h" -struct _counter_t { +struct _counter_t +{ int nbcores; int nbperf; int *counters; }; - + static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) { + int cpu, int group_fd, unsigned long flags) +{ long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } + if (res == -1) + { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } return res; } -counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { +counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +{ struct perf_event_attr pe; struct _counter_t *counters = malloc(sizeof(struct _counter_t)); - + unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); counters->nbcores=nbcores; counters->nbperf=nb_perf; @@ -61,59 +65,70 @@ counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *name pe.read_format = PERF_FORMAT_GROUP; counters->counters = malloc((nbcores+1)*sizeof(int)); - for (int core=0; core<nbcores; core++) { - counters->counters[core]=-1; - for(int idperf=0; idperf<nb_perf; idperf ++){ - pe.type = types[idperf]; - pe.config = names[idperf]; - int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); - if(counters->counters[core]==-1) - counters->counters[core]=res; + for (int core=0; core<nbcores; core++) + { + counters->counters[core]=-1; + for(int idperf=0; idperf<nb_perf; idperf ++) + { + pe.type = types[idperf]; + pe.config = names[idperf]; + int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); + if(counters->counters[core]==-1) + counters->counters[core]=res; + } } - } return counters; } -void clean_counters(counter_t counters) { +void clean_counters(counter_t counters) +{ for(int core=0; core<counters->nbcores; core++) close(counters->counters[core]); free(counters->counters); free(counters); } -void start_counters(counter_t counters) { +void start_counters(counter_t counters) +{ for(int core=0; core<counters->nbcores; core++) ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); } -void reset_counters(counter_t counters) { +void reset_counters(counter_t counters) +{ for(int core=0; core<counters->nbcores; core++) ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); } -struct read_format { +struct read_format +{ uint64_t nr; - struct { + struct + { uint64_t value; } values[]; }; -void get_counters(counter_t counters, long long *values) { +void get_counters(counter_t counters, long long *values) +{ int nb_perf = counters->nbperf; size_t buffer_size = sizeof(uint64_t)*(1+nb_perf); - struct read_format* buffer = NULL; + struct read_format *buffer = NULL; if(buffer==NULL) buffer = malloc(buffer_size); - + memset(values, 0, nb_perf*sizeof(long long)); - for (int core=0; core<counters->nbcores; core++) { - if (-1 == read(counters->counters[core], buffer, buffer_size)) { - perror("PB Lecture resultat"); - exit(EXIT_FAILURE); - } - for(int idperf=0; idperf<=nb_perf; idperf++) { - values[idperf] += buffer->values[idperf].value; + for (int core=0; core<counters->nbcores; core++) + { + if (-1 == read(counters->counters[core], buffer, buffer_size)) + { + perror("PB Lecture resultat"); + exit(EXIT_FAILURE); + } + for(int idperf=0; idperf<=nb_perf; idperf++) + { + values[idperf] += buffer->values[idperf].value; + } } - } reset_counters(counters); } diff --git a/src/counters_individual.c b/src/counters_individual.c index 1437aa3..222037a 100644 --- a/src/counters_individual.c +++ b/src/counters_individual.c @@ -28,67 +28,79 @@ #include <asm/unistd.h> #include <stdint.h> -struct _counter_t { +struct _counter_t +{ int nbcores; int nbperf; int **counters; uint64_t *counters_values; uint64_t *tmp_counters_values; - int* perf_indexes; - + int *perf_indexes; + }; -typedef struct _counter_t* counter_t; +typedef struct _counter_t *counter_t; #include "counters_option.h" -void show_all_counters() { - for(int i=0; i<nb_counter_option;i++) +void show_all_counters() +{ + for(int i=0; i<nb_counter_option; i++) printf("%s\n", perf_static_info[i].name); } -void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb){ +void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) +{ *perf_type = malloc(nb*sizeof(__u32)); *perf_key = malloc(nb*sizeof(__u64)); - for(int i=0; i<nb; i++) { - (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; - (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; - } + for(int i=0; i<nb; i++) + { + (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; + (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; + } } -void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) { +void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) +{ char *token; *nb_perf=0; *perf_indexes=NULL; - while((token=strtok(perf_string, ",")) != NULL) { - perf_string = NULL; - int i; - for(i=0; i<nb_counter_option; i++) { - if(strcmp(perf_static_info[i].name, token) == 0) { - (*nb_perf)++; - (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); - (*perf_indexes)[*nb_perf-1]=i; - break; - } + while((token=strtok(perf_string, ",")) != NULL) + { + perf_string = NULL; + int i; + for(i=0; i<nb_counter_option; i++) + { + if(strcmp(perf_static_info[i].name, token) == 0) + { + (*nb_perf)++; + (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); + (*perf_indexes)[*nb_perf-1]=i; + break; + } + } + if(i == nb_counter_option) + { + fprintf(stderr, "Unknown performance counter: %s\n", token); + exit(EXIT_FAILURE); + } } - if(i == nb_counter_option) { - fprintf(stderr, "Unknown performance counter: %s\n", token); - exit(EXIT_FAILURE); - } - } } static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) { + int cpu, int group_fd, unsigned long flags) +{ long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } + if (res == -1) + { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } return res; } -counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { +counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +{ struct perf_event_attr pe; unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); memset(&pe, 0, sizeof(struct perf_event_attr)); @@ -98,26 +110,30 @@ counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *nam counter_t counters = malloc(sizeof(struct _counter_t)); counters->nbperf = nb_perf; counters->nbcores=nbcores; - counters->counters=malloc(nb_perf*sizeof(int*)); - for (int i=0; i<nb_perf; i++) { - pe.type = types[i]; - pe.config = names[i]; - counters->counters[i] = malloc(nbcores*sizeof(int)); - - for (int core=0; core<nbcores; core++) { - counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); + counters->counters=malloc(nb_perf*sizeof(int *)); + for (int i=0; i<nb_perf; i++) + { + pe.type = types[i]; + pe.config = names[i]; + counters->counters[i] = malloc(nbcores*sizeof(int)); + + for (int core=0; core<nbcores; core++) + { + counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); + } } - } return counters; } -void clean_counters(void *ptr) { +void clean_counters(void *ptr) +{ counter_t counters = (counter_t) ptr; - for(int counter=0; counter<counters->nbperf; counter++) { - for(int core=0; core<counters->nbcores; core++) - close(counters->counters[counter][core]); - free(counters->counters[counter]); - } + for(int counter=0; counter<counters->nbperf; counter++) + { + for(int core=0; core<counters->nbcores; core++) + close(counters->counters[counter][core]); + free(counters->counters[counter]); + } free(counters->counters); free(counters->counters_values); free(counters->tmp_counters_values); @@ -126,31 +142,37 @@ void clean_counters(void *ptr) { free(counters); } -void start_counters(counter_t counters) { +void start_counters(counter_t counters) +{ for(int counter=0; counter<counters->nbperf; counter++) for(int core=0; core<counters->nbcores; core++) ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); } -void reset_counters(counter_t counters) { +void reset_counters(counter_t counters) +{ for(int counter=0; counter<counters->nbperf; counter++) for(int core=0; core<counters->nbcores; core++) ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); } -void _get_counters(counter_t counters, uint64_t *values) { - for(int i=0; i<counters->nbperf; i++) { - uint64_t accu=0; - uint64_t count=0; - for (int core=0; core<counters->nbcores; core++) { - if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) { - fprintf(stderr, "Cannot read result"); - exit(EXIT_FAILURE); - } - accu += count; +void _get_counters(counter_t counters, uint64_t *values) +{ + for(int i=0; i<counters->nbperf; i++) + { + uint64_t accu=0; + uint64_t count=0; + for (int core=0; core<counters->nbcores; core++) + { + if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) + { + fprintf(stderr, "Cannot read result"); + exit(EXIT_FAILURE); + } + accu += count; + } + values[i] = accu; } - values[i] = accu; - } } @@ -158,14 +180,15 @@ void _get_counters(counter_t counters, uint64_t *values) { -unsigned int init_counters(char* args, void **state) { +unsigned int init_counters(char *args, void **state) +{ int nb_perf; - int* perf_indexes=NULL; + int *perf_indexes=NULL; perf_event_list(args, &nb_perf, &perf_indexes); - __u32* perf_type; - __u64* perf_key; + __u32 *perf_type; + __u64 *perf_key; perf_type_key(&perf_type, &perf_key, perf_indexes, nb_perf); counter_t fd = _init_counters(nb_perf, perf_type, perf_key); free(perf_type); @@ -176,15 +199,16 @@ unsigned int init_counters(char* args, void **state) { fd->tmp_counters_values = malloc(nb_perf*sizeof(uint64_t)); start_counters(fd); _get_counters(fd, fd->counters_values); - *state = (void*) fd; + *state = (void *) fd; return nb_perf; } -unsigned int get_counters(uint64_t* results, void*ptr) { +unsigned int get_counters(uint64_t *results, void *ptr) +{ counter_t state = (counter_t) ptr; -_get_counters(state, state->tmp_counters_values); + _get_counters(state, state->tmp_counters_values); for(int i=0; i<state->nbperf; i++) results[i] = state->tmp_counters_values[i] - state->counters_values[i]; @@ -192,9 +216,10 @@ _get_counters(state, state->tmp_counters_values); return state->nbperf; } -void label_counters(char **labels, void*ptr) { +void label_counters(char **labels, void *ptr) +{ counter_t state = (counter_t) ptr; - for(int i=0; i<state->nbperf;i++) + for(int i=0; i<state->nbperf; i++) labels[i] = perf_static_info[state->perf_indexes[i]].name; } diff --git a/src/frapl.c b/src/frapl.c index 433a28c..d0d0abf 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -28,7 +28,8 @@ #define MAX_HEADER 128 -char *get_frapl_string(const char *filename) { +char *get_frapl_string(const char *filename) +{ int fd = open(filename, O_RDONLY); if( fd == -1) return NULL; @@ -37,9 +38,10 @@ char *get_frapl_string(const char *filename) { close(fd); result[nb-1] = 0; return (result); -} +} -void test_append(char* name, int i) { +void test_append(char *name, int i) +{ //char last = name[strlen(name)-1]; //if (last>='0' && last <= '9') // return; @@ -47,22 +49,24 @@ void test_append(char* name, int i) { } -struct _frapl_t { +struct _frapl_t +{ unsigned int nb; char **names; int *fids; - uint64_t* values; - uint64_t* tmp_values; + uint64_t *values; + uint64_t *tmp_values; }; typedef struct _frapl_t _frapl_t; -void add_frapl_source(_frapl_t* rapl, char*name, char*energy_uj) { +void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) +{ rapl->nb += 1; - rapl->names = realloc(rapl->names, sizeof(char**)*rapl->nb); - rapl->fids = realloc(rapl->fids, sizeof(int*)*rapl->nb); - + rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); + rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); + rapl->names[rapl->nb-1] = malloc(strlen(name)+1); strcpy(rapl->names[rapl->nb-1], name); //printf("%s\n", energy_uj); @@ -71,18 +75,21 @@ void add_frapl_source(_frapl_t* rapl, char*name, char*energy_uj) { } -void _get_frapl(uint64_t *values, _frapl_t* rapl) { +void _get_frapl(uint64_t *values, _frapl_t *rapl) +{ static char buffer[512]; - for (int i = 0; i < rapl->nb; i++) { + for (int i = 0; i < rapl->nb; i++) + { - pread(rapl->fids[i], buffer, 100, 0); - values[i] = strtoull(buffer, NULL, 10); - } + pread(rapl->fids[i], buffer, 100, 0); + values[i] = strtoull(buffer, NULL, 10); + } } -unsigned int init_frapl(char* none, void **ptr) { +unsigned int init_frapl(char *none, void **ptr) +{ _frapl_t *rapl = malloc(sizeof(_frapl_t)); rapl->nb = 0; rapl->names = NULL; @@ -92,46 +99,49 @@ unsigned int init_frapl(char* none, void **ptr) { char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - for (int i=0;; i++) { - sprintf(buffer, name_base, i, "name"); - char *tmp = get_frapl_string(buffer); - if (tmp == NULL) break; - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); - add_frapl_source(rapl, tmp, buffer); - free(tmp); - - for (int j=0;; j++) { - sprintf(buffer, name_sub, i, i, j, "name"); - char *tmp_sub = get_frapl_string(buffer); - if (tmp_sub == NULL) break; - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - - - sprintf(buffer, name_sub, i, i, j, "energy_uj"); - add_frapl_source(rapl, tmp_sub, buffer); - - free(tmp_sub); + for (int i=0;; i++) + { + sprintf(buffer, name_base, i, "name"); + char *tmp = get_frapl_string(buffer); + if (tmp == NULL) break; + //printf("%s\n", tmp); + test_append(tmp, i); + //printf("%s -> %s\n", buffer, tmp); + + sprintf(buffer, name_base, i, "energy_uj"); + add_frapl_source(rapl, tmp, buffer); + free(tmp); + + for (int j=0;; j++) + { + sprintf(buffer, name_sub, i, i, j, "name"); + char *tmp_sub = get_frapl_string(buffer); + if (tmp_sub == NULL) break; + //printf("%s\n", tmp_sub); + test_append(tmp_sub, i); + //printf("%s -> %s\n", buffer, tmp_sub); + + + sprintf(buffer, name_sub, i, i, j, "energy_uj"); + add_frapl_source(rapl, tmp_sub, buffer); + + free(tmp_sub); + } } - } rapl->values = calloc(sizeof(uint64_t), rapl->nb); rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); _get_frapl(rapl->values, rapl); - *ptr = (void*)rapl; + *ptr = (void *)rapl; return rapl->nb; } -unsigned int get_frapl(uint64_t* results, void* ptr) { - _frapl_t* state = (_frapl_t*) ptr; +unsigned int get_frapl(uint64_t *results, void *ptr) +{ + _frapl_t *state = (_frapl_t *) ptr; _get_frapl(state->tmp_values, state); for(int i=0; i<state->nb; i++) results[i] = state->tmp_values[i] - state->values[i]; @@ -140,12 +150,14 @@ unsigned int get_frapl(uint64_t* results, void* ptr) { return state->nb; } -void clean_frapl(void *ptr) { - _frapl_t* rapl = (_frapl_t*) ptr; - for(int i=0; i<rapl->nb; i++) { - free(rapl->names[i]); - close(rapl->fids[i]); - } +void clean_frapl(void *ptr) +{ + _frapl_t *rapl = (_frapl_t *) ptr; + for(int i=0; i<rapl->nb; i++) + { + free(rapl->names[i]); + close(rapl->fids[i]); + } free(rapl->names); free(rapl->fids); free(rapl->values); @@ -154,8 +166,9 @@ void clean_frapl(void *ptr) { } -void label_frapl(char **labels, void *ptr) { - _frapl_t* rapl = (_frapl_t*) ptr; +void label_frapl(char **labels, void *ptr) +{ + _frapl_t *rapl = (_frapl_t *) ptr; for(int i=0; i<rapl->nb; i++) labels[i] = rapl->names[i]; } diff --git a/src/frapl.h b/src/frapl.h index 6b2d154..937108e 100644 --- a/src/frapl.h +++ b/src/frapl.h @@ -18,8 +18,8 @@ *******************************************************/ -unsigned int init_frapl(char*, void **); -unsigned int get_frapl(uint64_t* results, void*); +unsigned int init_frapl(char *, void **); +unsigned int get_frapl(uint64_t *results, void *); void clean_frapl(void *); -void label_frapl(char **labels, void*); +void label_frapl(char **labels, void *); diff --git a/src/infiniband.c b/src/infiniband.c index 49dca07..e0daa2a 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -26,49 +26,55 @@ #include <stdint.h> -struct network_t { +struct network_t +{ uint64_t values[4]; uint64_t tmp_values[4]; int sources[4]; }; -unsigned int _get_network(uint64_t* results, int* sources); +unsigned int _get_network(uint64_t *results, int *sources); -unsigned int init_infiniband(char* infi_path, void**ptr) { +unsigned int init_infiniband(char *infi_path, void **ptr) +{ if(infi_path==NULL) return 0; - if(strcmp(infi_path,"X")==0) { + if(strcmp(infi_path,"X")==0) + { + + glob_t res; + + glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); + if(res.gl_pathc == 0) + return 0; + infi_path = res.gl_pathv[0]; + } - glob_t res; - - glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); - if(res.gl_pathc == 0) - return 0; - infi_path = res.gl_pathv[0]; - } - char *filenames[] = {"%s/port_rcv_packets", - "%s/port_rcv_data", - "%s/port_xmit_packets", - "%s/port_xmit_data"}; + "%s/port_rcv_data", + "%s/port_xmit_packets", + "%s/port_xmit_data" + }; struct network_t *state = malloc(sizeof(struct network_t)); char buffer[1024]; - for(int i=0; i<4; i++) { - sprintf(buffer, filenames[i], infi_path); - state->sources[i] = open(buffer, O_RDONLY); - } - - *ptr = (void*) state; + for(int i=0; i<4; i++) + { + sprintf(buffer, filenames[i], infi_path); + state->sources[i] = open(buffer, O_RDONLY); + } + + *ptr = (void *) state; _get_network(state->values, state->sources); return 4; } char *_labels_infiniband[4] = {"irxp", "irxb", "itxp", "itxb"}; -void label_infiniband(char **labels, void*none) { +void label_infiniband(char **labels, void *none) +{ for(int i=0; i<4; i++) labels[i] = _labels_infiniband[i]; } diff --git a/src/infiniband.h b/src/infiniband.h index af8b2b6..1f6aaf9 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -18,5 +18,5 @@ *******************************************************/ -unsigned int init_infiniband(char* infi_path, void**ptr); -void label_infiniband(char **labels, void*); +unsigned int init_infiniband(char *infi_path, void **ptr); +void label_infiniband(char **labels, void *); diff --git a/src/load.c b/src/load.c index b3d154d..80daf4b 100644 --- a/src/load.c +++ b/src/load.c @@ -27,29 +27,33 @@ char buffer[LOAD_BUFFER_SIZE]; static int load_fid=-1; -static uint64_t load_values[10]={0,0,0,0,0,0,0,0,0,0}; -static uint64_t tmp_load_values[10]={0,0,0,0,0,0,0,0,0,0}; +static uint64_t load_values[10]= {0,0,0,0,0,0,0,0,0,0}; +static uint64_t tmp_load_values[10]= {0,0,0,0,0,0,0,0,0,0}; -void _get_load(uint64_t* results) { +void _get_load(uint64_t *results) +{ pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0); int pos=0; while(buffer[pos] > '9' || buffer[pos] < '0') pos++; - for(int i=0; i<10; i++) { - results[i] = strtoull(buffer+pos, NULL, 10); - while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; - pos++; - } + for(int i=0; i<10; i++) + { + results[i] = strtoull(buffer+pos, NULL, 10); + while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; + pos++; + } } // Public interface -unsigned int init_load(char* argument, void **state) { +unsigned int init_load(char *argument, void **state) +{ load_fid = open("/proc/stat", O_RDONLY); _get_load(load_values); return 10; } -unsigned int get_load(uint64_t* results, void* state) { +unsigned int get_load(uint64_t *results, void *state) +{ _get_load(tmp_load_values); for(int i=0; i<10; i++) results[i] = tmp_load_values[i] - load_values[i]; @@ -58,13 +62,16 @@ unsigned int get_load(uint64_t* results, void* state) { return 10; } -void clean_load(void *state) { +void clean_load(void *state) +{ close(load_fid); } char *_labels[10] = {"user","nice","system","idle","iowait","irq", - "softirq","steal","guest","guest_nice"}; -void label_load(char **labels, void*none) { + "softirq","steal","guest","guest_nice" + }; +void label_load(char **labels, void *none) +{ for(int i=0; i<10; i++) labels[i] = _labels[i]; } diff --git a/src/load.h b/src/load.h index 42ce968..299fa3e 100644 --- a/src/load.h +++ b/src/load.h @@ -18,7 +18,7 @@ *******************************************************/ -unsigned int init_load(char*, void **); -unsigned int get_load(uint64_t* results, void*); +unsigned int init_load(char *, void **); +unsigned int get_load(uint64_t *results, void *); void clean_load(void *); -void label_load(char **labels, void*); +void label_load(char **labels, void *); diff --git a/src/mojitos.c b/src/mojitos.c index e80e692..94954cf 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -35,7 +35,8 @@ -void usage(char** argv) { +void usage(char **argv) +{ printf("Usage : %s [-t time] [-f freq] [-r] [-p perf_list] [-l] [-u] [-c] [-d network_device] [-i infiniband_path] [-o logfile] [-e command arguments...]\n", argv[0]); printf("if time==0 then loops infinitively\n"); printf("if -e is present, time and freq are not used\n"); @@ -52,23 +53,26 @@ void usage(char** argv) { exit(EXIT_SUCCESS); } -void sighandler(int none) { +void sighandler(int none) +{ } -void flush(int none) { +void flush(int none) +{ exit(0); } FILE *output; -void flushexit() { +void flushexit() +{ fflush(output); fclose(output); } -typedef unsigned int (initializer_t)(char*, void **); -typedef void (labeler_t)(char **, void*); -typedef unsigned int (*getter_t)(uint64_t*, void*); -typedef void (*cleaner_t)(void*); +typedef unsigned int (initializer_t)(char *, void **); +typedef void (labeler_t)(char **, void *); +typedef unsigned int (*getter_t)(uint64_t *, void *); +typedef void (*cleaner_t)(void *); unsigned int nb_sources=0; void **states=NULL; @@ -79,30 +83,33 @@ unsigned int nb_sensors=0; char **labels=NULL; uint64_t *values=NULL; -void add_source(initializer_t init, char* arg, labeler_t labeler, - getter_t get, cleaner_t clean) { - nb_sources++; - states = realloc(states, nb_sources*sizeof(void*)); - int nb = init(arg, &states[nb_sources-1]); - if (nb == 0) { +void add_source(initializer_t init, char *arg, labeler_t labeler, + getter_t get, cleaner_t clean) +{ + nb_sources++; + states = realloc(states, nb_sources*sizeof(void *)); + int nb = init(arg, &states[nb_sources-1]); + if (nb == 0) + { nb_sources--; - states = realloc(states, nb_sources*sizeof(void*)); + states = realloc(states, nb_sources*sizeof(void *)); return; } - getter = realloc(getter, nb_sources*sizeof(void*)); - getter[nb_sources-1] = get; - cleaner = realloc(cleaner, nb_sources*sizeof(void*)); - cleaner[nb_sources-1] = clean; + getter = realloc(getter, nb_sources*sizeof(void *)); + getter[nb_sources-1] = get; + cleaner = realloc(cleaner, nb_sources*sizeof(void *)); + cleaner[nb_sources-1] = clean; - labels = realloc(labels, (nb_sensors+nb)*sizeof(char*)); - labeler(labels+nb_sensors, states[nb_sources-1]); - - values = realloc(values, (nb_sensors+nb)*sizeof(uint64_t)); - nb_sensors += nb; + labels = realloc(labels, (nb_sensors+nb)*sizeof(char *)); + labeler(labels+nb_sensors, states[nb_sources-1]); + + values = realloc(values, (nb_sensors+nb)*sizeof(uint64_t)); + nb_sensors += nb; } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ int total_time=1; int delta=0; int frequency=1; @@ -112,63 +119,65 @@ int main(int argc, char **argv) { if(argc==1) usage(argv); - + output=stdout; - + atexit(flushexit); signal(15, flush); - + int c; while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application==NULL) - switch (c) { - case 'f': - frequency=atoi(argv[optind]); - break; - case 't': - total_time=atoi(argv[optind]); - delta=1; - if(total_time==0) { - total_time=1; - delta=0; + switch (c) + { + case 'f': + frequency=atoi(argv[optind]); + break; + case 't': + total_time=atoi(argv[optind]); + delta=1; + if(total_time==0) + { + total_time=1; + delta=0; + } + break; + case 'd': + add_source(init_network, argv[optind], label_network, get_network, clean_network); + break; + case 'i': + add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); + break; + case 'o': + output = fopen(argv[optind],"wb"); + break; + case 'e': + application=&argv[optind]; + signal(17,sighandler); + break; + case 'p': + add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); + break; + case 'r': + add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); + break; + case 'R': + add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); + break; + case 'u': + add_source(init_load, NULL, label_load, get_load, clean_load); + break; + case 'c': + add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); + break; + case 's': + stat_mode=0; + break; + case 'l': + show_all_counters(); + exit(EXIT_SUCCESS); + default: + usage(argv); } - break; - case 'd': - add_source(init_network, argv[optind], label_network, get_network, clean_network); - break; - case 'i': - add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); - break; - case 'o': - output = fopen(argv[optind],"wb"); - break; - case 'e': - application=&argv[optind]; - signal(17,sighandler); - break; - case 'p': - add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); - break; - case 'r': - add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); - break; - case 'R': - add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); - break; - case 'u': - add_source(init_load, NULL, label_load, get_load, clean_load); - break; - case 'c': - add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); - break; - case 's': - stat_mode=0; - break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); - default: - usage(argv); - } setvbuf(output, NULL, _IONBF, BUFSIZ); @@ -187,71 +196,77 @@ int main(int argc, char **argv) { unsigned long int stat_data=0; - for (int temps = 0; temps <total_time*frequency; temps+=delta) { - clock_gettime(CLOCK_MONOTONIC, &ts_ref); - - // Get Data - unsigned int current = 0; - for(int i=0; i<nb_sources; i++) - current += getter[i](&values[current], states[i]); - - if(application != NULL) { - - if(fork()==0){ - execvp(application[0], application); - exit(0); - } - pause(); - clock_gettime(CLOCK_MONOTONIC, &ts); - if(ts.tv_nsec >= ts_ref.tv_nsec) - fprintf(output, "%ld.%09ld ", (ts.tv_sec-ts_ref.tv_sec), ts.tv_nsec-ts_ref.tv_nsec); + for (int temps = 0; temps <total_time*frequency; temps+=delta) + { + clock_gettime(CLOCK_MONOTONIC, &ts_ref); + + // Get Data + unsigned int current = 0; + for(int i=0; i<nb_sources; i++) + current += getter[i](&values[current], states[i]); + + if(application != NULL) + { + + if(fork()==0) + { + execvp(application[0], application); + exit(0); + } + pause(); + clock_gettime(CLOCK_MONOTONIC, &ts); + if(ts.tv_nsec >= ts_ref.tv_nsec) + fprintf(output, "%ld.%09ld ", (ts.tv_sec-ts_ref.tv_sec), ts.tv_nsec-ts_ref.tv_nsec); + else + fprintf(output, "%ld.%09ld ", (ts.tv_sec-ts_ref.tv_sec)-1,1000000000+ts.tv_nsec-ts_ref.tv_nsec); + } else - fprintf(output, "%ld.%09ld ", (ts.tv_sec-ts_ref.tv_sec)-1,1000000000+ts.tv_nsec-ts_ref.tv_nsec); - } - else { + { #ifdef DEBUG - clock_gettime(CLOCK_MONOTONIC, &ts); - fprintf(stderr, "%ld\n", (ts.tv_nsec-ts_ref.tv_nsec)/1000); - //Indiv: mean: 148 std: 31 % med: 141 std: 28 % - //Group: mean: 309 std: 41 % med: 297 std: 39 % + clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stderr, "%ld\n", (ts.tv_nsec-ts_ref.tv_nsec)/1000); + //Indiv: mean: 148 std: 31 % med: 141 std: 28 % + //Group: mean: 309 std: 41 % med: 297 std: 39 % #endif - if(stat_mode==0) { - clock_gettime(CLOCK_MONOTONIC, &ts); - if(ts.tv_nsec >= ts_ref.tv_nsec) - stat_data = ts.tv_nsec-ts_ref.tv_nsec; - else - stat_data = 1000000000+ts.tv_nsec-ts_ref.tv_nsec; - } - - // Treat Data - fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); - } - - for(int i=0; i<nb_sensors; i++) - fprintf(output, "%" PRIu64 " ", values[i]); + if(stat_mode==0) + { + clock_gettime(CLOCK_MONOTONIC, &ts); + if(ts.tv_nsec >= ts_ref.tv_nsec) + stat_data = ts.tv_nsec-ts_ref.tv_nsec; + else + stat_data = 1000000000+ts.tv_nsec-ts_ref.tv_nsec; + } + + // Treat Data + fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); + } - if(stat_mode==0) - fprintf(output, "%ld ", stat_data); + for(int i=0; i<nb_sensors; i++) + fprintf(output, "%" PRIu64 " ", values[i]); - fprintf(output, "\n"); + if(stat_mode==0) + fprintf(output, "%ld ", stat_data); - if(application != NULL) - break; + fprintf(output, "\n"); - clock_gettime(CLOCK_MONOTONIC, &ts); - usleep(1000*1000/frequency-(ts.tv_nsec/1000)%(1000*1000/frequency)); - } + if(application != NULL) + break; - for(int i=0; i<nb_sources;i++) + clock_gettime(CLOCK_MONOTONIC, &ts); + usleep(1000*1000/frequency-(ts.tv_nsec/1000)%(1000*1000/frequency)); + } + + for(int i=0; i<nb_sources; i++) cleaner[i](states[i]); - if(nb_sources > 0) { - free(getter); - free(cleaner); - free(labels); - free(values); - free(states); - } + if(nb_sources > 0) + { + free(getter); + free(cleaner); + free(labels); + free(values); + free(states); + } } diff --git a/src/network.c b/src/network.c index 6e3f494..587319b 100644 --- a/src/network.c +++ b/src/network.c @@ -24,60 +24,68 @@ #include <string.h> #include <stdint.h> -struct network_t { +struct network_t +{ uint64_t values[4]; uint64_t tmp_values[4]; int sources[4]; }; -unsigned int _get_network(uint64_t* results, int* sources) { +unsigned int _get_network(uint64_t *results, int *sources) +{ if(sources==NULL) return 0; char buffer[128]; - for(int i=0; i<4; i++){ - pread(sources[i], buffer, 127, 0); + for(int i=0; i<4; i++) + { + pread(sources[i], buffer, 127, 0); - results[i] = strtoull(buffer, NULL, 10); - } + results[i] = strtoull(buffer, NULL, 10); + } return 4; } -unsigned int init_network(char* dev, void**ptr) { +unsigned int init_network(char *dev, void **ptr) +{ if(dev==NULL) return 0; - if(strcmp(dev,"X")==0) { - int f = open("/proc/net/route", O_RDONLY); - char buffer[1000]; - read(f, buffer, 999); - char *start_of_dev = index(buffer, '\n')+1; - char *end_of_dev = index(start_of_dev, '\t'); - *end_of_dev='\0'; - dev = start_of_dev; - close(f); - } - + if(strcmp(dev,"X")==0) + { + int f = open("/proc/net/route", O_RDONLY); + char buffer[1000]; + read(f, buffer, 999); + char *start_of_dev = index(buffer, '\n')+1; + char *end_of_dev = index(start_of_dev, '\t'); + *end_of_dev='\0'; + dev = start_of_dev; + close(f); + } + char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", - "/sys/class/net/%s/statistics/rx_bytes", - "/sys/class/net/%s/statistics/tx_packets", - "/sys/class/net/%s/statistics/tx_bytes"}; + "/sys/class/net/%s/statistics/rx_bytes", + "/sys/class/net/%s/statistics/tx_packets", + "/sys/class/net/%s/statistics/tx_bytes" + }; struct network_t *state = malloc(sizeof(struct network_t)); char buffer2[256]; - for(int i=0; i<4; i++) { - sprintf(buffer2, filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); - } - *ptr = (void*) state; + for(int i=0; i<4; i++) + { + sprintf(buffer2, filenames[i], dev); + state->sources[i] = open(buffer2, O_RDONLY); + } + *ptr = (void *) state; _get_network(state->values, state->sources); return 4; } -unsigned int get_network(uint64_t* results, void* ptr) { +unsigned int get_network(uint64_t *results, void *ptr) +{ struct network_t *state = (struct network_t *) ptr; _get_network(state->tmp_values, state->sources); for(int i=0; i<4; i++) @@ -87,17 +95,19 @@ unsigned int get_network(uint64_t* results, void* ptr) { return 4; } -void clean_network(void *ptr) { +void clean_network(void *ptr) +{ struct network_t *state = (struct network_t *) ptr; if(state==NULL) return; - for(int i=0;i<4;i++) + for(int i=0; i<4; i++) close(state->sources[i]); free(state); -} +} char *_labels_network[4] = {"rxp", "rxb", "txp", "txb"}; -void label_network(char **labels, void*none) { +void label_network(char **labels, void *none) +{ for(int i=0; i<4; i++) labels[i] = _labels_network[i]; } diff --git a/src/network.h b/src/network.h index 44759dc..3ba9ae5 100644 --- a/src/network.h +++ b/src/network.h @@ -18,8 +18,8 @@ *******************************************************/ -unsigned int init_network(char*, void **); -unsigned int get_network(uint64_t* results, void*); +unsigned int init_network(char *, void **); +unsigned int get_network(uint64_t *results, void *); void clean_network(void *); -void label_network(char **labels, void*); +void label_network(char **labels, void *); diff --git a/src/rapl.c b/src/rapl.c index 14b4a58..2536600 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -24,15 +24,16 @@ #include <powercap/powercap-rapl.h> -struct _rapl_t { - powercap_rapl_pkg* pkgs; +struct _rapl_t +{ + powercap_rapl_pkg *pkgs; uint32_t nb_pkgs; uint32_t nb; char **names; - uint32_t* zones; - uint32_t* packages; - uint64_t* values; - uint64_t* tmp_values; + uint32_t *zones; + uint32_t *packages; + uint64_t *values; + uint64_t *tmp_values; }; typedef struct _rapl_t _rapl_t; @@ -49,69 +50,77 @@ const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_COR #define MAX_LEN_NAME 100 // values [zone + package *nbzones] microjoules -void _get_rapl(uint64_t *values, _rapl_t* rapl) { - for (int i = 0; i < rapl->nb; i++) { +void _get_rapl(uint64_t *values, _rapl_t *rapl) +{ + for (int i = 0; i < rapl->nb; i++) + { #ifdef DEBUG - int ret = + int ret = #endif - powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], - rapl->zones[i], - &values[i]); + powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], + rapl->zones[i], + &values[i]); #ifdef DEBUG - printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); + printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); #endif - } + } } -unsigned int init_rapl(char* none, void **ptr) { +unsigned int init_rapl(char *none, void **ptr) +{ // get number of processor sockets - _rapl_t* rapl= malloc(sizeof(struct _rapl_t)); + _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); rapl->nb = 0; rapl->packages = NULL; rapl->zones = NULL; rapl->nb_pkgs = powercap_rapl_get_num_instances(); //rapl->nb_pkgs = powercap_rapl_get_num_packages(); - - if (rapl->nb_pkgs == 0) { - perror("no packages found (maybe the kernel module isn't loaded?)"); - exit(-1); - } - rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); - for (int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { - perror("powercap_rapl_init, check access (root needed ?)"); + + if (rapl->nb_pkgs == 0) + { + perror("no packages found (maybe the kernel module isn't loaded?)"); exit(-1); } + rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); + for (int package = 0; package < rapl->nb_pkgs; package++) + if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) + { + perror("powercap_rapl_init, check access (root needed ?)"); + exit(-1); + } rapl->names = NULL; - + char _name[MAX_LEN_NAME+1]; char _name2[MAX_LEN_NAME+11]; - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { - for(unsigned int zone=0; zone < nb_zones; zone++) { - int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], - _name, MAX_LEN_NAME); - if (length>0) { - - sprintf(_name2, "%s%u", _name, package); - - rapl->nb++; - rapl->names = realloc(rapl->names, sizeof(char*)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); - rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); - rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); - - strcpy(rapl->names[rapl->nb-1], _name2); - rapl->zones[rapl->nb-1] = rapl_zones[zone]; - rapl->packages[rapl->nb-1] = package; - } + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) + { + for(unsigned int zone=0; zone < nb_zones; zone++) + { + int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], + _name, MAX_LEN_NAME); + if (length>0) + { + + sprintf(_name2, "%s%u", _name, package); + + rapl->nb++; + rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); + rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); + rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); + rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); + + strcpy(rapl->names[rapl->nb-1], _name2); + rapl->zones[rapl->nb-1] = rapl_zones[zone]; + rapl->packages[rapl->nb-1] = package; + } #ifdef DEBUG - printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); + printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); #endif + } } - } #ifdef DEBUG printf("Result of init\n"); for(int i=0; i<rapl->nb; i++) @@ -123,14 +132,15 @@ unsigned int init_rapl(char* none, void **ptr) { _get_rapl(rapl->values, rapl); - *ptr = (void*)rapl; + *ptr = (void *)rapl; return rapl->nb; } -unsigned int get_rapl(uint64_t* results, void* ptr) { - _rapl_t* state = (_rapl_t*) ptr; +unsigned int get_rapl(uint64_t *results, void *ptr) +{ + _rapl_t *state = (_rapl_t *) ptr; _get_rapl(state->tmp_values, state); for(int i=0; i<state->nb; i++) results[i] = state->tmp_values[i] - state->values[i]; @@ -142,14 +152,15 @@ unsigned int get_rapl(uint64_t* results, void* ptr) { -void clean_rapl(void* ptr) { - _rapl_t* rapl = (_rapl_t*) ptr; +void clean_rapl(void *ptr) +{ + _rapl_t *rapl = (_rapl_t *) ptr; for (int package = 0; package < rapl->nb_pkgs; package++) if (powercap_rapl_destroy(&rapl->pkgs[package])) perror("powercap_rapl_destroy"); - for (int elem=0; elem<rapl->nb; elem++) - free(rapl->names[elem]); - + for (int elem=0; elem<rapl->nb; elem++) + free(rapl->names[elem]); + free(rapl->names); free(rapl->pkgs); free(rapl->zones); @@ -159,8 +170,9 @@ void clean_rapl(void* ptr) { free(rapl); } -void label_rapl(char **labels, void *ptr) { - _rapl_t* rapl = (_rapl_t*) ptr; +void label_rapl(char **labels, void *ptr) +{ + _rapl_t *rapl = (_rapl_t *) ptr; for(int i=0; i<rapl->nb; i++) labels[i] = rapl->names[i]; } diff --git a/src/rapl.h b/src/rapl.h index 9ec5f3a..74cc515 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -18,8 +18,8 @@ *******************************************************/ -unsigned int init_rapl(char*, void **); -unsigned int get_rapl(uint64_t* results, void*); +unsigned int init_rapl(char *, void **); +unsigned int get_rapl(uint64_t *results, void *); void clean_rapl(void *); -void label_rapl(char **labels, void*); +void label_rapl(char **labels, void *); diff --git a/src/temperature.c b/src/temperature.c index 142e86a..9dec997 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -25,113 +25,127 @@ #include <stdio.h> #include <stdint.h> -struct temperature_t { +struct temperature_t +{ char **label_list; int *fid_list; int nb_elem; }; - -int get_string(char *filename, char *buffer, int max_size) { + +int get_string(char *filename, char *buffer, int max_size) +{ int fid = open(filename, O_RDONLY); //printf("Tries to open : %s : %d\n", filename, fid); if(fid == -1) return -1; - + int nb = read(fid, buffer, max_size); - if(nb == -1) { - close(fid); - return -1; - } + if(nb == -1) + { + close(fid); + return -1; + } buffer[nb]=0; close(fid); return 0; } -void add_to_list(char ***list_name, char *source, int nb_elem) { +void add_to_list(char ***list_name, char *source, int nb_elem) +{ //printf("Adds: %s\n", source); - *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char*)); + *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char *)); (*list_name)[nb_elem] = malloc(strlen(source)+1); strcpy((*list_name)[nb_elem], source); } -void add_temperature_sensor(int id_rep, struct temperature_t *state) { +void add_temperature_sensor(int id_rep, struct temperature_t *state) +{ static int key=0; static char buffer_filename[512]; static char buffer_label[512]; - + int delta = sprintf(buffer_label, "Temp_%d_", key); - - for(int i=1;;i++) { - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); - if(get_string(buffer_filename, buffer_label+delta, 100) == -1) - break; - - for(int pos = 0; pos < strlen(buffer_label); pos++) { - if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; - if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; - } - add_to_list(&state->label_list, buffer_label, state->nb_elem); - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); - state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); - state->fid_list[state->nb_elem] = open(buffer_filename, O_RDONLY); + for(int i=1;; i++) + { + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); + if(get_string(buffer_filename, buffer_label+delta, 100) == -1) + break; + + for(int pos = 0; pos < strlen(buffer_label); pos++) + { + if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; + if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; + } + add_to_list(&state->label_list, buffer_label, state->nb_elem); + + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); + state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); + state->fid_list[state->nb_elem] = open(buffer_filename, O_RDONLY); + + state->nb_elem++; + // printf("%s : %s\n", buffer_label, buffer_filename); + } - state->nb_elem++; - // printf("%s : %s\n", buffer_label, buffer_filename); - } - key++; } -unsigned int init_temperature(char *args, void** ptr) { +unsigned int init_temperature(char *args, void **ptr) +{ struct temperature_t *state = malloc(sizeof(struct temperature_t)); state->nb_elem = 0; state->label_list = NULL; state->fid_list = NULL; - + char base_name[] = "/sys/class/hwmon/hwmon%d/name"; static char name[512]; static char buffer[512]; int i = 0; sprintf(name, base_name, i); - while(get_string(name, buffer, 8) != -1) { - if (strcmp(buffer, "coretemp")==0) - add_temperature_sensor(i, state); - - i++; - sprintf(name, base_name, i); - } - *ptr = (void*) state; + while(get_string(name, buffer, 8) != -1) + { + if (strcmp(buffer, "coretemp")==0) + add_temperature_sensor(i, state); + + i++; + sprintf(name, base_name, i); + } + *ptr = (void *) state; return state->nb_elem; } -unsigned int get_temperature(uint64_t* results, void* ptr) { - struct temperature_t *state = (struct temperature_t*)ptr; +unsigned int get_temperature(uint64_t *results, void *ptr) +{ + struct temperature_t *state = (struct temperature_t *)ptr; static char buffer[512]; - for(int i=0; i<state->nb_elem; i++) { - pread(state->fid_list[i], buffer, 100, 0); - results[i] = strtoull(buffer, NULL, 10); - } + for(int i=0; i<state->nb_elem; i++) + { + pread(state->fid_list[i], buffer, 100, 0); + results[i] = strtoull(buffer, NULL, 10); + } return state->nb_elem; } -void clean_temperature(void* ptr) { - struct temperature_t *state = (struct temperature_t*)ptr; - - for(int i=0; i<state->nb_elem; i++) { - free(state->label_list[i]); - close(state->fid_list[i]); - } +void clean_temperature(void *ptr) +{ + struct temperature_t *state = (struct temperature_t *)ptr; + + for(int i=0; i<state->nb_elem; i++) + { + free(state->label_list[i]); + close(state->fid_list[i]); + } free(state->label_list); free(state->fid_list); free(state); } -void label_temperature(char**labels, void* ptr) { - struct temperature_t *state = (struct temperature_t*)ptr; +void label_temperature(char **labels, void *ptr) +{ + struct temperature_t *state = (struct temperature_t *)ptr; for(int i=0; i<state->nb_elem; i++) labels[i] = state->label_list[i]; } diff --git a/src/temperature.h b/src/temperature.h index c6c34df..e49e416 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -18,7 +18,7 @@ *******************************************************/ -unsigned int init_temperature(char*, void **); -unsigned int get_temperature(uint64_t* results, void*); +unsigned int init_temperature(char *, void **); +unsigned int get_temperature(uint64_t *results, void *); void clean_temperature(void *); -void label_temperature(char **labels, void*); +void label_temperature(char **labels, void *); -- GitLab From 235419f61c07e12e6a6b00741f53da148b9900c4 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 20 Dec 2022 13:12:48 +0100 Subject: [PATCH 003/125] code style: 4 spaces instead of 2 --- makefile | 8 +- src/counters_group.c | 129 ++++++------ src/counters_individual.c | 250 +++++++++++------------ src/frapl.c | 180 ++++++++--------- src/infiniband.c | 60 +++--- src/load.c | 40 ++-- src/mojitos.c | 404 ++++++++++++++++++++------------------ src/network.c | 120 +++++------ src/rapl.c | 184 ++++++++--------- src/temperature.c | 174 ++++++++-------- 10 files changed, 787 insertions(+), 762 deletions(-) diff --git a/makefile b/makefile index 064dfca..6aaf27c 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -.PHONY: all clean mojitos mojitos_group debug format +.PHONY: all clean mojitos mojitos_group debug format SRC_DIR = src OBJ_DIR = obj @@ -10,7 +10,7 @@ OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc CFLAGS = -std=gnu99 -O3 -Wall # -Wextra -Werror -Wpedantic -ASTYLE = astyle --style=gnu -s2 -k3 -n -Z -Q +ASTYLE = astyle --style=gnu -xf -s4 -k3 -n -Z -Q # depending on the context it may need to be changed to all: mojitos mojitos_group @@ -34,7 +34,7 @@ $(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h $(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(SRC_DIR)/%.h $(CC) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR): +$(OBJ_DIR): mkdir -p $(OBJ_DIR) $(BIN_DIR): @@ -43,7 +43,7 @@ $(BIN_DIR): debug: CFLAGS += -DDEBUG -g debug: all -format: +format: $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h clean: diff --git a/src/counters_group.c b/src/counters_group.c index f134823..0154a94 100644 --- a/src/counters_group.c +++ b/src/counters_group.c @@ -31,104 +31,103 @@ struct _counter_t { - int nbcores; - int nbperf; - int *counters; + int nbcores; + int nbperf; + int *counters; }; -static long -perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) { - long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) - { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } - return res; + long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + if (res == -1) + { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } + return res; } counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { - struct perf_event_attr pe; - struct _counter_t *counters = malloc(sizeof(struct _counter_t)); + struct perf_event_attr pe; + struct _counter_t *counters = malloc(sizeof(struct _counter_t)); - unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); - counters->nbcores=nbcores; - counters->nbperf=nb_perf; - memset(&pe, 0, sizeof(struct perf_event_attr)); - pe.size = sizeof(struct perf_event_attr); - pe.disabled = 1; + unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); + counters->nbcores=nbcores; + counters->nbperf=nb_perf; + memset(&pe, 0, sizeof(struct perf_event_attr)); + pe.size = sizeof(struct perf_event_attr); + pe.disabled = 1; - pe.read_format = PERF_FORMAT_GROUP; - counters->counters = malloc((nbcores+1)*sizeof(int)); + pe.read_format = PERF_FORMAT_GROUP; + counters->counters = malloc((nbcores+1)*sizeof(int)); - for (int core=0; core<nbcores; core++) - { - counters->counters[core]=-1; - for(int idperf=0; idperf<nb_perf; idperf ++) + for (int core=0; core<nbcores; core++) { - pe.type = types[idperf]; - pe.config = names[idperf]; - int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); - if(counters->counters[core]==-1) - counters->counters[core]=res; + counters->counters[core]=-1; + for(int idperf=0; idperf<nb_perf; idperf ++) + { + pe.type = types[idperf]; + pe.config = names[idperf]; + int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); + if(counters->counters[core]==-1) + counters->counters[core]=res; + } } - } - return counters; + return counters; } void clean_counters(counter_t counters) { - for(int core=0; core<counters->nbcores; core++) - close(counters->counters[core]); - free(counters->counters); - free(counters); + for(int core=0; core<counters->nbcores; core++) + close(counters->counters[core]); + free(counters->counters); + free(counters); } void start_counters(counter_t counters) { - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); + for(int core=0; core<counters->nbcores; core++) + ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); } void reset_counters(counter_t counters) { - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); + for(int core=0; core<counters->nbcores; core++) + ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); } struct read_format { - uint64_t nr; - struct - { - uint64_t value; - } values[]; + uint64_t nr; + struct + { + uint64_t value; + } values[]; }; void get_counters(counter_t counters, long long *values) { - int nb_perf = counters->nbperf; - size_t buffer_size = sizeof(uint64_t)*(1+nb_perf); - struct read_format *buffer = NULL; - if(buffer==NULL) - buffer = malloc(buffer_size); + int nb_perf = counters->nbperf; + size_t buffer_size = sizeof(uint64_t)*(1+nb_perf); + struct read_format *buffer = NULL; + if(buffer==NULL) + buffer = malloc(buffer_size); - memset(values, 0, nb_perf*sizeof(long long)); + memset(values, 0, nb_perf*sizeof(long long)); - for (int core=0; core<counters->nbcores; core++) - { - if (-1 == read(counters->counters[core], buffer, buffer_size)) - { - perror("PB Lecture resultat"); - exit(EXIT_FAILURE); - } - for(int idperf=0; idperf<=nb_perf; idperf++) + for (int core=0; core<counters->nbcores; core++) { - values[idperf] += buffer->values[idperf].value; + if (-1 == read(counters->counters[core], buffer, buffer_size)) + { + perror("PB Lecture resultat"); + exit(EXIT_FAILURE); + } + for(int idperf=0; idperf<=nb_perf; idperf++) + { + values[idperf] += buffer->values[idperf].value; + } } - } - reset_counters(counters); + reset_counters(counters); } diff --git a/src/counters_individual.c b/src/counters_individual.c index 222037a..aff7fd0 100644 --- a/src/counters_individual.c +++ b/src/counters_individual.c @@ -30,13 +30,13 @@ struct _counter_t { - int nbcores; - int nbperf; - int **counters; - uint64_t *counters_values; - uint64_t *tmp_counters_values; + int nbcores; + int nbperf; + int **counters; + uint64_t *counters_values; + uint64_t *tmp_counters_values; - int *perf_indexes; + int *perf_indexes; }; typedef struct _counter_t *counter_t; @@ -45,134 +45,134 @@ typedef struct _counter_t *counter_t; void show_all_counters() { - for(int i=0; i<nb_counter_option; i++) - printf("%s\n", perf_static_info[i].name); + for(int i=0; i<nb_counter_option; i++) + printf("%s\n", perf_static_info[i].name); } void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) { - *perf_type = malloc(nb*sizeof(__u32)); - *perf_key = malloc(nb*sizeof(__u64)); - for(int i=0; i<nb; i++) - { - (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; - (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; - } + *perf_type = malloc(nb*sizeof(__u32)); + *perf_key = malloc(nb*sizeof(__u64)); + for(int i=0; i<nb; i++) + { + (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; + (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; + } } void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) { - char *token; - *nb_perf=0; - *perf_indexes=NULL; - while((token=strtok(perf_string, ",")) != NULL) - { - perf_string = NULL; - int i; - for(i=0; i<nb_counter_option; i++) + char *token; + *nb_perf=0; + *perf_indexes=NULL; + while((token=strtok(perf_string, ",")) != NULL) { - if(strcmp(perf_static_info[i].name, token) == 0) - { - (*nb_perf)++; - (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); - (*perf_indexes)[*nb_perf-1]=i; - break; - } + perf_string = NULL; + int i; + for(i=0; i<nb_counter_option; i++) + { + if(strcmp(perf_static_info[i].name, token) == 0) + { + (*nb_perf)++; + (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); + (*perf_indexes)[*nb_perf-1]=i; + break; + } + } + if(i == nb_counter_option) + { + fprintf(stderr, "Unknown performance counter: %s\n", token); + exit(EXIT_FAILURE); + } } - if(i == nb_counter_option) - { - fprintf(stderr, "Unknown performance counter: %s\n", token); - exit(EXIT_FAILURE); - } - } } static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { - long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) - { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } - return res; + long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + if (res == -1) + { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } + return res; } counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { - struct perf_event_attr pe; - unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); - memset(&pe, 0, sizeof(struct perf_event_attr)); - pe.size = sizeof(struct perf_event_attr); - pe.disabled = 1; - - counter_t counters = malloc(sizeof(struct _counter_t)); - counters->nbperf = nb_perf; - counters->nbcores=nbcores; - counters->counters=malloc(nb_perf*sizeof(int *)); - for (int i=0; i<nb_perf; i++) - { - pe.type = types[i]; - pe.config = names[i]; - counters->counters[i] = malloc(nbcores*sizeof(int)); - - for (int core=0; core<nbcores; core++) + struct perf_event_attr pe; + unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); + memset(&pe, 0, sizeof(struct perf_event_attr)); + pe.size = sizeof(struct perf_event_attr); + pe.disabled = 1; + + counter_t counters = malloc(sizeof(struct _counter_t)); + counters->nbperf = nb_perf; + counters->nbcores=nbcores; + counters->counters=malloc(nb_perf*sizeof(int *)); + for (int i=0; i<nb_perf; i++) { - counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); + pe.type = types[i]; + pe.config = names[i]; + counters->counters[i] = malloc(nbcores*sizeof(int)); + + for (int core=0; core<nbcores; core++) + { + counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); + } } - } - return counters; + return counters; } void clean_counters(void *ptr) { - counter_t counters = (counter_t) ptr; - for(int counter=0; counter<counters->nbperf; counter++) - { - for(int core=0; core<counters->nbcores; core++) - close(counters->counters[counter][core]); - free(counters->counters[counter]); - } - free(counters->counters); - free(counters->counters_values); - free(counters->tmp_counters_values); - free(counters->perf_indexes); - - free(counters); + counter_t counters = (counter_t) ptr; + for(int counter=0; counter<counters->nbperf; counter++) + { + for(int core=0; core<counters->nbcores; core++) + close(counters->counters[counter][core]); + free(counters->counters[counter]); + } + free(counters->counters); + free(counters->counters_values); + free(counters->tmp_counters_values); + free(counters->perf_indexes); + + free(counters); } void start_counters(counter_t counters) { - for(int counter=0; counter<counters->nbperf; counter++) - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); + for(int counter=0; counter<counters->nbperf; counter++) + for(int core=0; core<counters->nbcores; core++) + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); } void reset_counters(counter_t counters) { - for(int counter=0; counter<counters->nbperf; counter++) - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); + for(int counter=0; counter<counters->nbperf; counter++) + for(int core=0; core<counters->nbcores; core++) + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); } void _get_counters(counter_t counters, uint64_t *values) { - for(int i=0; i<counters->nbperf; i++) - { - uint64_t accu=0; - uint64_t count=0; - for (int core=0; core<counters->nbcores; core++) + for(int i=0; i<counters->nbperf; i++) { - if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) - { - fprintf(stderr, "Cannot read result"); - exit(EXIT_FAILURE); - } - accu += count; + uint64_t accu=0; + uint64_t count=0; + for (int core=0; core<counters->nbcores; core++) + { + if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) + { + fprintf(stderr, "Cannot read result"); + exit(EXIT_FAILURE); + } + accu += count; + } + values[i] = accu; } - values[i] = accu; - } } @@ -182,44 +182,44 @@ void _get_counters(counter_t counters, uint64_t *values) unsigned int init_counters(char *args, void **state) { - int nb_perf; - int *perf_indexes=NULL; - - perf_event_list(args, &nb_perf, &perf_indexes); - - __u32 *perf_type; - __u64 *perf_key; - perf_type_key(&perf_type, &perf_key, perf_indexes, nb_perf); - counter_t fd = _init_counters(nb_perf, perf_type, perf_key); - free(perf_type); - free(perf_key); - - fd->perf_indexes = perf_indexes; - fd->counters_values = malloc(nb_perf*sizeof(uint64_t)); - fd->tmp_counters_values = malloc(nb_perf*sizeof(uint64_t)); - start_counters(fd); - _get_counters(fd, fd->counters_values); - *state = (void *) fd; - - return nb_perf; + int nb_perf; + int *perf_indexes=NULL; + + perf_event_list(args, &nb_perf, &perf_indexes); + + __u32 *perf_type; + __u64 *perf_key; + perf_type_key(&perf_type, &perf_key, perf_indexes, nb_perf); + counter_t fd = _init_counters(nb_perf, perf_type, perf_key); + free(perf_type); + free(perf_key); + + fd->perf_indexes = perf_indexes; + fd->counters_values = malloc(nb_perf*sizeof(uint64_t)); + fd->tmp_counters_values = malloc(nb_perf*sizeof(uint64_t)); + start_counters(fd); + _get_counters(fd, fd->counters_values); + *state = (void *) fd; + + return nb_perf; } unsigned int get_counters(uint64_t *results, void *ptr) { - counter_t state = (counter_t) ptr; + counter_t state = (counter_t) ptr; - _get_counters(state, state->tmp_counters_values); - for(int i=0; i<state->nbperf; i++) - results[i] = state->tmp_counters_values[i] - state->counters_values[i]; + _get_counters(state, state->tmp_counters_values); + for(int i=0; i<state->nbperf; i++) + results[i] = state->tmp_counters_values[i] - state->counters_values[i]; - memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); - return state->nbperf; + memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); + return state->nbperf; } void label_counters(char **labels, void *ptr) { - counter_t state = (counter_t) ptr; - for(int i=0; i<state->nbperf; i++) - labels[i] = perf_static_info[state->perf_indexes[i]].name; + counter_t state = (counter_t) ptr; + for(int i=0; i<state->nbperf; i++) + labels[i] = perf_static_info[state->perf_indexes[i]].name; } diff --git a/src/frapl.c b/src/frapl.c index d0d0abf..f142c45 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -30,32 +30,32 @@ char *get_frapl_string(const char *filename) { - int fd = open(filename, O_RDONLY); - if( fd == -1) - return NULL; - char *result = malloc(MAX_HEADER); - int nb = read(fd, result, MAX_HEADER); - close(fd); - result[nb-1] = 0; - return (result); + int fd = open(filename, O_RDONLY); + if( fd == -1) + return NULL; + char *result = malloc(MAX_HEADER); + int nb = read(fd, result, MAX_HEADER); + close(fd); + result[nb-1] = 0; + return (result); } void test_append(char *name, int i) { - //char last = name[strlen(name)-1]; - //if (last>='0' && last <= '9') - // return; - sprintf(name+strlen(name), "%d", i); + //char last = name[strlen(name)-1]; + //if (last>='0' && last <= '9') + // return; + sprintf(name+strlen(name), "%d", i); } struct _frapl_t { - unsigned int nb; - char **names; - int *fids; - uint64_t *values; - uint64_t *tmp_values; + unsigned int nb; + char **names; + int *fids; + uint64_t *values; + uint64_t *tmp_values; }; typedef struct _frapl_t _frapl_t; @@ -63,112 +63,112 @@ typedef struct _frapl_t _frapl_t; void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) { - rapl->nb += 1; - rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); - rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); + rapl->nb += 1; + rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); + rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(strlen(name)+1); - strcpy(rapl->names[rapl->nb-1], name); - //printf("%s\n", energy_uj); + rapl->names[rapl->nb-1] = malloc(strlen(name)+1); + strcpy(rapl->names[rapl->nb-1], name); + //printf("%s\n", energy_uj); - rapl->fids[rapl->nb-1] = open(energy_uj, O_RDONLY); + rapl->fids[rapl->nb-1] = open(energy_uj, O_RDONLY); } void _get_frapl(uint64_t *values, _frapl_t *rapl) { - static char buffer[512]; + static char buffer[512]; - for (int i = 0; i < rapl->nb; i++) - { + for (int i = 0; i < rapl->nb; i++) + { - pread(rapl->fids[i], buffer, 100, 0); - values[i] = strtoull(buffer, NULL, 10); - } + pread(rapl->fids[i], buffer, 100, 0); + values[i] = strtoull(buffer, NULL, 10); + } } unsigned int init_frapl(char *none, void **ptr) { - _frapl_t *rapl = malloc(sizeof(_frapl_t)); - rapl->nb = 0; - rapl->names = NULL; - rapl->fids = NULL; - - char buffer[1024]; - char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; - char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - - for (int i=0;; i++) - { - sprintf(buffer, name_base, i, "name"); - char *tmp = get_frapl_string(buffer); - if (tmp == NULL) break; - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); - add_frapl_source(rapl, tmp, buffer); - free(tmp); - - for (int j=0;; j++) - { - sprintf(buffer, name_sub, i, i, j, "name"); - char *tmp_sub = get_frapl_string(buffer); - if (tmp_sub == NULL) break; - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - + _frapl_t *rapl = malloc(sizeof(_frapl_t)); + rapl->nb = 0; + rapl->names = NULL; + rapl->fids = NULL; - sprintf(buffer, name_sub, i, i, j, "energy_uj"); - add_frapl_source(rapl, tmp_sub, buffer); + char buffer[1024]; + char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; + char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - free(tmp_sub); + for (int i=0;; i++) + { + sprintf(buffer, name_base, i, "name"); + char *tmp = get_frapl_string(buffer); + if (tmp == NULL) break; + //printf("%s\n", tmp); + test_append(tmp, i); + //printf("%s -> %s\n", buffer, tmp); + + sprintf(buffer, name_base, i, "energy_uj"); + add_frapl_source(rapl, tmp, buffer); + free(tmp); + + for (int j=0;; j++) + { + sprintf(buffer, name_sub, i, i, j, "name"); + char *tmp_sub = get_frapl_string(buffer); + if (tmp_sub == NULL) break; + //printf("%s\n", tmp_sub); + test_append(tmp_sub, i); + //printf("%s -> %s\n", buffer, tmp_sub); + + + sprintf(buffer, name_sub, i, i, j, "energy_uj"); + add_frapl_source(rapl, tmp_sub, buffer); + + free(tmp_sub); + } } - } - rapl->values = calloc(sizeof(uint64_t), rapl->nb); - rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); + rapl->values = calloc(sizeof(uint64_t), rapl->nb); + rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); - _get_frapl(rapl->values, rapl); + _get_frapl(rapl->values, rapl); - *ptr = (void *)rapl; - return rapl->nb; + *ptr = (void *)rapl; + return rapl->nb; } unsigned int get_frapl(uint64_t *results, void *ptr) { - _frapl_t *state = (_frapl_t *) ptr; - _get_frapl(state->tmp_values, state); - for(int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; + _frapl_t *state = (_frapl_t *) ptr; + _get_frapl(state->tmp_values, state); + for(int i=0; i<state->nb; i++) + results[i] = state->tmp_values[i] - state->values[i]; - memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); - return state->nb; + memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); + return state->nb; } void clean_frapl(void *ptr) { - _frapl_t *rapl = (_frapl_t *) ptr; - for(int i=0; i<rapl->nb; i++) - { - free(rapl->names[i]); - close(rapl->fids[i]); - } - free(rapl->names); - free(rapl->fids); - free(rapl->values); - free(rapl->tmp_values); - free(rapl); + _frapl_t *rapl = (_frapl_t *) ptr; + for(int i=0; i<rapl->nb; i++) + { + free(rapl->names[i]); + close(rapl->fids[i]); + } + free(rapl->names); + free(rapl->fids); + free(rapl->values); + free(rapl->tmp_values); + free(rapl); } void label_frapl(char **labels, void *ptr) { - _frapl_t *rapl = (_frapl_t *) ptr; - for(int i=0; i<rapl->nb; i++) - labels[i] = rapl->names[i]; + _frapl_t *rapl = (_frapl_t *) ptr; + for(int i=0; i<rapl->nb; i++) + labels[i] = rapl->names[i]; } diff --git a/src/infiniband.c b/src/infiniband.c index e0daa2a..4c1da1d 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -28,53 +28,53 @@ struct network_t { - uint64_t values[4]; - uint64_t tmp_values[4]; - int sources[4]; + uint64_t values[4]; + uint64_t tmp_values[4]; + int sources[4]; }; unsigned int _get_network(uint64_t *results, int *sources); unsigned int init_infiniband(char *infi_path, void **ptr) { - if(infi_path==NULL) - return 0; + if(infi_path==NULL) + return 0; - if(strcmp(infi_path,"X")==0) - { + if(strcmp(infi_path,"X")==0) + { - glob_t res; + glob_t res; - glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); - if(res.gl_pathc == 0) - return 0; - infi_path = res.gl_pathv[0]; - } + glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); + if(res.gl_pathc == 0) + return 0; + infi_path = res.gl_pathv[0]; + } - char *filenames[] = {"%s/port_rcv_packets", - "%s/port_rcv_data", - "%s/port_xmit_packets", - "%s/port_xmit_data" - }; + char *filenames[] = {"%s/port_rcv_packets", + "%s/port_rcv_data", + "%s/port_xmit_packets", + "%s/port_xmit_data" + }; - struct network_t *state = malloc(sizeof(struct network_t)); + struct network_t *state = malloc(sizeof(struct network_t)); - char buffer[1024]; - for(int i=0; i<4; i++) - { - sprintf(buffer, filenames[i], infi_path); - state->sources[i] = open(buffer, O_RDONLY); - } + char buffer[1024]; + for(int i=0; i<4; i++) + { + sprintf(buffer, filenames[i], infi_path); + state->sources[i] = open(buffer, O_RDONLY); + } - *ptr = (void *) state; - _get_network(state->values, state->sources); + *ptr = (void *) state; + _get_network(state->values, state->sources); - return 4; + return 4; } char *_labels_infiniband[4] = {"irxp", "irxb", "itxp", "itxb"}; void label_infiniband(char **labels, void *none) { - for(int i=0; i<4; i++) - labels[i] = _labels_infiniband[i]; + for(int i=0; i<4; i++) + labels[i] = _labels_infiniband[i]; } diff --git a/src/load.c b/src/load.c index 80daf4b..e345119 100644 --- a/src/load.c +++ b/src/load.c @@ -32,39 +32,39 @@ static uint64_t tmp_load_values[10]= {0,0,0,0,0,0,0,0,0,0}; void _get_load(uint64_t *results) { - pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0); - int pos=0; - while(buffer[pos] > '9' || buffer[pos] < '0') pos++; - for(int i=0; i<10; i++) - { - results[i] = strtoull(buffer+pos, NULL, 10); - while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; - pos++; - } + pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0); + int pos=0; + while(buffer[pos] > '9' || buffer[pos] < '0') pos++; + for(int i=0; i<10; i++) + { + results[i] = strtoull(buffer+pos, NULL, 10); + while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; + pos++; + } } // Public interface unsigned int init_load(char *argument, void **state) { - load_fid = open("/proc/stat", O_RDONLY); - _get_load(load_values); - return 10; + load_fid = open("/proc/stat", O_RDONLY); + _get_load(load_values); + return 10; } unsigned int get_load(uint64_t *results, void *state) { - _get_load(tmp_load_values); - for(int i=0; i<10; i++) - results[i] = tmp_load_values[i] - load_values[i]; + _get_load(tmp_load_values); + for(int i=0; i<10; i++) + results[i] = tmp_load_values[i] - load_values[i]; - memcpy(load_values, tmp_load_values, sizeof(load_values)); - return 10; + memcpy(load_values, tmp_load_values, sizeof(load_values)); + return 10; } void clean_load(void *state) { - close(load_fid); + close(load_fid); } char *_labels[10] = {"user","nice","system","idle","iowait","irq", @@ -72,6 +72,6 @@ char *_labels[10] = {"user","nice","system","idle","iowait","irq", }; void label_load(char **labels, void *none) { - for(int i=0; i<10; i++) - labels[i] = _labels[i]; + for(int i=0; i<10; i++) + labels[i] = _labels[i]; } diff --git a/src/mojitos.c b/src/mojitos.c index 94954cf..23e71c3 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -37,20 +37,22 @@ void usage(char **argv) { - printf("Usage : %s [-t time] [-f freq] [-r] [-p perf_list] [-l] [-u] [-c] [-d network_device] [-i infiniband_path] [-o logfile] [-e command arguments...]\n", argv[0]); - printf("if time==0 then loops infinitively\n"); - printf("if -e is present, time and freq are not used\n"); - printf("-r activates RAPL\n"); - printf("-R activates the file version of RAPL\n"); - printf("-p activates performance counters\n"); - printf(" perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n"); - printf("-l lists the possible performance counters and quits\n"); - printf("-d activates network monitoring (if network_device is X, tries to detect it automatically)\n"); - printf("-i activates infiniband monitoring (if infiniband_path is X, tries to detect it automatically)\n"); - printf("-s activates statistics of overhead in nanoseconds\n"); - printf("-u activates report of system load\n"); - printf("-c activates report of processor temperature\n"); - exit(EXIT_SUCCESS); + printf("Usage : %s [-rRluc] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" + " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" + "if time==0 then loops infinitively\n" + "if -e is present, time and freq are not used\n" + "-r activates RAPL\n" + "-R activates the file version of RAPL\n" + "-p activates performance counters\n" + " perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n" + "-l lists the possible performance counters and quits\n" + "-d activates network monitoring (if network_device is X, tries to detect it automatically)\n" + "-i activates infiniband monitoring (if infiniband_path is X, tries to detect it automatically)\n" + "-s activates statistics of overhead in nanoseconds\n" + "-u activates report of system load\n" + "-c activates report of processor temperature\n" + , argv[0]); + exit(EXIT_SUCCESS); } void sighandler(int none) @@ -59,14 +61,14 @@ void sighandler(int none) void flush(int none) { - exit(0); + exit(0); } FILE *output; void flushexit() { - fflush(output); - fclose(output); + fflush(output); + fclose(output); } typedef unsigned int (initializer_t)(char *, void **); @@ -74,199 +76,223 @@ typedef void (labeler_t)(char **, void *); typedef unsigned int (*getter_t)(uint64_t *, void *); typedef void (*cleaner_t)(void *); -unsigned int nb_sources=0; -void **states=NULL; -getter_t *getter=NULL; -cleaner_t *cleaner=NULL; +unsigned int nb_sources = 0; +void **states = NULL; +getter_t *getter = NULL; +cleaner_t *cleaner = NULL; -unsigned int nb_sensors=0; -char **labels=NULL; -uint64_t *values=NULL; +unsigned int nb_sensors = 0; +char **labels = NULL; +uint64_t *values = NULL; void add_source(initializer_t init, char *arg, labeler_t labeler, getter_t get, cleaner_t clean) { - nb_sources++; - states = realloc(states, nb_sources*sizeof(void *)); - int nb = init(arg, &states[nb_sources-1]); - if (nb == 0) - { - nb_sources--; - states = realloc(states, nb_sources*sizeof(void *)); - return; - } - - getter = realloc(getter, nb_sources*sizeof(void *)); - getter[nb_sources-1] = get; - cleaner = realloc(cleaner, nb_sources*sizeof(void *)); - cleaner[nb_sources-1] = clean; - - labels = realloc(labels, (nb_sensors+nb)*sizeof(char *)); - labeler(labels+nb_sensors, states[nb_sources-1]); - - values = realloc(values, (nb_sensors+nb)*sizeof(uint64_t)); - nb_sensors += nb; + nb_sources++; + states = realloc(states, nb_sources * sizeof(void *)); + int nb = init(arg, &states[nb_sources - 1]); + if (nb == 0) + { + nb_sources--; + states = realloc(states, nb_sources * sizeof(void *)); + return; + } + + getter = realloc(getter, nb_sources * sizeof(void *)); + getter[nb_sources - 1] = get; + cleaner = realloc(cleaner, nb_sources * sizeof(void *)); + cleaner[nb_sources - 1] = clean; + + labels = realloc(labels, (nb_sensors + nb) * sizeof(char *)); + labeler(labels + nb_sensors, states[nb_sources - 1]); + + values = realloc(values, (nb_sensors + nb) * sizeof(uint64_t)); + nb_sensors += nb; } int main(int argc, char **argv) { - int total_time=1; - int delta=0; - int frequency=1; - char **application = NULL; - - int stat_mode = -1; - - if(argc==1) - usage(argv); - - output=stdout; - - atexit(flushexit); - signal(15, flush); - - int c; - while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application==NULL) - switch (c) - { - case 'f': - frequency=atoi(argv[optind]); - break; - case 't': - total_time=atoi(argv[optind]); - delta=1; - if(total_time==0) - { - total_time=1; - delta=0; - } - break; - case 'd': - add_source(init_network, argv[optind], label_network, get_network, clean_network); - break; - case 'i': - add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); - break; - case 'o': - output = fopen(argv[optind],"wb"); - break; - case 'e': - application=&argv[optind]; - signal(17,sighandler); - break; - case 'p': - add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); - break; - case 'r': - add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); - break; - case 'R': - add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); - break; - case 'u': - add_source(init_load, NULL, label_load, get_load, clean_load); - break; - case 'c': - add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); - break; - case 's': - stat_mode=0; - break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); - default: - usage(argv); - } - - - setvbuf(output, NULL, _IONBF, BUFSIZ); - struct timespec ts; - struct timespec ts_ref; - - fprintf(output, "#timestamp "); - - for(int i=0; i<nb_sensors; i++) - fprintf(output, "%s ", labels[i]); - - if(stat_mode==0) - fprintf(output, "overhead "); - - fprintf(output, "\n"); - - unsigned long int stat_data=0; - - for (int temps = 0; temps <total_time*frequency; temps+=delta) - { - clock_gettime(CLOCK_MONOTONIC, &ts_ref); - - // Get Data - unsigned int current = 0; - for(int i=0; i<nb_sources; i++) - current += getter[i](&values[current], states[i]); - - if(application != NULL) - { + int total_time = 1; + int delta = 0; + int frequency = 1; + char **application = NULL; - if(fork()==0) - { - execvp(application[0], application); - exit(0); - } - pause(); - clock_gettime(CLOCK_MONOTONIC, &ts); - if(ts.tv_nsec >= ts_ref.tv_nsec) - fprintf(output, "%ld.%09ld ", (ts.tv_sec-ts_ref.tv_sec), ts.tv_nsec-ts_ref.tv_nsec); - else - fprintf(output, "%ld.%09ld ", (ts.tv_sec-ts_ref.tv_sec)-1,1000000000+ts.tv_nsec-ts_ref.tv_nsec); - } - else + int stat_mode = -1; + + if (argc == 1) { -#ifdef DEBUG - clock_gettime(CLOCK_MONOTONIC, &ts); - fprintf(stderr, "%ld\n", (ts.tv_nsec-ts_ref.tv_nsec)/1000); - //Indiv: mean: 148 std: 31 % med: 141 std: 28 % - //Group: mean: 309 std: 41 % med: 297 std: 39 % -#endif - if(stat_mode==0) + usage(argv); + } + + output = stdout; + + atexit(flushexit); + signal(15, flush); + + int c; + while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) + switch (c) { - clock_gettime(CLOCK_MONOTONIC, &ts); - if(ts.tv_nsec >= ts_ref.tv_nsec) - stat_data = ts.tv_nsec-ts_ref.tv_nsec; - else - stat_data = 1000000000+ts.tv_nsec-ts_ref.tv_nsec; + case 'f': + frequency = atoi(argv[optind]); + break; + case 't': + total_time = atoi(argv[optind]); + delta = 1; + if (total_time == 0) + { + total_time = 1; + delta = 0; + } + break; + case 'd': + add_source(init_network, argv[optind], label_network, get_network, clean_network); + break; + case 'i': + add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); + break; + case 'o': + output = fopen(argv[optind], "wb"); + break; + case 'e': + application = &argv[optind]; + signal(17, sighandler); + break; + case 'p': + add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); + break; + case 'r': + add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); + break; + case 'R': + add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); + break; + case 'u': + add_source(init_load, NULL, label_load, get_load, clean_load); + break; + case 'c': + add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); + break; + case 's': + stat_mode = 0; + break; + case 'l': + show_all_counters(); + exit(EXIT_SUCCESS); + default: + usage(argv); } - // Treat Data - fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); - } - for(int i=0; i<nb_sensors; i++) - fprintf(output, "%" PRIu64 " ", values[i]); + setvbuf(output, NULL, _IONBF, BUFSIZ); + struct timespec ts; + struct timespec ts_ref; - if(stat_mode==0) - fprintf(output, "%ld ", stat_data); + fprintf(output, "#timestamp "); - fprintf(output, "\n"); + for (int i = 0; i < nb_sensors; i++) + { + fprintf(output, "%s ", labels[i]); + } - if(application != NULL) - break; + if (stat_mode == 0) + { + fprintf(output, "overhead "); + } - clock_gettime(CLOCK_MONOTONIC, &ts); - usleep(1000*1000/frequency-(ts.tv_nsec/1000)%(1000*1000/frequency)); - } + fprintf(output, "\n"); - for(int i=0; i<nb_sources; i++) - cleaner[i](states[i]); + unsigned long int stat_data = 0; - if(nb_sources > 0) - { - free(getter); - free(cleaner); - free(labels); - free(values); - free(states); - } + for (int temps = 0; temps < total_time * frequency; temps += delta) + { + clock_gettime(CLOCK_MONOTONIC, &ts_ref); + + // Get Data + unsigned int current = 0; + for (int i = 0; i < nb_sources; i++) + { + current += getter[i](&values[current], states[i]); + } + + if (application != NULL) + { + + if (fork() == 0) + { + execvp(application[0], application); + exit(0); + } + pause(); + clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) + { + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec), ts.tv_nsec - ts_ref.tv_nsec); + } + else + { + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000000000 + ts.tv_nsec - ts_ref.tv_nsec); + } + } + else + { +#ifdef DEBUG + clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stderr, "%ld\n", (ts.tv_nsec - ts_ref.tv_nsec) / 1000); + //Indiv: mean: 148 std: 31 % med: 141 std: 28 % + //Group: mean: 309 std: 41 % med: 297 std: 39 % +#endif + if (stat_mode == 0) + { + clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) + { + stat_data = ts.tv_nsec - ts_ref.tv_nsec; + } + else + { + stat_data = 1000000000 + ts.tv_nsec - ts_ref.tv_nsec; + } + } + + // Treat Data + fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); + } + + for (int i = 0; i < nb_sensors; i++) + { + fprintf(output, "%" PRIu64 " ", values[i]); + } + + if (stat_mode == 0) + { + fprintf(output, "%ld ", stat_data); + } + + fprintf(output, "\n"); + + if (application != NULL) + { + break; + } + + clock_gettime(CLOCK_MONOTONIC, &ts); + usleep(1000 * 1000 / frequency - (ts.tv_nsec / 1000) % (1000 * 1000 / frequency)); + } + + for (int i = 0; i < nb_sources; i++) + { + cleaner[i](states[i]); + } + + if (nb_sources > 0) + { + free(getter); + free(cleaner); + free(labels); + free(values); + free(states); + } } diff --git a/src/network.c b/src/network.c index 587319b..2cadf42 100644 --- a/src/network.c +++ b/src/network.c @@ -26,88 +26,88 @@ struct network_t { - uint64_t values[4]; - uint64_t tmp_values[4]; - int sources[4]; + uint64_t values[4]; + uint64_t tmp_values[4]; + int sources[4]; }; unsigned int _get_network(uint64_t *results, int *sources) { - if(sources==NULL) - return 0; - char buffer[128]; - for(int i=0; i<4; i++) - { - pread(sources[i], buffer, 127, 0); - - results[i] = strtoull(buffer, NULL, 10); - } - return 4; + if(sources==NULL) + return 0; + char buffer[128]; + for(int i=0; i<4; i++) + { + pread(sources[i], buffer, 127, 0); + + results[i] = strtoull(buffer, NULL, 10); + } + return 4; } unsigned int init_network(char *dev, void **ptr) { - if(dev==NULL) - return 0; - - if(strcmp(dev,"X")==0) - { - int f = open("/proc/net/route", O_RDONLY); - char buffer[1000]; - read(f, buffer, 999); - char *start_of_dev = index(buffer, '\n')+1; - char *end_of_dev = index(start_of_dev, '\t'); - *end_of_dev='\0'; - dev = start_of_dev; - close(f); - } - - char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", - "/sys/class/net/%s/statistics/rx_bytes", - "/sys/class/net/%s/statistics/tx_packets", - "/sys/class/net/%s/statistics/tx_bytes" - }; - - struct network_t *state = malloc(sizeof(struct network_t)); - - char buffer2[256]; - for(int i=0; i<4; i++) - { - sprintf(buffer2, filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); - } - *ptr = (void *) state; - _get_network(state->values, state->sources); - - return 4; + if(dev==NULL) + return 0; + + if(strcmp(dev,"X")==0) + { + int f = open("/proc/net/route", O_RDONLY); + char buffer[1000]; + read(f, buffer, 999); + char *start_of_dev = index(buffer, '\n')+1; + char *end_of_dev = index(start_of_dev, '\t'); + *end_of_dev='\0'; + dev = start_of_dev; + close(f); + } + + char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", + "/sys/class/net/%s/statistics/rx_bytes", + "/sys/class/net/%s/statistics/tx_packets", + "/sys/class/net/%s/statistics/tx_bytes" + }; + + struct network_t *state = malloc(sizeof(struct network_t)); + + char buffer2[256]; + for(int i=0; i<4; i++) + { + sprintf(buffer2, filenames[i], dev); + state->sources[i] = open(buffer2, O_RDONLY); + } + *ptr = (void *) state; + _get_network(state->values, state->sources); + + return 4; } unsigned int get_network(uint64_t *results, void *ptr) { - struct network_t *state = (struct network_t *) ptr; - _get_network(state->tmp_values, state->sources); - for(int i=0; i<4; i++) - results[i] = state->tmp_values[i] - state->values[i]; + struct network_t *state = (struct network_t *) ptr; + _get_network(state->tmp_values, state->sources); + for(int i=0; i<4; i++) + results[i] = state->tmp_values[i] - state->values[i]; - memcpy(state->values, state->tmp_values, 4*sizeof(uint64_t)); - return 4; + memcpy(state->values, state->tmp_values, 4*sizeof(uint64_t)); + return 4; } void clean_network(void *ptr) { - struct network_t *state = (struct network_t *) ptr; - if(state==NULL) - return; - for(int i=0; i<4; i++) - close(state->sources[i]); - free(state); + struct network_t *state = (struct network_t *) ptr; + if(state==NULL) + return; + for(int i=0; i<4; i++) + close(state->sources[i]); + free(state); } char *_labels_network[4] = {"rxp", "rxb", "txp", "txb"}; void label_network(char **labels, void *none) { - for(int i=0; i<4; i++) - labels[i] = _labels_network[i]; + for(int i=0; i<4; i++) + labels[i] = _labels_network[i]; } diff --git a/src/rapl.c b/src/rapl.c index 2536600..044a1b7 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -26,14 +26,14 @@ struct _rapl_t { - powercap_rapl_pkg *pkgs; - uint32_t nb_pkgs; - uint32_t nb; - char **names; - uint32_t *zones; - uint32_t *packages; - uint64_t *values; - uint64_t *tmp_values; + powercap_rapl_pkg *pkgs; + uint32_t nb_pkgs; + uint32_t nb; + char **names; + uint32_t *zones; + uint32_t *packages; + uint64_t *values; + uint64_t *tmp_values; }; typedef struct _rapl_t _rapl_t; @@ -52,101 +52,101 @@ const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_COR // values [zone + package *nbzones] microjoules void _get_rapl(uint64_t *values, _rapl_t *rapl) { - for (int i = 0; i < rapl->nb; i++) - { + for (int i = 0; i < rapl->nb; i++) + { #ifdef DEBUG - int ret = + int ret = #endif - powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], - rapl->zones[i], - &values[i]); + powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], + rapl->zones[i], + &values[i]); #ifdef DEBUG - printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); + printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); #endif - } + } } unsigned int init_rapl(char *none, void **ptr) { - // get number of processor sockets - _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); - rapl->nb = 0; - rapl->packages = NULL; - rapl->zones = NULL; - - rapl->nb_pkgs = powercap_rapl_get_num_instances(); - //rapl->nb_pkgs = powercap_rapl_get_num_packages(); - - if (rapl->nb_pkgs == 0) - { - perror("no packages found (maybe the kernel module isn't loaded?)"); - exit(-1); - } - rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); - for (int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) - { - perror("powercap_rapl_init, check access (root needed ?)"); - exit(-1); - } - - rapl->names = NULL; - - char _name[MAX_LEN_NAME+1]; - char _name2[MAX_LEN_NAME+11]; - - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - { - for(unsigned int zone=0; zone < nb_zones; zone++) + // get number of processor sockets + _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); + rapl->nb = 0; + rapl->packages = NULL; + rapl->zones = NULL; + + rapl->nb_pkgs = powercap_rapl_get_num_instances(); + //rapl->nb_pkgs = powercap_rapl_get_num_packages(); + + if (rapl->nb_pkgs == 0) { - int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], - _name, MAX_LEN_NAME); - if (length>0) + perror("no packages found (maybe the kernel module isn't loaded?)"); + exit(-1); + } + rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); + for (int package = 0; package < rapl->nb_pkgs; package++) + if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { + perror("powercap_rapl_init, check access (root needed ?)"); + exit(-1); + } - sprintf(_name2, "%s%u", _name, package); + rapl->names = NULL; - rapl->nb++; - rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); - rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); - rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); + char _name[MAX_LEN_NAME+1]; + char _name2[MAX_LEN_NAME+11]; - strcpy(rapl->names[rapl->nb-1], _name2); - rapl->zones[rapl->nb-1] = rapl_zones[zone]; - rapl->packages[rapl->nb-1] = package; - } + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) + { + for(unsigned int zone=0; zone < nb_zones; zone++) + { + int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], + _name, MAX_LEN_NAME); + if (length>0) + { + + sprintf(_name2, "%s%u", _name, package); + + rapl->nb++; + rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); + rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); + rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); + rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); + + strcpy(rapl->names[rapl->nb-1], _name2); + rapl->zones[rapl->nb-1] = rapl_zones[zone]; + rapl->packages[rapl->nb-1] = package; + } #ifdef DEBUG - printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); + printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); #endif + } } - } #ifdef DEBUG - printf("Result of init\n"); - for(int i=0; i<rapl->nb; i++) - printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); + printf("Result of init\n"); + for(int i=0; i<rapl->nb; i++) + printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); #endif - rapl->values = calloc(sizeof(uint64_t), rapl->nb); - rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); + rapl->values = calloc(sizeof(uint64_t), rapl->nb); + rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); - _get_rapl(rapl->values, rapl); + _get_rapl(rapl->values, rapl); - *ptr = (void *)rapl; - return rapl->nb; + *ptr = (void *)rapl; + return rapl->nb; } unsigned int get_rapl(uint64_t *results, void *ptr) { - _rapl_t *state = (_rapl_t *) ptr; - _get_rapl(state->tmp_values, state); - for(int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; + _rapl_t *state = (_rapl_t *) ptr; + _get_rapl(state->tmp_values, state); + for(int i=0; i<state->nb; i++) + results[i] = state->tmp_values[i] - state->values[i]; - memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); - return state->nb; + memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); + return state->nb; } @@ -154,25 +154,25 @@ unsigned int get_rapl(uint64_t *results, void *ptr) void clean_rapl(void *ptr) { - _rapl_t *rapl = (_rapl_t *) ptr; - for (int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_destroy(&rapl->pkgs[package])) - perror("powercap_rapl_destroy"); - for (int elem=0; elem<rapl->nb; elem++) - free(rapl->names[elem]); - - free(rapl->names); - free(rapl->pkgs); - free(rapl->zones); - free(rapl->packages); - free(rapl->values); - free(rapl->tmp_values); - free(rapl); + _rapl_t *rapl = (_rapl_t *) ptr; + for (int package = 0; package < rapl->nb_pkgs; package++) + if (powercap_rapl_destroy(&rapl->pkgs[package])) + perror("powercap_rapl_destroy"); + for (int elem=0; elem<rapl->nb; elem++) + free(rapl->names[elem]); + + free(rapl->names); + free(rapl->pkgs); + free(rapl->zones); + free(rapl->packages); + free(rapl->values); + free(rapl->tmp_values); + free(rapl); } void label_rapl(char **labels, void *ptr) { - _rapl_t *rapl = (_rapl_t *) ptr; - for(int i=0; i<rapl->nb; i++) - labels[i] = rapl->names[i]; + _rapl_t *rapl = (_rapl_t *) ptr; + for(int i=0; i<rapl->nb; i++) + labels[i] = rapl->names[i]; } diff --git a/src/temperature.c b/src/temperature.c index 9dec997..e9282dc 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -27,125 +27,125 @@ struct temperature_t { - char **label_list; - int *fid_list; - int nb_elem; + char **label_list; + int *fid_list; + int nb_elem; }; int get_string(char *filename, char *buffer, int max_size) { - int fid = open(filename, O_RDONLY); - //printf("Tries to open : %s : %d\n", filename, fid); - if(fid == -1) - return -1; - - int nb = read(fid, buffer, max_size); - if(nb == -1) - { - close(fid); - return -1; - } - - buffer[nb]=0; - close(fid); - return 0; + int fid = open(filename, O_RDONLY); + //printf("Tries to open : %s : %d\n", filename, fid); + if(fid == -1) + return -1; + + int nb = read(fid, buffer, max_size); + if(nb == -1) + { + close(fid); + return -1; + } + + buffer[nb]=0; + close(fid); + return 0; } void add_to_list(char ***list_name, char *source, int nb_elem) { - //printf("Adds: %s\n", source); - *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char *)); - (*list_name)[nb_elem] = malloc(strlen(source)+1); - strcpy((*list_name)[nb_elem], source); + //printf("Adds: %s\n", source); + *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char *)); + (*list_name)[nb_elem] = malloc(strlen(source)+1); + strcpy((*list_name)[nb_elem], source); } void add_temperature_sensor(int id_rep, struct temperature_t *state) { - static int key=0; - static char buffer_filename[512]; - static char buffer_label[512]; + static int key=0; + static char buffer_filename[512]; + static char buffer_label[512]; - int delta = sprintf(buffer_label, "Temp_%d_", key); + int delta = sprintf(buffer_label, "Temp_%d_", key); - for(int i=1;; i++) - { - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); - if(get_string(buffer_filename, buffer_label+delta, 100) == -1) - break; - - for(int pos = 0; pos < strlen(buffer_label); pos++) + for(int i=1;; i++) { - if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; - if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); + if(get_string(buffer_filename, buffer_label+delta, 100) == -1) + break; + + for(int pos = 0; pos < strlen(buffer_label); pos++) + { + if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; + if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; + } + add_to_list(&state->label_list, buffer_label, state->nb_elem); + + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); + state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); + state->fid_list[state->nb_elem] = open(buffer_filename, O_RDONLY); + + state->nb_elem++; + // printf("%s : %s\n", buffer_label, buffer_filename); } - add_to_list(&state->label_list, buffer_label, state->nb_elem); - - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); - state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); - state->fid_list[state->nb_elem] = open(buffer_filename, O_RDONLY); - state->nb_elem++; - // printf("%s : %s\n", buffer_label, buffer_filename); - } - - key++; + key++; } unsigned int init_temperature(char *args, void **ptr) { - struct temperature_t *state = malloc(sizeof(struct temperature_t)); - state->nb_elem = 0; - state->label_list = NULL; - state->fid_list = NULL; - - char base_name[] = "/sys/class/hwmon/hwmon%d/name"; - static char name[512]; - static char buffer[512]; - - int i = 0; - sprintf(name, base_name, i); - while(get_string(name, buffer, 8) != -1) - { - if (strcmp(buffer, "coretemp")==0) - add_temperature_sensor(i, state); - - i++; - sprintf(name, base_name, i); - } - *ptr = (void *) state; - return state->nb_elem; + struct temperature_t *state = malloc(sizeof(struct temperature_t)); + state->nb_elem = 0; + state->label_list = NULL; + state->fid_list = NULL; + + char base_name[] = "/sys/class/hwmon/hwmon%d/name"; + static char name[512]; + static char buffer[512]; + + int i = 0; + sprintf(name, base_name, i); + while(get_string(name, buffer, 8) != -1) + { + if (strcmp(buffer, "coretemp")==0) + add_temperature_sensor(i, state); + + i++; + sprintf(name, base_name, i); + } + *ptr = (void *) state; + return state->nb_elem; } unsigned int get_temperature(uint64_t *results, void *ptr) { - struct temperature_t *state = (struct temperature_t *)ptr; - static char buffer[512]; - for(int i=0; i<state->nb_elem; i++) - { - pread(state->fid_list[i], buffer, 100, 0); - results[i] = strtoull(buffer, NULL, 10); - } - return state->nb_elem; + struct temperature_t *state = (struct temperature_t *)ptr; + static char buffer[512]; + for(int i=0; i<state->nb_elem; i++) + { + pread(state->fid_list[i], buffer, 100, 0); + results[i] = strtoull(buffer, NULL, 10); + } + return state->nb_elem; } void clean_temperature(void *ptr) { - struct temperature_t *state = (struct temperature_t *)ptr; - - for(int i=0; i<state->nb_elem; i++) - { - free(state->label_list[i]); - close(state->fid_list[i]); - } - free(state->label_list); - free(state->fid_list); - free(state); + struct temperature_t *state = (struct temperature_t *)ptr; + + for(int i=0; i<state->nb_elem; i++) + { + free(state->label_list[i]); + close(state->fid_list[i]); + } + free(state->label_list); + free(state->fid_list); + free(state); } void label_temperature(char **labels, void *ptr) { - struct temperature_t *state = (struct temperature_t *)ptr; - for(int i=0; i<state->nb_elem; i++) - labels[i] = state->label_list[i]; + struct temperature_t *state = (struct temperature_t *)ptr; + for(int i=0; i<state->nb_elem; i++) + labels[i] = state->label_list[i]; } -- GitLab From 6739c0277c2c1fad4833e00b8203e47a570143f4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 8 Jan 2023 08:22:18 +0000 Subject: [PATCH 004/125] Replace multiple occurrences of int with define --- src/network.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/network.c b/src/network.c index 2cadf42..1032c85 100644 --- a/src/network.c +++ b/src/network.c @@ -24,11 +24,13 @@ #include <string.h> #include <stdint.h> +#define NB_SENSOR 4 + struct network_t { - uint64_t values[4]; - uint64_t tmp_values[4]; - int sources[4]; + uint64_t values[NB_SENSOR]; + uint64_t tmp_values[NB_SENSOR]; + int sources[NB_SENSOR]; }; unsigned int _get_network(uint64_t *results, int *sources) @@ -36,13 +38,13 @@ unsigned int _get_network(uint64_t *results, int *sources) if(sources==NULL) return 0; char buffer[128]; - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) { pread(sources[i], buffer, 127, 0); results[i] = strtoull(buffer, NULL, 10); } - return 4; + return NB_SENSOR; } @@ -73,7 +75,7 @@ unsigned int init_network(char *dev, void **ptr) struct network_t *state = malloc(sizeof(struct network_t)); char buffer2[256]; - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) { sprintf(buffer2, filenames[i], dev); state->sources[i] = open(buffer2, O_RDONLY); @@ -81,18 +83,18 @@ unsigned int init_network(char *dev, void **ptr) *ptr = (void *) state; _get_network(state->values, state->sources); - return 4; + return NB_SENSOR; } unsigned int get_network(uint64_t *results, void *ptr) { struct network_t *state = (struct network_t *) ptr; _get_network(state->tmp_values, state->sources); - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) results[i] = state->tmp_values[i] - state->values[i]; - memcpy(state->values, state->tmp_values, 4*sizeof(uint64_t)); - return 4; + memcpy(state->values, state->tmp_values, NB_SENSOR*sizeof(uint64_t)); + return NB_SENSOR; } void clean_network(void *ptr) @@ -100,14 +102,14 @@ void clean_network(void *ptr) struct network_t *state = (struct network_t *) ptr; if(state==NULL) return; - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) close(state->sources[i]); free(state); } -char *_labels_network[4] = {"rxp", "rxb", "txp", "txb"}; +char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; void label_network(char **labels, void *none) { - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_network[i]; } -- GitLab From 13f506f0c8554e67bac9c3a82424f931492425f4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 8 Jan 2023 08:25:19 +0000 Subject: [PATCH 005/125] Replace multiple occurrences of int with define --- src/infiniband.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/infiniband.c b/src/infiniband.c index 4c1da1d..1f0171b 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -26,11 +26,13 @@ #include <stdint.h> +#define NB_SENSOR 4 + struct network_t { - uint64_t values[4]; - uint64_t tmp_values[4]; - int sources[4]; + uint64_t values[NB_SENSOR]; + uint64_t tmp_values[NB_SENSOR]; + int sources[NB_SENSOR]; }; unsigned int _get_network(uint64_t *results, int *sources); @@ -60,7 +62,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) struct network_t *state = malloc(sizeof(struct network_t)); char buffer[1024]; - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) { sprintf(buffer, filenames[i], infi_path); state->sources[i] = open(buffer, O_RDONLY); @@ -69,12 +71,12 @@ unsigned int init_infiniband(char *infi_path, void **ptr) *ptr = (void *) state; _get_network(state->values, state->sources); - return 4; + return NB_SENSOR; } -char *_labels_infiniband[4] = {"irxp", "irxb", "itxp", "itxb"}; +char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; void label_infiniband(char **labels, void *none) { - for(int i=0; i<4; i++) + for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_infiniband[i]; } -- GitLab From 49467488ab26107953f6772084980d3bc088538e Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 8 Jan 2023 10:57:33 +0000 Subject: [PATCH 006/125] Fix: error handling --- src/frapl.c | 21 ++++++++++++++++++--- src/load.c | 16 ++++++++++++++-- src/network.c | 26 ++++++++++++++++++++++---- src/temperature.c | 16 +++++++++++++--- 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/frapl.c b/src/frapl.c index f142c45..438af03 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -24,6 +24,7 @@ #include <unistd.h> #include <fcntl.h> #include <inttypes.h> +#include <errno.h> #define MAX_HEADER 128 @@ -32,7 +33,9 @@ char *get_frapl_string(const char *filename) { int fd = open(filename, O_RDONLY); if( fd == -1) - return NULL; + { + return NULL; + } char *result = malloc(MAX_HEADER); int nb = read(fd, result, MAX_HEADER); close(fd); @@ -71,7 +74,15 @@ void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) strcpy(rapl->names[rapl->nb-1], name); //printf("%s\n", energy_uj); - rapl->fids[rapl->nb-1] = open(energy_uj, O_RDONLY); + int fd = open(energy_uj, O_RDONLY); + + if (fd < 0) + { + fprintf(stderr, "%s ", energy_uj); + perror("open"); + exit(1); + } + rapl->fids[rapl->nb-1] = fd; } @@ -82,7 +93,11 @@ void _get_frapl(uint64_t *values, _frapl_t *rapl) for (int i = 0; i < rapl->nb; i++) { - pread(rapl->fids[i], buffer, 100, 0); + if (pread(rapl->fids[i], buffer, 100, 0) < 0) + { + perror("pread"); + exit(1); + } values[i] = strtoull(buffer, NULL, 10); } } diff --git a/src/load.c b/src/load.c index e345119..5a909b6 100644 --- a/src/load.c +++ b/src/load.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <stdio.h> #define LOAD_BUFFER_SIZE 1024 char buffer[LOAD_BUFFER_SIZE]; @@ -29,10 +30,15 @@ char buffer[LOAD_BUFFER_SIZE]; static int load_fid=-1; static uint64_t load_values[10]= {0,0,0,0,0,0,0,0,0,0}; static uint64_t tmp_load_values[10]= {0,0,0,0,0,0,0,0,0,0}; +static char *stat = "/proc/stat"; void _get_load(uint64_t *results) { - pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0); + if (pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0) < 0) + { + perror("pread"); + exit(1); + } int pos=0; while(buffer[pos] > '9' || buffer[pos] < '0') pos++; for(int i=0; i<10; i++) @@ -47,7 +53,13 @@ void _get_load(uint64_t *results) unsigned int init_load(char *argument, void **state) { - load_fid = open("/proc/stat", O_RDONLY); + load_fid = open(stat, O_RDONLY); + if (load_fid < 0) + { + fprintf(stderr,"%s ",stat); + perror("open"); + exit(1); + } _get_load(load_values); return 10; } diff --git a/src/network.c b/src/network.c index 1032c85..7a22f23 100644 --- a/src/network.c +++ b/src/network.c @@ -26,6 +26,7 @@ #define NB_SENSOR 4 +static char *route = "/proc/net/route"; struct network_t { uint64_t values[NB_SENSOR]; @@ -40,7 +41,11 @@ unsigned int _get_network(uint64_t *results, int *sources) char buffer[128]; for(int i=0; i<NB_SENSOR; i++) { - pread(sources[i], buffer, 127, 0); + if (pread(sources[i], buffer, 127, 0) < 0) + { + perror("pread"); + exit(1); + } results[i] = strtoull(buffer, NULL, 10); } @@ -56,14 +61,27 @@ unsigned int init_network(char *dev, void **ptr) if(strcmp(dev,"X")==0) { - int f = open("/proc/net/route", O_RDONLY); + int fd = open(route, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "%s ", route); + perror("open"); + exit(1); + } char buffer[1000]; - read(f, buffer, 999); + + if ( read(fd, buffer, 999) < 0 ) + { + perror("read"); + close(fd); + exit(1); + } + char *start_of_dev = index(buffer, '\n')+1; char *end_of_dev = index(start_of_dev, '\t'); *end_of_dev='\0'; dev = start_of_dev; - close(f); + close(fd); } char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", diff --git a/src/temperature.c b/src/temperature.c index e9282dc..d3e4c99 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -83,8 +83,14 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); - state->fid_list[state->nb_elem] = open(buffer_filename, O_RDONLY); - + int fd = open(buffer_filename, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "%s ", buffer_filename); + perror("open"); + exit(1); + } + state->fid_list[state->nb_elem] = fd; state->nb_elem++; // printf("%s : %s\n", buffer_label, buffer_filename); } @@ -123,7 +129,11 @@ unsigned int get_temperature(uint64_t *results, void *ptr) static char buffer[512]; for(int i=0; i<state->nb_elem; i++) { - pread(state->fid_list[i], buffer, 100, 0); + if (pread(state->fid_list[i], buffer, 100, 0) < 0) + { + perror("pread"); + exit(1); + } results[i] = strtoull(buffer, NULL, 10); } return state->nb_elem; -- GitLab From 78bb763f196699ccc098d0ff2ee4048573ce03d4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 8 Jan 2023 12:10:26 +0000 Subject: [PATCH 007/125] fix: Werror flag --- makefile | 2 +- src/frapl.c | 15 +++++++++------ src/load.c | 3 +++ src/network.c | 2 ++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/makefile b/makefile index 6aaf27c..cca83e7 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters_individual.o rapl.o frapl. OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc -CFLAGS = -std=gnu99 -O3 -Wall # -Wextra -Werror -Wpedantic +CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic ASTYLE = astyle --style=gnu -xf -s4 -k3 -n -Z -Q diff --git a/src/frapl.c b/src/frapl.c index 438af03..1cc0ef9 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -28,6 +28,8 @@ #define MAX_HEADER 128 +#define UNUSED(expr) do { (void)(expr); } while (0) + char *get_frapl_string(const char *filename) { @@ -90,7 +92,7 @@ void _get_frapl(uint64_t *values, _frapl_t *rapl) { static char buffer[512]; - for (int i = 0; i < rapl->nb; i++) + for (unsigned int i = 0; i < rapl->nb; i++) { if (pread(rapl->fids[i], buffer, 100, 0) < 0) @@ -105,6 +107,7 @@ void _get_frapl(uint64_t *values, _frapl_t *rapl) unsigned int init_frapl(char *none, void **ptr) { + UNUSED(none); _frapl_t *rapl = malloc(sizeof(_frapl_t)); rapl->nb = 0; rapl->names = NULL; @@ -114,7 +117,7 @@ unsigned int init_frapl(char *none, void **ptr) char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - for (int i=0;; i++) + for (unsigned int i=0;; i++) { sprintf(buffer, name_base, i, "name"); char *tmp = get_frapl_string(buffer); @@ -127,7 +130,7 @@ unsigned int init_frapl(char *none, void **ptr) add_frapl_source(rapl, tmp, buffer); free(tmp); - for (int j=0;; j++) + for (unsigned int j=0;; j++) { sprintf(buffer, name_sub, i, i, j, "name"); char *tmp_sub = get_frapl_string(buffer); @@ -158,7 +161,7 @@ unsigned int get_frapl(uint64_t *results, void *ptr) { _frapl_t *state = (_frapl_t *) ptr; _get_frapl(state->tmp_values, state); - for(int i=0; i<state->nb; i++) + for(unsigned int i=0; i<state->nb; i++) results[i] = state->tmp_values[i] - state->values[i]; memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); @@ -168,7 +171,7 @@ unsigned int get_frapl(uint64_t *results, void *ptr) void clean_frapl(void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(int i=0; i<rapl->nb; i++) + for(unsigned int i=0; i<rapl->nb; i++) { free(rapl->names[i]); close(rapl->fids[i]); @@ -184,6 +187,6 @@ void clean_frapl(void *ptr) void label_frapl(char **labels, void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(int i=0; i<rapl->nb; i++) + for(unsigned int i=0; i<rapl->nb; i++) labels[i] = rapl->names[i]; } diff --git a/src/load.c b/src/load.c index 5a909b6..18c49a4 100644 --- a/src/load.c +++ b/src/load.c @@ -25,6 +25,7 @@ #include <stdio.h> #define LOAD_BUFFER_SIZE 1024 +#define UNUSED(expr) do { (void)(expr); } while (0) char buffer[LOAD_BUFFER_SIZE]; static int load_fid=-1; @@ -53,6 +54,8 @@ void _get_load(uint64_t *results) unsigned int init_load(char *argument, void **state) { + UNUSED(argument); + UNUSED(state); load_fid = open(stat, O_RDONLY); if (load_fid < 0) { diff --git a/src/network.c b/src/network.c index 7a22f23..d9575af 100644 --- a/src/network.c +++ b/src/network.c @@ -25,6 +25,7 @@ #include <stdint.h> #define NB_SENSOR 4 +#define UNUSED(expr) do { (void)(expr); } while (0) static char *route = "/proc/net/route"; struct network_t @@ -128,6 +129,7 @@ void clean_network(void *ptr) char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; void label_network(char **labels, void *none) { + UNUSED(none); for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_network[i]; } -- GitLab From 5e9585022ae6f8935461621f8843090b95480aff Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 8 Jan 2023 12:59:31 +0000 Subject: [PATCH 008/125] fix: unused --- src/load.c | 3 +++ src/mojitos.c | 12 +++++++----- src/temperature.c | 5 ++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/load.c b/src/load.c index 18c49a4..33ebdbf 100644 --- a/src/load.c +++ b/src/load.c @@ -69,6 +69,7 @@ unsigned int init_load(char *argument, void **state) unsigned int get_load(uint64_t *results, void *state) { + UNUSED(state); _get_load(tmp_load_values); for(int i=0; i<10; i++) results[i] = tmp_load_values[i] - load_values[i]; @@ -79,6 +80,7 @@ unsigned int get_load(uint64_t *results, void *state) void clean_load(void *state) { + UNUSED(state); close(load_fid); } @@ -87,6 +89,7 @@ char *_labels[10] = {"user","nice","system","idle","iowait","irq", }; void label_load(char **labels, void *none) { + UNUSED(none); for(int i=0; i<10; i++) labels[i] = _labels[i]; } diff --git a/src/mojitos.c b/src/mojitos.c index 23e71c3..ed6b462 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -33,7 +33,7 @@ #include "load.h" #include "temperature.h" - +#define UNUSED(expr) do { (void)(expr); } while (0) void usage(char **argv) { @@ -57,10 +57,12 @@ void usage(char **argv) void sighandler(int none) { + UNUSED(none); } void flush(int none) { + UNUSED(none); exit(0); } @@ -190,7 +192,7 @@ int main(int argc, char **argv) fprintf(output, "#timestamp "); - for (int i = 0; i < nb_sensors; i++) + for (unsigned int i = 0; i < nb_sensors; i++) { fprintf(output, "%s ", labels[i]); } @@ -210,7 +212,7 @@ int main(int argc, char **argv) // Get Data unsigned int current = 0; - for (int i = 0; i < nb_sources; i++) + for (unsigned int i = 0; i < nb_sources; i++) { current += getter[i](&values[current], states[i]); } @@ -259,7 +261,7 @@ int main(int argc, char **argv) fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); } - for (int i = 0; i < nb_sensors; i++) + for (unsigned int i = 0; i < nb_sensors; i++) { fprintf(output, "%" PRIu64 " ", values[i]); } @@ -280,7 +282,7 @@ int main(int argc, char **argv) usleep(1000 * 1000 / frequency - (ts.tv_nsec / 1000) % (1000 * 1000 / frequency)); } - for (int i = 0; i < nb_sources; i++) + for (unsigned int i = 0; i < nb_sources; i++) { cleaner[i](states[i]); } diff --git a/src/temperature.c b/src/temperature.c index d3e4c99..e210f7b 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -25,6 +25,8 @@ #include <stdio.h> #include <stdint.h> +#define UNUSED(expr) do { (void)(expr); } while (0) + struct temperature_t { char **label_list; @@ -74,7 +76,7 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) if(get_string(buffer_filename, buffer_label+delta, 100) == -1) break; - for(int pos = 0; pos < strlen(buffer_label); pos++) + for(unsigned int pos = 0; pos < strlen(buffer_label); pos++) { if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; @@ -100,6 +102,7 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) unsigned int init_temperature(char *args, void **ptr) { + UNUSED(args); struct temperature_t *state = malloc(sizeof(struct temperature_t)); state->nb_elem = 0; state->label_list = NULL; -- GitLab From 165260432f2bfa39c581932e4beaf51fbc206217 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 8 Jan 2023 13:14:41 +0000 Subject: [PATCH 009/125] fix unsigned & unused --- src/counters_individual.c | 6 +++--- src/infiniband.c | 2 ++ src/rapl.c | 17 ++++++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/counters_individual.c b/src/counters_individual.c index aff7fd0..0f597ad 100644 --- a/src/counters_individual.c +++ b/src/counters_individual.c @@ -45,7 +45,7 @@ typedef struct _counter_t *counter_t; void show_all_counters() { - for(int i=0; i<nb_counter_option; i++) + for(unsigned int i=0; i<nb_counter_option; i++) printf("%s\n", perf_static_info[i].name); } @@ -67,7 +67,7 @@ void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) while((token=strtok(perf_string, ",")) != NULL) { perf_string = NULL; - int i; + unsigned int i; for(i=0; i<nb_counter_option; i++) { if(strcmp(perf_static_info[i].name, token) == 0) @@ -117,7 +117,7 @@ counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *nam pe.config = names[i]; counters->counters[i] = malloc(nbcores*sizeof(int)); - for (int core=0; core<nbcores; core++) + for (unsigned int core=0; core<nbcores; core++) { counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); } diff --git a/src/infiniband.c b/src/infiniband.c index 1f0171b..7c6fff4 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -27,6 +27,7 @@ #include <stdint.h> #define NB_SENSOR 4 +#define UNUSED(expr) do { (void)(expr); } while (0) struct network_t { @@ -77,6 +78,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; void label_infiniband(char **labels, void *none) { + UNUSED(none); for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_infiniband[i]; } diff --git a/src/rapl.c b/src/rapl.c index 044a1b7..ab1b38c 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -24,6 +24,8 @@ #include <powercap/powercap-rapl.h> +#define UNUSED(expr) do { (void)(expr); } while (0) + struct _rapl_t { powercap_rapl_pkg *pkgs; @@ -52,7 +54,7 @@ const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_COR // values [zone + package *nbzones] microjoules void _get_rapl(uint64_t *values, _rapl_t *rapl) { - for (int i = 0; i < rapl->nb; i++) + for (unsigned int i = 0; i < rapl->nb; i++) { #ifdef DEBUG int ret = @@ -68,6 +70,7 @@ void _get_rapl(uint64_t *values, _rapl_t *rapl) unsigned int init_rapl(char *none, void **ptr) { + UNUSED(none); // get number of processor sockets _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); rapl->nb = 0; @@ -83,7 +86,7 @@ unsigned int init_rapl(char *none, void **ptr) exit(-1); } rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); - for (int package = 0; package < rapl->nb_pkgs; package++) + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { perror("powercap_rapl_init, check access (root needed ?)"); @@ -123,7 +126,7 @@ unsigned int init_rapl(char *none, void **ptr) } #ifdef DEBUG printf("Result of init\n"); - for(int i=0; i<rapl->nb; i++) + for(unsigned int i=0; i<rapl->nb; i++) printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); #endif @@ -142,7 +145,7 @@ unsigned int get_rapl(uint64_t *results, void *ptr) { _rapl_t *state = (_rapl_t *) ptr; _get_rapl(state->tmp_values, state); - for(int i=0; i<state->nb; i++) + for(unsigned int i=0; i<state->nb; i++) results[i] = state->tmp_values[i] - state->values[i]; memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); @@ -155,10 +158,10 @@ unsigned int get_rapl(uint64_t *results, void *ptr) void clean_rapl(void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; - for (int package = 0; package < rapl->nb_pkgs; package++) + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) if (powercap_rapl_destroy(&rapl->pkgs[package])) perror("powercap_rapl_destroy"); - for (int elem=0; elem<rapl->nb; elem++) + for (unsigned int elem=0; elem<rapl->nb; elem++) free(rapl->names[elem]); free(rapl->names); @@ -173,6 +176,6 @@ void clean_rapl(void *ptr) void label_rapl(char **labels, void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; - for(int i=0; i<rapl->nb; i++) + for(unsigned int i=0; i<rapl->nb; i++) labels[i] = rapl->names[i]; } -- GitLab From 12903e30bd1f3911024a4661581782d7f31b06ca Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 9 Jan 2023 07:50:54 +0000 Subject: [PATCH 010/125] feature: builder, python to bash --- src/counters_option.sh | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/counters_option.sh diff --git a/src/counters_option.sh b/src/counters_option.sh new file mode 100644 index 0000000..7d01bb7 --- /dev/null +++ b/src/counters_option.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + +linux_include="/usr/include/linux/perf_event.h" + +string="#include <linux/perf_event.h> + +typedef struct counter_option { + char *name; + __u32 perf_type; + __u64 perf_key; +} counter_option; + +static counter_option perf_static_info[] = {" +echo "$string" + +nb=0 + +black_list=( "stalled_cycles_frontend" "stalled_cycles_backend" "cache_l1i" "cache_op_write" "cache_result_miss" ) + +while IFS= read -r line; do + if [[ $line == *"perf_hw_id"* ]]; then + mode="PERF_TYPE_HARDWARE" + elif [[ $line == *"perf_hw_cache_"* ]]; then + mode="PERF_TYPE_HW_CACHE" + elif [[ $line == *"perf_sw_id"* ]]; then + mode="PERF_TYPE_SOFTWARE" + elif [[ $line == *"PERF_COUNT_"* && $line == *"="* ]]; then + perf_name=$(echo "$line" | awk '{print $1}') + short_perf=$(echo "${perf_name:14}" | tr '[:upper:]' '[:lower:]') + if [[ " ${black_list[@]} " == *" $short_perf "* ]]; then + continue + fi + if [[ $mode == "PERF_TYPE_HW_CACHE" ]]; then + op_id=0 + for op_id_str in 'r' 'w' 'p'; do + op_id_names=("PERF_COUNT_HW_CACHE_OP_READ" "PERF_COUNT_HW_CACHE_OP_WRITE" "PERF_COUNT_HW_CACHE_OP_PREFETCH") + result_id=0 + for result_id_str in 'a' 'm'; do + result_id_names=("PERF_COUNT_HW_CACHE_RESULT_ACCESS" "PERF_COUNT_HW_CACHE_RESULT_MISS") + + printf "{ .name = \"%s_%s_%s\", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },\n" \ + $short_perf \ + $op_id_str \ + $result_id_str \ + $mode \ + $perf_name \ + ${op_id_names[$op_id]} \ + ${result_id_names[$result_id]} + + nb=$((nb + 1)) + ((result_id++)) + done + ((op_id++)) + done + else + printf "{ .name = \"%s\", .perf_type = %s, .perf_key = %s},\n" \ + $short_perf \ + $mode \ + $perf_name + + nb=$((nb + 1)) + fi + fi +done < "$linux_include" + +echo '};' + +echo "static unsigned int nb_counter_option = $nb ;" -- GitLab From 93d0f9764639e2e1735ba7ed896780a54a8129c7 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 9 Jan 2023 10:24:30 +0100 Subject: [PATCH 011/125] Convert counters_option.py to counters_option.sh The "counters_option.h" generator is now a POSIX shell script. The intent is to have a more portable script, and, hopefully, one that is more readable as well. --- makefile | 2 +- src/counters_option.py | 62 ----------------------- src/counters_option.sh | 112 ++++++++++++++++++++++++----------------- 3 files changed, 66 insertions(+), 110 deletions(-) delete mode 100755 src/counters_option.py diff --git a/makefile b/makefile index cca83e7..84d6fb5 100644 --- a/makefile +++ b/makefile @@ -26,7 +26,7 @@ $(OBJ_DIR)/counters_%.o: $(SRC_DIR)/counters_%.c $(SRC_DIR)/counters.h $(SRC_DIR $(CC) $(CFLAGS) -c $< -o $@ $(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.py - python3 ./$(SRC_DIR)/counters_option.py > $(SRC_DIR)/counters_option.h + sh ./$(SRC_DIR)/counters_option.sh > $(SRC_DIR)/counters_option.h $(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h $(CC) $(CFLAGS) -c $< -o $@ diff --git a/src/counters_option.py b/src/counters_option.py deleted file mode 100755 index 877a33a..0000000 --- a/src/counters_option.py +++ /dev/null @@ -1,62 +0,0 @@ -#! /usr/bin/python3 - -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - -linux_include = '/usr/include/linux/perf_event.h' - -string = """#include <linux/perf_event.h> - -typedef struct counter_option { - char *name; - __u32 perf_type; - __u64 perf_key; -} counter_option; - -static counter_option perf_static_info[] = {""" -print(string) - -nb = 0 - -black_list = ['stalled_cycles_frontend','stalled_cycles_backend', - 'cache_l1i', 'cache_op_write', 'cache_result_miss'] - -with open(linux_include, 'r') as infile: - mode = '' - for line in infile: - if 'perf_hw_id' in line: - mode = 'PERF_TYPE_HARDWARE' - elif 'perf_hw_cache_' in line: - mode = 'PERF_TYPE_HW_CACHE' - elif 'perf_sw_id' in line: - mode = 'PERF_TYPE_SOFTWARE' - elif 'PERF_COUNT_' in line and '=' in line: - perf_name = line.split()[0] - short_perf = perf_name[14:].lower() - if short_perf in black_list: - continue - if mode == 'PERF_TYPE_HW_CACHE': - for op_id, op_id_str in enumerate(['r', 'w', 'p']): - op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] - for result_id, result_id_str in enumerate(['a', 'm']): - result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] - - res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( - short_perf, op_id_str, result_id_str, - mode, - perf_name, - op_id_names[op_id], - result_id_names[result_id]) - - print(res) - nb += 1 - - else: - res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' - print(res) - nb += 1 - - -print('};') - -print('static unsigned int nb_counter_option =',nb,';') diff --git a/src/counters_option.sh b/src/counters_option.sh index 7d01bb7..1e6a22a 100644 --- a/src/counters_option.sh +++ b/src/counters_option.sh @@ -3,9 +3,9 @@ # SPDX-License-Identifier: GPL-3.0-or-later # Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> -linux_include="/usr/include/linux/perf_event.h" +linux_include=/usr/include/linux/perf_event.h -string="#include <linux/perf_event.h> +echo '#include <linux/perf_event.h> typedef struct counter_option { char *name; @@ -13,59 +13,77 @@ typedef struct counter_option { __u64 perf_key; } counter_option; -static counter_option perf_static_info[] = {" -echo "$string" +static counter_option perf_static_info[] = {' nb=0 -black_list=( "stalled_cycles_frontend" "stalled_cycles_backend" "cache_l1i" "cache_op_write" "cache_result_miss" ) +while IFS= read line; do + case $line in + *perf_hw_id*) + mode=PERF_TYPE_HARDWARE + ;; + *perf_hw_cache_*) + mode=PERF_TYPE_HW_CACHE + ;; + *perf_sw_id*) + mode=PERF_TYPE_SOFTWARE + ;; + *PERF_COUNT_*=*) + perf_name=$(echo "$line" | awk '{print $1}') + short_perf=$(echo "$perf_name" | sed 's/PERF_COUNT_[HS]W_//' | tr 'A-Z' 'a-z') + case $short_perf in + # blacklist + stalled_cycles_frontend|stalled_cycles_backend|cache_l1i|cache_op_write|cache_result_miss) + continue + ;; + esac -while IFS= read -r line; do - if [[ $line == *"perf_hw_id"* ]]; then - mode="PERF_TYPE_HARDWARE" - elif [[ $line == *"perf_hw_cache_"* ]]; then - mode="PERF_TYPE_HW_CACHE" - elif [[ $line == *"perf_sw_id"* ]]; then - mode="PERF_TYPE_SOFTWARE" - elif [[ $line == *"PERF_COUNT_"* && $line == *"="* ]]; then - perf_name=$(echo "$line" | awk '{print $1}') - short_perf=$(echo "${perf_name:14}" | tr '[:upper:]' '[:lower:]') - if [[ " ${black_list[@]} " == *" $short_perf "* ]]; then - continue - fi - if [[ $mode == "PERF_TYPE_HW_CACHE" ]]; then - op_id=0 - for op_id_str in 'r' 'w' 'p'; do - op_id_names=("PERF_COUNT_HW_CACHE_OP_READ" "PERF_COUNT_HW_CACHE_OP_WRITE" "PERF_COUNT_HW_CACHE_OP_PREFETCH") - result_id=0 - for result_id_str in 'a' 'm'; do - result_id_names=("PERF_COUNT_HW_CACHE_RESULT_ACCESS" "PERF_COUNT_HW_CACHE_RESULT_MISS") + if [ "$mode" != 'PERF_TYPE_HW_CACHE' ]; then + printf '{ .name = "%s", .perf_type = %s, .perf_key = %s},\n' \ + "$short_perf" \ + "$mode" \ + "$perf_name" - printf "{ .name = \"%s_%s_%s\", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },\n" \ - $short_perf \ - $op_id_str \ - $result_id_str \ - $mode \ - $perf_name \ - ${op_id_names[$op_id]} \ - ${result_id_names[$result_id]} + : $((nb += 1)) + continue + fi - nb=$((nb + 1)) - ((result_id++)) - done - ((op_id++)) - done - else - printf "{ .name = \"%s\", .perf_type = %s, .perf_key = %s},\n" \ - $short_perf \ - $mode \ - $perf_name + # $mode == PERF_TYPE_HW_CACHE + for op_id in \ + 'r PERF_COUNT_HW_CACHE_OP_READ' \ + 'w PERF_COUNT_HW_CACHE_OP_WRITE' \ + 'p PERF_COUNT_HW_CACHE_OP_PREFETCH' + do + op_id_str=${op_id% *} + op_id_name=${op_id#* } + + for result_id in \ + 'a PERF_COUNT_HW_CACHE_RESULT_ACCESS' \ + 'm PERF_COUNT_HW_CACHE_RESULT_MISS' + do + result_id_str=${result_id% *} + result_id_name=${result_id#* } - nb=$((nb + 1)) - fi - fi + printf '{' + printf ' .name = "%s_%s_%s",' \ + "$short_perf" \ + "$op_id_str" \ + "$result_id_str" + printf ' .perf_type = %s,' \ + "$mode" + printf ' .perf_key = %s | (%s >> 8) | (%s >> 16)' \ + "$perf_name" \ + "$op_id_name" \ + "$result_id_name" + printf ' },\n' + : $((nb += 1)) + done + done + ;; + esac done < "$linux_include" echo '};' -echo "static unsigned int nb_counter_option = $nb ;" +printf 'static unsigned int nb_counter_option = %d;\n' "$nb" + -- GitLab From 2a8704563c88a623f549688c6d3fa2e7704ab14b Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 9 Jan 2023 10:28:09 +0100 Subject: [PATCH 012/125] msc: basic reformating --- src/frapl.c | 4 ++-- src/infiniband.c | 2 +- src/load.c | 10 +++++----- src/mojitos.c | 4 ++-- src/network.c | 2 +- src/rapl.c | 2 +- src/temperature.c | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/frapl.c b/src/frapl.c index 1cc0ef9..6048e1d 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -107,7 +107,7 @@ void _get_frapl(uint64_t *values, _frapl_t *rapl) unsigned int init_frapl(char *none, void **ptr) { - UNUSED(none); + UNUSED(none); _frapl_t *rapl = malloc(sizeof(_frapl_t)); rapl->nb = 0; rapl->names = NULL; @@ -187,6 +187,6 @@ void clean_frapl(void *ptr) void label_frapl(char **labels, void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) + for(unsigned int i=0; i<rapl->nb; i++) labels[i] = rapl->names[i]; } diff --git a/src/infiniband.c b/src/infiniband.c index 7c6fff4..5f0d1d3 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -78,7 +78,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; void label_infiniband(char **labels, void *none) { - UNUSED(none); + UNUSED(none); for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_infiniband[i]; } diff --git a/src/load.c b/src/load.c index 33ebdbf..c6ff82a 100644 --- a/src/load.c +++ b/src/load.c @@ -54,8 +54,8 @@ void _get_load(uint64_t *results) unsigned int init_load(char *argument, void **state) { - UNUSED(argument); - UNUSED(state); + UNUSED(argument); + UNUSED(state); load_fid = open(stat, O_RDONLY); if (load_fid < 0) { @@ -69,7 +69,7 @@ unsigned int init_load(char *argument, void **state) unsigned int get_load(uint64_t *results, void *state) { - UNUSED(state); + UNUSED(state); _get_load(tmp_load_values); for(int i=0; i<10; i++) results[i] = tmp_load_values[i] - load_values[i]; @@ -80,7 +80,7 @@ unsigned int get_load(uint64_t *results, void *state) void clean_load(void *state) { - UNUSED(state); + UNUSED(state); close(load_fid); } @@ -89,7 +89,7 @@ char *_labels[10] = {"user","nice","system","idle","iowait","irq", }; void label_load(char **labels, void *none) { - UNUSED(none); + UNUSED(none); for(int i=0; i<10; i++) labels[i] = _labels[i]; } diff --git a/src/mojitos.c b/src/mojitos.c index ed6b462..fe56307 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -57,12 +57,12 @@ void usage(char **argv) void sighandler(int none) { - UNUSED(none); + UNUSED(none); } void flush(int none) { - UNUSED(none); + UNUSED(none); exit(0); } diff --git a/src/network.c b/src/network.c index d9575af..f5dc7d2 100644 --- a/src/network.c +++ b/src/network.c @@ -129,7 +129,7 @@ void clean_network(void *ptr) char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; void label_network(char **labels, void *none) { - UNUSED(none); + UNUSED(none); for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_network[i]; } diff --git a/src/rapl.c b/src/rapl.c index ab1b38c..bb0a26f 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -70,7 +70,7 @@ void _get_rapl(uint64_t *values, _rapl_t *rapl) unsigned int init_rapl(char *none, void **ptr) { - UNUSED(none); + UNUSED(none); // get number of processor sockets _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); rapl->nb = 0; diff --git a/src/temperature.c b/src/temperature.c index e210f7b..6868efb 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -102,7 +102,7 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) unsigned int init_temperature(char *args, void **ptr) { - UNUSED(args); + UNUSED(args); struct temperature_t *state = malloc(sizeof(struct temperature_t)); state->nb_elem = 0; state->label_list = NULL; -- GitLab From 1f9e3275176f35d0636011ee4f5f060c622a5b7f Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 9 Jan 2023 10:30:46 +0100 Subject: [PATCH 013/125] Correcting shebang on src/counters_option.sh --- src/counters_option.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/counters_option.sh b/src/counters_option.sh index 1e6a22a..5d1e577 100644 --- a/src/counters_option.sh +++ b/src/counters_option.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # SPDX-License-Identifier: GPL-3.0-or-later # Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> -- GitLab From 97d53cb266c74b98f8cbd88fb7970de993dcdd72 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 9 Jan 2023 11:42:31 +0000 Subject: [PATCH 014/125] close #2: add PANIC macro --- src/mojitos.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mojitos.c b/src/mojitos.c index ed6b462..b205baa 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -34,6 +34,14 @@ #include "temperature.h" #define UNUSED(expr) do { (void)(expr); } while (0) +#define PANIC(code, fmt, ...) \ + do { \ + fprintf(stderr, "Exit on error: "); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + exit(code); \ + } while (0) + void usage(char **argv) { @@ -136,9 +144,11 @@ int main(int argc, char **argv) switch (c) { case 'f': + if (optind >= argc) PANIC(1,"-f, no frequency provided"); frequency = atoi(argv[optind]); break; case 't': + if (optind >= argc) PANIC(1,"-t, no time provided"); total_time = atoi(argv[optind]); delta = 1; if (total_time == 0) @@ -154,6 +164,7 @@ int main(int argc, char **argv) add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); break; case 'o': + if (optind >= argc) PANIC(1,"-o, no logfile provided"); output = fopen(argv[optind], "wb"); break; case 'e': @@ -161,6 +172,7 @@ int main(int argc, char **argv) signal(17, sighandler); break; case 'p': + if (optind >= argc) PANIC(1,"-p, no counter provided"); add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); break; case 'r': -- GitLab From edb624615b580fbf43ed66b017df7e16af7ba942 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 9 Jan 2023 12:39:04 +0000 Subject: [PATCH 015/125] fix: -o --- src/mojitos.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/mojitos.c b/src/mojitos.c index b205baa..b5e6748 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -1,4 +1,5 @@ /******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. @@ -65,20 +66,23 @@ void usage(char **argv) void sighandler(int none) { - UNUSED(none); + UNUSED(none); } void flush(int none) { - UNUSED(none); + UNUSED(none); exit(0); } FILE *output; void flushexit() { - fflush(output); - fclose(output); + if (output != NULL) + { + fflush(output); + fclose(output); + } } typedef unsigned int (initializer_t)(char *, void **); @@ -144,11 +148,11 @@ int main(int argc, char **argv) switch (c) { case 'f': - if (optind >= argc) PANIC(1,"-f, no frequency provided"); + if (optind >= argc) PANIC(1,"-f, no frequency provided"); frequency = atoi(argv[optind]); break; case 't': - if (optind >= argc) PANIC(1,"-t, no time provided"); + if (optind >= argc) PANIC(1,"-t, no time provided"); total_time = atoi(argv[optind]); delta = 1; if (total_time == 0) @@ -164,15 +168,19 @@ int main(int argc, char **argv) add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); break; case 'o': - if (optind >= argc) PANIC(1,"-o, no logfile provided"); - output = fopen(argv[optind], "wb"); + if (optind >= argc) PANIC(1,"-o, no logfile provided"); + if ((output = fopen(argv[optind], "wb")) == NULL) + { + perror("fopen"); + PANIC(1, "-o %s", argv[optind]); + } break; case 'e': application = &argv[optind]; signal(17, sighandler); break; case 'p': - if (optind >= argc) PANIC(1,"-p, no counter provided"); + if (optind >= argc) PANIC(1,"-p, no counter provided"); add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); break; case 'r': -- GitLab From a0e916eb8ada2141e32225a1a9a80445d2125652 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 16 Jan 2023 09:41:47 +0000 Subject: [PATCH 016/125] Style update --- makefile | 2 +- src/counters_group.c | 59 ++++---- src/counters_individual.c | 111 +++++++-------- src/frapl.c | 102 ++++++-------- src/infiniband.c | 29 ++-- src/load.c | 41 +++--- src/mojitos.c | 290 +++++++++++++++++--------------------- src/network.c | 71 +++++----- src/rapl.c | 81 +++++------ src/temperature.c | 97 ++++++------- 10 files changed, 399 insertions(+), 484 deletions(-) diff --git a/makefile b/makefile index cca83e7..bf7d070 100644 --- a/makefile +++ b/makefile @@ -10,7 +10,7 @@ OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic -ASTYLE = astyle --style=gnu -xf -s4 -k3 -n -Z -Q +ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q # depending on the context it may need to be changed to all: mojitos mojitos_group diff --git a/src/counters_group.c b/src/counters_group.c index 0154a94..000e67a 100644 --- a/src/counters_group.c +++ b/src/counters_group.c @@ -29,8 +29,7 @@ #include "counters.h" -struct _counter_t -{ +struct _counter_t { int nbcores; int nbperf; int *counters; @@ -40,12 +39,11 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) - { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } + if (res == -1) { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } return res; } @@ -64,18 +62,16 @@ counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *name pe.read_format = PERF_FORMAT_GROUP; counters->counters = malloc((nbcores+1)*sizeof(int)); - for (int core=0; core<nbcores; core++) - { - counters->counters[core]=-1; - for(int idperf=0; idperf<nb_perf; idperf ++) - { - pe.type = types[idperf]; - pe.config = names[idperf]; - int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); - if(counters->counters[core]==-1) - counters->counters[core]=res; - } + for (int core=0; core<nbcores; core++) { + counters->counters[core]=-1; + for(int idperf=0; idperf<nb_perf; idperf ++) { + pe.type = types[idperf]; + pe.config = names[idperf]; + int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); + if(counters->counters[core]==-1) + counters->counters[core]=res; } + } return counters; } @@ -98,11 +94,9 @@ void reset_counters(counter_t counters) ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); } -struct read_format -{ +struct read_format { uint64_t nr; - struct - { + struct { uint64_t value; } values[]; }; @@ -117,17 +111,14 @@ void get_counters(counter_t counters, long long *values) memset(values, 0, nb_perf*sizeof(long long)); - for (int core=0; core<counters->nbcores; core++) - { - if (-1 == read(counters->counters[core], buffer, buffer_size)) - { - perror("PB Lecture resultat"); - exit(EXIT_FAILURE); - } - for(int idperf=0; idperf<=nb_perf; idperf++) - { - values[idperf] += buffer->values[idperf].value; - } + for (int core=0; core<counters->nbcores; core++) { + if (-1 == read(counters->counters[core], buffer, buffer_size)) { + perror("PB Lecture resultat"); + exit(EXIT_FAILURE); + } + for(int idperf=0; idperf<=nb_perf; idperf++) { + values[idperf] += buffer->values[idperf].value; } + } reset_counters(counters); } diff --git a/src/counters_individual.c b/src/counters_individual.c index 0f597ad..5a24eed 100644 --- a/src/counters_individual.c +++ b/src/counters_individual.c @@ -28,8 +28,7 @@ #include <asm/unistd.h> #include <stdint.h> -struct _counter_t -{ +struct _counter_t { int nbcores; int nbperf; int **counters; @@ -53,49 +52,43 @@ void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) { *perf_type = malloc(nb*sizeof(__u32)); *perf_key = malloc(nb*sizeof(__u64)); - for(int i=0; i<nb; i++) - { - (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; - (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; - } + for(int i=0; i<nb; i++) { + (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; + (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; + } } void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) { char *token; *nb_perf=0; *perf_indexes=NULL; - while((token=strtok(perf_string, ",")) != NULL) - { - perf_string = NULL; - unsigned int i; - for(i=0; i<nb_counter_option; i++) - { - if(strcmp(perf_static_info[i].name, token) == 0) - { - (*nb_perf)++; - (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); - (*perf_indexes)[*nb_perf-1]=i; - break; - } - } - if(i == nb_counter_option) - { - fprintf(stderr, "Unknown performance counter: %s\n", token); - exit(EXIT_FAILURE); - } + while((token=strtok(perf_string, ",")) != NULL) { + perf_string = NULL; + unsigned int i; + for(i=0; i<nb_counter_option; i++) { + if(strcmp(perf_static_info[i].name, token) == 0) { + (*nb_perf)++; + (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); + (*perf_indexes)[*nb_perf-1]=i; + break; + } } + if(i == nb_counter_option) { + fprintf(stderr, "Unknown performance counter: %s\n", token); + exit(EXIT_FAILURE); + } + } } static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) - { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } + if (res == -1) { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } return res; } @@ -111,29 +104,26 @@ counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *nam counters->nbperf = nb_perf; counters->nbcores=nbcores; counters->counters=malloc(nb_perf*sizeof(int *)); - for (int i=0; i<nb_perf; i++) - { - pe.type = types[i]; - pe.config = names[i]; - counters->counters[i] = malloc(nbcores*sizeof(int)); - - for (unsigned int core=0; core<nbcores; core++) - { - counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); - } + for (int i=0; i<nb_perf; i++) { + pe.type = types[i]; + pe.config = names[i]; + counters->counters[i] = malloc(nbcores*sizeof(int)); + + for (unsigned int core=0; core<nbcores; core++) { + counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); } + } return counters; } void clean_counters(void *ptr) { counter_t counters = (counter_t) ptr; - for(int counter=0; counter<counters->nbperf; counter++) - { - for(int core=0; core<counters->nbcores; core++) - close(counters->counters[counter][core]); - free(counters->counters[counter]); - } + for(int counter=0; counter<counters->nbperf; counter++) { + for(int core=0; core<counters->nbcores; core++) + close(counters->counters[counter][core]); + free(counters->counters[counter]); + } free(counters->counters); free(counters->counters_values); free(counters->tmp_counters_values); @@ -158,21 +148,18 @@ void reset_counters(counter_t counters) void _get_counters(counter_t counters, uint64_t *values) { - for(int i=0; i<counters->nbperf; i++) - { - uint64_t accu=0; - uint64_t count=0; - for (int core=0; core<counters->nbcores; core++) - { - if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) - { - fprintf(stderr, "Cannot read result"); - exit(EXIT_FAILURE); - } - accu += count; - } - values[i] = accu; + for(int i=0; i<counters->nbperf; i++) { + uint64_t accu=0; + uint64_t count=0; + for (int core=0; core<counters->nbcores; core++) { + if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) { + fprintf(stderr, "Cannot read result"); + exit(EXIT_FAILURE); + } + accu += count; } + values[i] = accu; + } } diff --git a/src/frapl.c b/src/frapl.c index 1cc0ef9..9874a12 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -34,10 +34,9 @@ char *get_frapl_string(const char *filename) { int fd = open(filename, O_RDONLY); - if( fd == -1) - { - return NULL; - } + if( fd == -1) { + return NULL; + } char *result = malloc(MAX_HEADER); int nb = read(fd, result, MAX_HEADER); close(fd); @@ -54,8 +53,7 @@ void test_append(char *name, int i) } -struct _frapl_t -{ +struct _frapl_t { unsigned int nb; char **names; int *fids; @@ -78,12 +76,11 @@ void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) int fd = open(energy_uj, O_RDONLY); - if (fd < 0) - { - fprintf(stderr, "%s ", energy_uj); - perror("open"); - exit(1); - } + if (fd < 0) { + fprintf(stderr, "%s ", energy_uj); + perror("open"); + exit(1); + } rapl->fids[rapl->nb-1] = fd; } @@ -92,22 +89,20 @@ void _get_frapl(uint64_t *values, _frapl_t *rapl) { static char buffer[512]; - for (unsigned int i = 0; i < rapl->nb; i++) - { + for (unsigned int i = 0; i < rapl->nb; i++) { - if (pread(rapl->fids[i], buffer, 100, 0) < 0) - { - perror("pread"); - exit(1); - } - values[i] = strtoull(buffer, NULL, 10); + if (pread(rapl->fids[i], buffer, 100, 0) < 0) { + perror("pread"); + exit(1); } + values[i] = strtoull(buffer, NULL, 10); + } } unsigned int init_frapl(char *none, void **ptr) { - UNUSED(none); + UNUSED(none); _frapl_t *rapl = malloc(sizeof(_frapl_t)); rapl->nb = 0; rapl->names = NULL; @@ -117,35 +112,33 @@ unsigned int init_frapl(char *none, void **ptr) char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - for (unsigned int i=0;; i++) - { - sprintf(buffer, name_base, i, "name"); - char *tmp = get_frapl_string(buffer); - if (tmp == NULL) break; - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); - add_frapl_source(rapl, tmp, buffer); - free(tmp); - - for (unsigned int j=0;; j++) - { - sprintf(buffer, name_sub, i, i, j, "name"); - char *tmp_sub = get_frapl_string(buffer); - if (tmp_sub == NULL) break; - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - - - sprintf(buffer, name_sub, i, i, j, "energy_uj"); - add_frapl_source(rapl, tmp_sub, buffer); - - free(tmp_sub); - } + for (unsigned int i=0;; i++) { + sprintf(buffer, name_base, i, "name"); + char *tmp = get_frapl_string(buffer); + if (tmp == NULL) break; + //printf("%s\n", tmp); + test_append(tmp, i); + //printf("%s -> %s\n", buffer, tmp); + + sprintf(buffer, name_base, i, "energy_uj"); + add_frapl_source(rapl, tmp, buffer); + free(tmp); + + for (unsigned int j=0;; j++) { + sprintf(buffer, name_sub, i, i, j, "name"); + char *tmp_sub = get_frapl_string(buffer); + if (tmp_sub == NULL) break; + //printf("%s\n", tmp_sub); + test_append(tmp_sub, i); + //printf("%s -> %s\n", buffer, tmp_sub); + + + sprintf(buffer, name_sub, i, i, j, "energy_uj"); + add_frapl_source(rapl, tmp_sub, buffer); + + free(tmp_sub); } + } rapl->values = calloc(sizeof(uint64_t), rapl->nb); rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); @@ -171,11 +164,10 @@ unsigned int get_frapl(uint64_t *results, void *ptr) void clean_frapl(void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) - { - free(rapl->names[i]); - close(rapl->fids[i]); - } + for(unsigned int i=0; i<rapl->nb; i++) { + free(rapl->names[i]); + close(rapl->fids[i]); + } free(rapl->names); free(rapl->fids); free(rapl->values); @@ -187,6 +179,6 @@ void clean_frapl(void *ptr) void label_frapl(char **labels, void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) + for(unsigned int i=0; i<rapl->nb; i++) labels[i] = rapl->names[i]; } diff --git a/src/infiniband.c b/src/infiniband.c index 7c6fff4..6621759 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -29,8 +29,7 @@ #define NB_SENSOR 4 #define UNUSED(expr) do { (void)(expr); } while (0) -struct network_t -{ +struct network_t { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; @@ -43,16 +42,15 @@ unsigned int init_infiniband(char *infi_path, void **ptr) if(infi_path==NULL) return 0; - if(strcmp(infi_path,"X")==0) - { + if(strcmp(infi_path,"X")==0) { - glob_t res; + glob_t res; - glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); - if(res.gl_pathc == 0) - return 0; - infi_path = res.gl_pathv[0]; - } + glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); + if(res.gl_pathc == 0) + return 0; + infi_path = res.gl_pathv[0]; + } char *filenames[] = {"%s/port_rcv_packets", "%s/port_rcv_data", @@ -63,11 +61,10 @@ unsigned int init_infiniband(char *infi_path, void **ptr) struct network_t *state = malloc(sizeof(struct network_t)); char buffer[1024]; - for(int i=0; i<NB_SENSOR; i++) - { - sprintf(buffer, filenames[i], infi_path); - state->sources[i] = open(buffer, O_RDONLY); - } + for(int i=0; i<NB_SENSOR; i++) { + sprintf(buffer, filenames[i], infi_path); + state->sources[i] = open(buffer, O_RDONLY); + } *ptr = (void *) state; _get_network(state->values, state->sources); @@ -78,7 +75,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; void label_infiniband(char **labels, void *none) { - UNUSED(none); + UNUSED(none); for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_infiniband[i]; } diff --git a/src/load.c b/src/load.c index 33ebdbf..4f11346 100644 --- a/src/load.c +++ b/src/load.c @@ -35,41 +35,38 @@ static char *stat = "/proc/stat"; void _get_load(uint64_t *results) { - if (pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0) < 0) - { - perror("pread"); - exit(1); - } + if (pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0) < 0) { + perror("pread"); + exit(1); + } int pos=0; while(buffer[pos] > '9' || buffer[pos] < '0') pos++; - for(int i=0; i<10; i++) - { - results[i] = strtoull(buffer+pos, NULL, 10); - while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; - pos++; - } + for(int i=0; i<10; i++) { + results[i] = strtoull(buffer+pos, NULL, 10); + while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; + pos++; + } } // Public interface unsigned int init_load(char *argument, void **state) { - UNUSED(argument); - UNUSED(state); + UNUSED(argument); + UNUSED(state); load_fid = open(stat, O_RDONLY); - if (load_fid < 0) - { - fprintf(stderr,"%s ",stat); - perror("open"); - exit(1); - } + if (load_fid < 0) { + fprintf(stderr,"%s ",stat); + perror("open"); + exit(1); + } _get_load(load_values); return 10; } unsigned int get_load(uint64_t *results, void *state) { - UNUSED(state); + UNUSED(state); _get_load(tmp_load_values); for(int i=0; i<10; i++) results[i] = tmp_load_values[i] - load_values[i]; @@ -80,7 +77,7 @@ unsigned int get_load(uint64_t *results, void *state) void clean_load(void *state) { - UNUSED(state); + UNUSED(state); close(load_fid); } @@ -89,7 +86,7 @@ char *_labels[10] = {"user","nice","system","idle","iowait","irq", }; void label_load(char **labels, void *none) { - UNUSED(none); + UNUSED(none); for(int i=0; i<10; i++) labels[i] = _labels[i]; } diff --git a/src/mojitos.c b/src/mojitos.c index b5e6748..3569d1b 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -78,11 +78,10 @@ void flush(int none) FILE *output; void flushexit() { - if (output != NULL) - { - fflush(output); - fclose(output); - } + if (output != NULL) { + fflush(output); + fclose(output); + } } typedef unsigned int (initializer_t)(char *, void **); @@ -105,12 +104,11 @@ void add_source(initializer_t init, char *arg, labeler_t labeler, nb_sources++; states = realloc(states, nb_sources * sizeof(void *)); int nb = init(arg, &states[nb_sources - 1]); - if (nb == 0) - { - nb_sources--; - states = realloc(states, nb_sources * sizeof(void *)); - return; - } + if (nb == 0) { + nb_sources--; + states = realloc(states, nb_sources * sizeof(void *)); + return; + } getter = realloc(getter, nb_sources * sizeof(void *)); getter[nb_sources - 1] = get; @@ -133,10 +131,9 @@ int main(int argc, char **argv) int stat_mode = -1; - if (argc == 1) - { - usage(argv); - } + if (argc == 1) { + usage(argv); + } output = stdout; @@ -145,65 +142,62 @@ int main(int argc, char **argv) int c; while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) - switch (c) - { - case 'f': - if (optind >= argc) PANIC(1,"-f, no frequency provided"); - frequency = atoi(argv[optind]); - break; - case 't': - if (optind >= argc) PANIC(1,"-t, no time provided"); - total_time = atoi(argv[optind]); - delta = 1; - if (total_time == 0) - { - total_time = 1; - delta = 0; - } - break; - case 'd': - add_source(init_network, argv[optind], label_network, get_network, clean_network); - break; - case 'i': - add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); - break; - case 'o': - if (optind >= argc) PANIC(1,"-o, no logfile provided"); - if ((output = fopen(argv[optind], "wb")) == NULL) - { - perror("fopen"); - PANIC(1, "-o %s", argv[optind]); - } - break; - case 'e': - application = &argv[optind]; - signal(17, sighandler); - break; - case 'p': - if (optind >= argc) PANIC(1,"-p, no counter provided"); - add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); - break; - case 'r': - add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); - break; - case 'R': - add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); - break; - case 'u': - add_source(init_load, NULL, label_load, get_load, clean_load); - break; - case 'c': - add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); - break; - case 's': - stat_mode = 0; - break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); - default: - usage(argv); + switch (c) { + case 'f': + if (optind >= argc) PANIC(1,"-f, no frequency provided"); + frequency = atoi(argv[optind]); + break; + case 't': + if (optind >= argc) PANIC(1,"-t, no time provided"); + total_time = atoi(argv[optind]); + delta = 1; + if (total_time == 0) { + total_time = 1; + delta = 0; } + break; + case 'd': + add_source(init_network, argv[optind], label_network, get_network, clean_network); + break; + case 'i': + add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); + break; + case 'o': + if (optind >= argc) PANIC(1,"-o, no logfile provided"); + if ((output = fopen(argv[optind], "wb")) == NULL) { + perror("fopen"); + PANIC(1, "-o %s", argv[optind]); + } + break; + case 'e': + application = &argv[optind]; + signal(17, sighandler); + break; + case 'p': + if (optind >= argc) PANIC(1,"-p, no counter provided"); + add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); + break; + case 'r': + add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); + break; + case 'R': + add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); + break; + case 'u': + add_source(init_load, NULL, label_load, get_load, clean_load); + break; + case 'c': + add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); + break; + case 's': + stat_mode = 0; + break; + case 'l': + show_all_counters(); + exit(EXIT_SUCCESS); + default: + usage(argv); + } setvbuf(output, NULL, _IONBF, BUFSIZ); @@ -212,109 +206,89 @@ int main(int argc, char **argv) fprintf(output, "#timestamp "); - for (unsigned int i = 0; i < nb_sensors; i++) - { - fprintf(output, "%s ", labels[i]); - } + for (unsigned int i = 0; i < nb_sensors; i++) { + fprintf(output, "%s ", labels[i]); + } - if (stat_mode == 0) - { - fprintf(output, "overhead "); - } + if (stat_mode == 0) { + fprintf(output, "overhead "); + } fprintf(output, "\n"); unsigned long int stat_data = 0; - for (int temps = 0; temps < total_time * frequency; temps += delta) - { - clock_gettime(CLOCK_MONOTONIC, &ts_ref); + for (int temps = 0; temps < total_time * frequency; temps += delta) { + clock_gettime(CLOCK_MONOTONIC, &ts_ref); - // Get Data - unsigned int current = 0; - for (unsigned int i = 0; i < nb_sources; i++) - { - current += getter[i](&values[current], states[i]); - } + // Get Data + unsigned int current = 0; + for (unsigned int i = 0; i < nb_sources; i++) { + current += getter[i](&values[current], states[i]); + } - if (application != NULL) - { - - if (fork() == 0) - { - execvp(application[0], application); - exit(0); - } - pause(); - clock_gettime(CLOCK_MONOTONIC, &ts); - if (ts.tv_nsec >= ts_ref.tv_nsec) - { - fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec), ts.tv_nsec - ts_ref.tv_nsec); - } - else - { - fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000000000 + ts.tv_nsec - ts_ref.tv_nsec); - } - } - else - { + if (application != NULL) { + + if (fork() == 0) { + execvp(application[0], application); + exit(0); + } + pause(); + clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) { + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec), ts.tv_nsec - ts_ref.tv_nsec); + } else { + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000000000 + ts.tv_nsec - ts_ref.tv_nsec); + } + } else { #ifdef DEBUG - clock_gettime(CLOCK_MONOTONIC, &ts); - fprintf(stderr, "%ld\n", (ts.tv_nsec - ts_ref.tv_nsec) / 1000); - //Indiv: mean: 148 std: 31 % med: 141 std: 28 % - //Group: mean: 309 std: 41 % med: 297 std: 39 % + clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stderr, "%ld\n", (ts.tv_nsec - ts_ref.tv_nsec) / 1000); + //Indiv: mean: 148 std: 31 % med: 141 std: 28 % + //Group: mean: 309 std: 41 % med: 297 std: 39 % #endif - if (stat_mode == 0) - { - clock_gettime(CLOCK_MONOTONIC, &ts); - if (ts.tv_nsec >= ts_ref.tv_nsec) - { - stat_data = ts.tv_nsec - ts_ref.tv_nsec; - } - else - { - stat_data = 1000000000 + ts.tv_nsec - ts_ref.tv_nsec; - } - } - - // Treat Data - fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); - } - - for (unsigned int i = 0; i < nb_sensors; i++) - { - fprintf(output, "%" PRIu64 " ", values[i]); - } - - if (stat_mode == 0) - { - fprintf(output, "%ld ", stat_data); + if (stat_mode == 0) { + clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) { + stat_data = ts.tv_nsec - ts_ref.tv_nsec; + } else { + stat_data = 1000000000 + ts.tv_nsec - ts_ref.tv_nsec; } + } - fprintf(output, "\n"); - - if (application != NULL) - { - break; - } + // Treat Data + fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); + } - clock_gettime(CLOCK_MONOTONIC, &ts); - usleep(1000 * 1000 / frequency - (ts.tv_nsec / 1000) % (1000 * 1000 / frequency)); + for (unsigned int i = 0; i < nb_sensors; i++) { + fprintf(output, "%" PRIu64 " ", values[i]); } - for (unsigned int i = 0; i < nb_sources; i++) - { - cleaner[i](states[i]); + if (stat_mode == 0) { + fprintf(output, "%ld ", stat_data); } - if (nb_sources > 0) - { - free(getter); - free(cleaner); - free(labels); - free(values); - free(states); + fprintf(output, "\n"); + + if (application != NULL) { + break; } + + clock_gettime(CLOCK_MONOTONIC, &ts); + usleep(1000 * 1000 / frequency - (ts.tv_nsec / 1000) % (1000 * 1000 / frequency)); + } + + for (unsigned int i = 0; i < nb_sources; i++) { + cleaner[i](states[i]); + } + + if (nb_sources > 0) { + free(getter); + free(cleaner); + free(labels); + free(values); + free(states); + } } diff --git a/src/network.c b/src/network.c index d9575af..647b4b3 100644 --- a/src/network.c +++ b/src/network.c @@ -28,8 +28,7 @@ #define UNUSED(expr) do { (void)(expr); } while (0) static char *route = "/proc/net/route"; -struct network_t -{ +struct network_t { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; @@ -40,16 +39,14 @@ unsigned int _get_network(uint64_t *results, int *sources) if(sources==NULL) return 0; char buffer[128]; - for(int i=0; i<NB_SENSOR; i++) - { - if (pread(sources[i], buffer, 127, 0) < 0) - { - perror("pread"); - exit(1); - } - - results[i] = strtoull(buffer, NULL, 10); + for(int i=0; i<NB_SENSOR; i++) { + if (pread(sources[i], buffer, 127, 0) < 0) { + perror("pread"); + exit(1); } + + results[i] = strtoull(buffer, NULL, 10); + } return NB_SENSOR; } @@ -60,31 +57,28 @@ unsigned int init_network(char *dev, void **ptr) if(dev==NULL) return 0; - if(strcmp(dev,"X")==0) - { - int fd = open(route, O_RDONLY); - if (fd < 0) - { - fprintf(stderr, "%s ", route); - perror("open"); - exit(1); - } - char buffer[1000]; - - if ( read(fd, buffer, 999) < 0 ) - { - perror("read"); - close(fd); - exit(1); - } - - char *start_of_dev = index(buffer, '\n')+1; - char *end_of_dev = index(start_of_dev, '\t'); - *end_of_dev='\0'; - dev = start_of_dev; + if(strcmp(dev,"X")==0) { + int fd = open(route, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s ", route); + perror("open"); + exit(1); + } + char buffer[1000]; + + if ( read(fd, buffer, 999) < 0 ) { + perror("read"); close(fd); + exit(1); } + char *start_of_dev = index(buffer, '\n')+1; + char *end_of_dev = index(start_of_dev, '\t'); + *end_of_dev='\0'; + dev = start_of_dev; + close(fd); + } + char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", "/sys/class/net/%s/statistics/rx_bytes", "/sys/class/net/%s/statistics/tx_packets", @@ -94,11 +88,10 @@ unsigned int init_network(char *dev, void **ptr) struct network_t *state = malloc(sizeof(struct network_t)); char buffer2[256]; - for(int i=0; i<NB_SENSOR; i++) - { - sprintf(buffer2, filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); - } + for(int i=0; i<NB_SENSOR; i++) { + sprintf(buffer2, filenames[i], dev); + state->sources[i] = open(buffer2, O_RDONLY); + } *ptr = (void *) state; _get_network(state->values, state->sources); @@ -129,7 +122,7 @@ void clean_network(void *ptr) char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; void label_network(char **labels, void *none) { - UNUSED(none); + UNUSED(none); for(int i=0; i<NB_SENSOR; i++) labels[i] = _labels_network[i]; } diff --git a/src/rapl.c b/src/rapl.c index ab1b38c..30d38c1 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -26,8 +26,7 @@ #define UNUSED(expr) do { (void)(expr); } while (0) -struct _rapl_t -{ +struct _rapl_t { powercap_rapl_pkg *pkgs; uint32_t nb_pkgs; uint32_t nb; @@ -54,23 +53,22 @@ const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_COR // values [zone + package *nbzones] microjoules void _get_rapl(uint64_t *values, _rapl_t *rapl) { - for (unsigned int i = 0; i < rapl->nb; i++) - { + for (unsigned int i = 0; i < rapl->nb; i++) { #ifdef DEBUG - int ret = + int ret = #endif - powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], - rapl->zones[i], - &values[i]); + powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], + rapl->zones[i], + &values[i]); #ifdef DEBUG - printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); + printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); #endif - } + } } unsigned int init_rapl(char *none, void **ptr) { - UNUSED(none); + UNUSED(none); // get number of processor sockets _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); rapl->nb = 0; @@ -80,50 +78,45 @@ unsigned int init_rapl(char *none, void **ptr) rapl->nb_pkgs = powercap_rapl_get_num_instances(); //rapl->nb_pkgs = powercap_rapl_get_num_packages(); - if (rapl->nb_pkgs == 0) - { - perror("no packages found (maybe the kernel module isn't loaded?)"); - exit(-1); - } + if (rapl->nb_pkgs == 0) { + perror("no packages found (maybe the kernel module isn't loaded?)"); + exit(-1); + } rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) - { - perror("powercap_rapl_init, check access (root needed ?)"); - exit(-1); - } + if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { + perror("powercap_rapl_init, check access (root needed ?)"); + exit(-1); + } rapl->names = NULL; char _name[MAX_LEN_NAME+1]; char _name2[MAX_LEN_NAME+11]; - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - { - for(unsigned int zone=0; zone < nb_zones; zone++) - { - int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], - _name, MAX_LEN_NAME); - if (length>0) - { - - sprintf(_name2, "%s%u", _name, package); - - rapl->nb++; - rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); - rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); - rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); - - strcpy(rapl->names[rapl->nb-1], _name2); - rapl->zones[rapl->nb-1] = rapl_zones[zone]; - rapl->packages[rapl->nb-1] = package; - } + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { + for(unsigned int zone=0; zone < nb_zones; zone++) { + int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], + _name, MAX_LEN_NAME); + if (length>0) { + + sprintf(_name2, "%s%u", _name, package); + + rapl->nb++; + rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); + rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); + rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); + rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); + + strcpy(rapl->names[rapl->nb-1], _name2); + rapl->zones[rapl->nb-1] = rapl_zones[zone]; + rapl->packages[rapl->nb-1] = package; + } #ifdef DEBUG - printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); + printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); #endif - } } + } #ifdef DEBUG printf("Result of init\n"); for(unsigned int i=0; i<rapl->nb; i++) diff --git a/src/temperature.c b/src/temperature.c index e210f7b..cdef158 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -27,8 +27,7 @@ #define UNUSED(expr) do { (void)(expr); } while (0) -struct temperature_t -{ +struct temperature_t { char **label_list; int *fid_list; int nb_elem; @@ -42,11 +41,10 @@ int get_string(char *filename, char *buffer, int max_size) return -1; int nb = read(fid, buffer, max_size); - if(nb == -1) - { - close(fid); - return -1; - } + if(nb == -1) { + close(fid); + return -1; + } buffer[nb]=0; close(fid); @@ -70,39 +68,36 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) int delta = sprintf(buffer_label, "Temp_%d_", key); - for(int i=1;; i++) - { - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); - if(get_string(buffer_filename, buffer_label+delta, 100) == -1) - break; - - for(unsigned int pos = 0; pos < strlen(buffer_label); pos++) - { - if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; - if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; - } - add_to_list(&state->label_list, buffer_label, state->nb_elem); - - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); - state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); - int fd = open(buffer_filename, O_RDONLY); - if (fd < 0) - { - fprintf(stderr, "%s ", buffer_filename); - perror("open"); - exit(1); - } - state->fid_list[state->nb_elem] = fd; - state->nb_elem++; - // printf("%s : %s\n", buffer_label, buffer_filename); + for(int i=1;; i++) { + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); + if(get_string(buffer_filename, buffer_label+delta, 100) == -1) + break; + + for(unsigned int pos = 0; pos < strlen(buffer_label); pos++) { + if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; + if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; + } + add_to_list(&state->label_list, buffer_label, state->nb_elem); + + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); + state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); + int fd = open(buffer_filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s ", buffer_filename); + perror("open"); + exit(1); } + state->fid_list[state->nb_elem] = fd; + state->nb_elem++; + // printf("%s : %s\n", buffer_label, buffer_filename); + } key++; } unsigned int init_temperature(char *args, void **ptr) { - UNUSED(args); + UNUSED(args); struct temperature_t *state = malloc(sizeof(struct temperature_t)); state->nb_elem = 0; state->label_list = NULL; @@ -114,14 +109,13 @@ unsigned int init_temperature(char *args, void **ptr) int i = 0; sprintf(name, base_name, i); - while(get_string(name, buffer, 8) != -1) - { - if (strcmp(buffer, "coretemp")==0) - add_temperature_sensor(i, state); + while(get_string(name, buffer, 8) != -1) { + if (strcmp(buffer, "coretemp")==0) + add_temperature_sensor(i, state); - i++; - sprintf(name, base_name, i); - } + i++; + sprintf(name, base_name, i); + } *ptr = (void *) state; return state->nb_elem; } @@ -130,15 +124,13 @@ unsigned int get_temperature(uint64_t *results, void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; static char buffer[512]; - for(int i=0; i<state->nb_elem; i++) - { - if (pread(state->fid_list[i], buffer, 100, 0) < 0) - { - perror("pread"); - exit(1); - } - results[i] = strtoull(buffer, NULL, 10); + for(int i=0; i<state->nb_elem; i++) { + if (pread(state->fid_list[i], buffer, 100, 0) < 0) { + perror("pread"); + exit(1); } + results[i] = strtoull(buffer, NULL, 10); + } return state->nb_elem; } @@ -146,11 +138,10 @@ void clean_temperature(void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; - for(int i=0; i<state->nb_elem; i++) - { - free(state->label_list[i]); - close(state->fid_list[i]); - } + for(int i=0; i<state->nb_elem; i++) { + free(state->label_list[i]); + close(state->fid_list[i]); + } free(state->label_list); free(state->fid_list); free(state); -- GitLab From 619d27218686342aa1e4fb23db42b2976b086463 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 10:48:01 +0100 Subject: [PATCH 017/125] remove "mojitos_group" - rm src/counters_group.c - mv src/counters_individual.c src/counters.c - remove the mojitos_group target from makefile --- makefile | 5 +- src/{counters_individual.c => counters.c} | 0 src/counters_group.c | 124 ---------------------- 3 files changed, 1 insertion(+), 128 deletions(-) rename src/{counters_individual.c => counters.c} (100%) delete mode 100644 src/counters_group.c diff --git a/makefile b/makefile index bf7d070..ab8c2dc 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ SRC_DIR = src OBJ_DIR = obj BIN_DIR = bin -OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters_individual.o rapl.o frapl.o network.o load.o infiniband.o temperature.o) +OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o frapl.o network.o load.o infiniband.o temperature.o) OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc @@ -19,9 +19,6 @@ all: mojitos mojitos: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS) $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos $(OBJECTS) -lpowercap -mojitos_group: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS_GRP) $(SRC_DIR)/counters_option.h - $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos_group $(OBJECTS_GRP) -lpowercap - $(OBJ_DIR)/counters_%.o: $(SRC_DIR)/counters_%.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h $(CC) $(CFLAGS) -c $< -o $@ diff --git a/src/counters_individual.c b/src/counters.c similarity index 100% rename from src/counters_individual.c rename to src/counters.c diff --git a/src/counters_group.c b/src/counters_group.c deleted file mode 100644 index 000e67a..0000000 --- a/src/counters_group.c +++ /dev/null @@ -1,124 +0,0 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <linux/perf_event.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/ioctl.h> -#include <stdio.h> -#include <stdint.h> -#include <asm/unistd.h> - -#include "counters.h" - -struct _counter_t { - int nbcores; - int nbperf; - int *counters; -}; - -static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) -{ - long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } - return res; -} - -counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) -{ - struct perf_event_attr pe; - struct _counter_t *counters = malloc(sizeof(struct _counter_t)); - - unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); - counters->nbcores=nbcores; - counters->nbperf=nb_perf; - memset(&pe, 0, sizeof(struct perf_event_attr)); - pe.size = sizeof(struct perf_event_attr); - pe.disabled = 1; - - pe.read_format = PERF_FORMAT_GROUP; - counters->counters = malloc((nbcores+1)*sizeof(int)); - - for (int core=0; core<nbcores; core++) { - counters->counters[core]=-1; - for(int idperf=0; idperf<nb_perf; idperf ++) { - pe.type = types[idperf]; - pe.config = names[idperf]; - int res=perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); - if(counters->counters[core]==-1) - counters->counters[core]=res; - } - } - return counters; -} - -void clean_counters(counter_t counters) -{ - for(int core=0; core<counters->nbcores; core++) - close(counters->counters[core]); - free(counters->counters); - free(counters); -} - -void start_counters(counter_t counters) -{ - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); -} -void reset_counters(counter_t counters) -{ - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); -} - -struct read_format { - uint64_t nr; - struct { - uint64_t value; - } values[]; -}; - -void get_counters(counter_t counters, long long *values) -{ - int nb_perf = counters->nbperf; - size_t buffer_size = sizeof(uint64_t)*(1+nb_perf); - struct read_format *buffer = NULL; - if(buffer==NULL) - buffer = malloc(buffer_size); - - memset(values, 0, nb_perf*sizeof(long long)); - - for (int core=0; core<counters->nbcores; core++) { - if (-1 == read(counters->counters[core], buffer, buffer_size)) { - perror("PB Lecture resultat"); - exit(EXIT_FAILURE); - } - for(int idperf=0; idperf<=nb_perf; idperf++) { - values[idperf] += buffer->values[idperf].value; - } - } - reset_counters(counters); -} -- GitLab From d24dabec7b03c5e99a5f99a9cbf4f8fb0cdd748f Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Mon, 16 Jan 2023 11:26:30 +0100 Subject: [PATCH 018/125] =?UTF-8?q?r=C3=A9cup=20vieilles=20modifs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frapl.c | 3 +++ mojitos.c | 2 +- rapl.c | 10 +++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/frapl.c b/frapl.c index 433a28c..657fd35 100644 --- a/frapl.c +++ b/frapl.c @@ -74,11 +74,14 @@ void add_frapl_source(_frapl_t* rapl, char*name, char*energy_uj) { void _get_frapl(uint64_t *values, _frapl_t* rapl) { static char buffer[512]; + printf("Results : "); for (int i = 0; i < rapl->nb; i++) { pread(rapl->fids[i], buffer, 100, 0); values[i] = strtoull(buffer, NULL, 10); + printf("%d", values[i]); } + printf("\n"); } diff --git a/mojitos.c b/mojitos.c index e80e692..029a24d 100644 --- a/mojitos.c +++ b/mojitos.c @@ -194,7 +194,7 @@ int main(int argc, char **argv) { unsigned int current = 0; for(int i=0; i<nb_sources; i++) current += getter[i](&values[current], states[i]); - + printf("Current : %d\n"); if(application != NULL) { if(fork()==0){ diff --git a/rapl.c b/rapl.c index 14b4a58..f23106d 100644 --- a/rapl.c +++ b/rapl.c @@ -132,9 +132,13 @@ unsigned int init_rapl(char* none, void **ptr) { unsigned int get_rapl(uint64_t* results, void* ptr) { _rapl_t* state = (_rapl_t*) ptr; _get_rapl(state->tmp_values, state); - for(int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; - + printf("results"); + for (unsigned int i = 0; i < state->nb; i++) + { + results[i] = state->tmp_values[i] - state->values[i]; + printf("%d, ", results[i]); + } + printf("\n"); memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); return state->nb; } -- GitLab From f71bec95a3305582ff26059104085b6e8775297d Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Mon, 16 Jan 2023 11:46:36 +0100 Subject: [PATCH 019/125] =?UTF-8?q?WSL=20fait=20des=20b=C3=AAtises=20faite?= =?UTF-8?q?s=20pas=20gaffe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 8 +- LICENSE | 1348 ++++++++++++++++++++-------------------- README.md | 200 +++--- makefile | 96 +-- src/counters.c | 424 ++++++------- src/counters.h | 52 +- src/counters_option.py | 124 ++-- src/frapl.c | 368 +++++------ src/frapl.h | 50 +- src/infiniband.c | 162 ++--- src/infiniband.h | 44 +- src/load.c | 184 +++--- src/load.h | 48 +- src/mojitos.c | 592 +++++++++--------- src/network.c | 256 ++++---- src/network.h | 50 +- src/rapl.c | 348 +++++------ src/rapl.h | 50 +- src/temperature.c | 310 ++++----- src/temperature.h | 48 +- 20 files changed, 2381 insertions(+), 2381 deletions(-) diff --git a/.gitignore b/.gitignore index f5893ce..5a8f74f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -*.o -src/counters_option.h -bin -obj +*.o +src/counters_option.h +bin +obj diff --git a/LICENSE b/LICENSE index f288702..3877ae0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,674 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<https://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<https://www.gnu.org/licenses/why-not-lgpl.html>. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>. diff --git a/README.md b/README.md index 2cf04f1..16d5d13 100644 --- a/README.md +++ b/README.md @@ -1,100 +1,100 @@ -# MOJITO/S - -An Open Source System, Energy and Network Monitoring Tools at the O/S level - -## Documentation - -MojitO/S runs on GNU/Linux -Usage - -```python -Usage : ./mojitos [-t time] [-f freq] [-r] [-p perf_list] [-l] \ - [-u] [-d network_device] [-o logfile] [-e command arguments...] -``` - -Timing -- If time is 0 then mojitos loops infinitively -- If -e is present, time and freq are not used - -Configuration -- -r activates RAPL (deprecated) -- -R activates RAPL -- -p activates performance counters. perf_list is coma separated list of performance counters without space. -- -l lists the possible performance counters and quits -- -d activates network monitoring -- -u activates system-level load monitoring -- -s activates statistics of overhead in nanoseconds - -MojitO/S is published under the GPL3 license and is part of the [Energumen Project](https://www.irit.fr/energumen/) - -<img src="https://www.irit.fr/energumen/images/energumen.png" width="100"> - -## Installation Instructions - -Dependencies -```bash -sudo apt install libpowercap0 libpowercap-dev powercap-utils python3 -``` -Download the source code -```bash -git clone https://gitlab.irit.fr/sepia-pub/mojitos.git -``` -Compile the code -```bash -cd mojitos -make -``` -To execute mojitos without being root to monitor performance counters -```bash -sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' -``` -To execute mohitos without being root for accessing RAPL -```bash -sudo chmod a+w /sys/class/powercap/intel-rapl/*/* -sudo chmod a+w /sys/class/powercap/intel-rapl/*/*/* -``` - -## Tutorial and Examples - -RAPL values during 2 seconds with a frequency of 2 Hz -```bash -$ ./mojitos -t 2 -f 2 -r -#timestamp package-00 core0 dram0 -1036389.135659868 10986 2869 1526 -1036389.500183551 1291440 255736 515562 -1036390.000754048 1333553 228393 689513 -1036390.500113978 1581967 267944 701536 -``` -Performance counters (cpu_cycle, cache_ll_r_a and page_faults) during 4 seconds with a frequency of 1Hz. For cache performance counters, _r and _w are respectively read and write, and _a, _m and _p are respectively access, miss, pending. - -```bash -$ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults -#timestamp cpu_cycles cache_ll page_faults -1036846.351749455 571199 1232 0 -1036847.001098880 348173344 2451387 872 -1036848.000166158 388112961 2509305 791 -1036849.000191883 402255979 2625283 799 -``` - -Network values with no time limit with a frequency of 1Hz. rxp and txp are the number of received and sent packets, while rxb and txp are the number of received and sent bytes. -```bash -$ ./mojitos -t 0 -f 1 -d enp0s25 -#timestamp rxp rxb txp txb -1036559.277376027 0 0 0 0 -1036560.000161101 4 581 2 179 -1036561.000083968 178 268675 55 4954 -1036562.000076162 11 1010 5 510 -1036563.000069724 17 1643 12 3602 -1036564.000113394 990 1493008 369 27299 -``` - -Overhead of the monitoring for RAPL and cpu_cycle -```bash -$ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s -#timestamp cpu_cycles package-00 core0 dram0 overhead -1036988.197227391 162214 19898 4944 1586 149612 -1036989.000151326 332613664 2513116 379577 1115171 739573 -1036990.000116433 482150700 3321341 587218 1380673 315719 -1036991.000182835 525984292 3592582 691221 1385982 272182 -1036992.000165117 397678789 2770561 444030 1375729 510379 -``` +# MOJITO/S + +An Open Source System, Energy and Network Monitoring Tools at the O/S level + +## Documentation + +MojitO/S runs on GNU/Linux +Usage + +```python +Usage : ./mojitos [-t time] [-f freq] [-r] [-p perf_list] [-l] \ + [-u] [-d network_device] [-o logfile] [-e command arguments...] +``` + +Timing +- If time is 0 then mojitos loops infinitively +- If -e is present, time and freq are not used + +Configuration +- -r activates RAPL (deprecated) +- -R activates RAPL +- -p activates performance counters. perf_list is coma separated list of performance counters without space. +- -l lists the possible performance counters and quits +- -d activates network monitoring +- -u activates system-level load monitoring +- -s activates statistics of overhead in nanoseconds + +MojitO/S is published under the GPL3 license and is part of the [Energumen Project](https://www.irit.fr/energumen/) + +<img src="https://www.irit.fr/energumen/images/energumen.png" width="100"> + +## Installation Instructions + +Dependencies +```bash +sudo apt install libpowercap0 libpowercap-dev powercap-utils python3 +``` +Download the source code +```bash +git clone https://gitlab.irit.fr/sepia-pub/mojitos.git +``` +Compile the code +```bash +cd mojitos +make +``` +To execute mojitos without being root to monitor performance counters +```bash +sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' +``` +To execute mohitos without being root for accessing RAPL +```bash +sudo chmod a+w /sys/class/powercap/intel-rapl/*/* +sudo chmod a+w /sys/class/powercap/intel-rapl/*/*/* +``` + +## Tutorial and Examples + +RAPL values during 2 seconds with a frequency of 2 Hz +```bash +$ ./mojitos -t 2 -f 2 -r +#timestamp package-00 core0 dram0 +1036389.135659868 10986 2869 1526 +1036389.500183551 1291440 255736 515562 +1036390.000754048 1333553 228393 689513 +1036390.500113978 1581967 267944 701536 +``` +Performance counters (cpu_cycle, cache_ll_r_a and page_faults) during 4 seconds with a frequency of 1Hz. For cache performance counters, _r and _w are respectively read and write, and _a, _m and _p are respectively access, miss, pending. + +```bash +$ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults +#timestamp cpu_cycles cache_ll page_faults +1036846.351749455 571199 1232 0 +1036847.001098880 348173344 2451387 872 +1036848.000166158 388112961 2509305 791 +1036849.000191883 402255979 2625283 799 +``` + +Network values with no time limit with a frequency of 1Hz. rxp and txp are the number of received and sent packets, while rxb and txp are the number of received and sent bytes. +```bash +$ ./mojitos -t 0 -f 1 -d enp0s25 +#timestamp rxp rxb txp txb +1036559.277376027 0 0 0 0 +1036560.000161101 4 581 2 179 +1036561.000083968 178 268675 55 4954 +1036562.000076162 11 1010 5 510 +1036563.000069724 17 1643 12 3602 +1036564.000113394 990 1493008 369 27299 +``` + +Overhead of the monitoring for RAPL and cpu_cycle +```bash +$ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s +#timestamp cpu_cycles package-00 core0 dram0 overhead +1036988.197227391 162214 19898 4944 1586 149612 +1036989.000151326 332613664 2513116 379577 1115171 739573 +1036990.000116433 482150700 3321341 587218 1380673 315719 +1036991.000182835 525984292 3592582 691221 1385982 272182 +1036992.000165117 397678789 2770561 444030 1375729 510379 +``` diff --git a/makefile b/makefile index ab8c2dc..7229c46 100644 --- a/makefile +++ b/makefile @@ -1,48 +1,48 @@ -.PHONY: all clean mojitos mojitos_group debug format - -SRC_DIR = src -OBJ_DIR = obj -BIN_DIR = bin - -OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o frapl.o network.o load.o infiniband.o temperature.o) -OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) - -CC = gcc -CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic - -ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q - - -# depending on the context it may need to be changed to all: mojitos mojitos_group -all: mojitos - -mojitos: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS) - $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos $(OBJECTS) -lpowercap - -$(OBJ_DIR)/counters_%.o: $(SRC_DIR)/counters_%.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h - $(CC) $(CFLAGS) -c $< -o $@ - -$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.py - python3 ./$(SRC_DIR)/counters_option.py > $(SRC_DIR)/counters_option.h - -$(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h - $(CC) $(CFLAGS) -c $< -o $@ - -$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(SRC_DIR)/%.h - $(CC) $(CFLAGS) -c $< -o $@ - -$(OBJ_DIR): - mkdir -p $(OBJ_DIR) - -$(BIN_DIR): - mkdir -p $(BIN_DIR) - -debug: CFLAGS += -DDEBUG -g -debug: all - -format: - $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h - -clean: - \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* - \rm -f $(SRC_DIR)/counters_option.h +.PHONY: all clean mojitos mojitos_group debug format + +SRC_DIR = src +OBJ_DIR = obj +BIN_DIR = bin + +OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o frapl.o network.o load.o infiniband.o temperature.o) +OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) + +CC = gcc +CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic + +ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q + + +# depending on the context it may need to be changed to all: mojitos mojitos_group +all: mojitos + +mojitos: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS) + $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos $(OBJECTS) -lpowercap + +$(OBJ_DIR)/counters_%.o: $(SRC_DIR)/counters_%.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h + $(CC) $(CFLAGS) -c $< -o $@ + +$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.py + python3 ./$(SRC_DIR)/counters_option.py > $(SRC_DIR)/counters_option.h + +$(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(SRC_DIR)/%.h + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJ_DIR): + mkdir -p $(OBJ_DIR) + +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +debug: CFLAGS += -DDEBUG -g +debug: all + +format: + $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h + +clean: + \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* + \rm -f $(SRC_DIR)/counters_option.h diff --git a/src/counters.c b/src/counters.c index 5a24eed..643c9a3 100644 --- a/src/counters.c +++ b/src/counters.c @@ -1,212 +1,212 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <linux/perf_event.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/ioctl.h> -#include <stdio.h> -#include <stdint.h> -#include <asm/unistd.h> -#include <stdint.h> - -struct _counter_t { - int nbcores; - int nbperf; - int **counters; - uint64_t *counters_values; - uint64_t *tmp_counters_values; - - int *perf_indexes; - -}; -typedef struct _counter_t *counter_t; - -#include "counters_option.h" - -void show_all_counters() -{ - for(unsigned int i=0; i<nb_counter_option; i++) - printf("%s\n", perf_static_info[i].name); -} - -void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) -{ - *perf_type = malloc(nb*sizeof(__u32)); - *perf_key = malloc(nb*sizeof(__u64)); - for(int i=0; i<nb; i++) { - (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; - (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; - } -} -void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) -{ - char *token; - *nb_perf=0; - *perf_indexes=NULL; - while((token=strtok(perf_string, ",")) != NULL) { - perf_string = NULL; - unsigned int i; - for(i=0; i<nb_counter_option; i++) { - if(strcmp(perf_static_info[i].name, token) == 0) { - (*nb_perf)++; - (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); - (*perf_indexes)[*nb_perf-1]=i; - break; - } - } - if(i == nb_counter_option) { - fprintf(stderr, "Unknown performance counter: %s\n", token); - exit(EXIT_FAILURE); - } - } -} - -static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) -{ - long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } - return res; -} - -counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) -{ - struct perf_event_attr pe; - unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); - memset(&pe, 0, sizeof(struct perf_event_attr)); - pe.size = sizeof(struct perf_event_attr); - pe.disabled = 1; - - counter_t counters = malloc(sizeof(struct _counter_t)); - counters->nbperf = nb_perf; - counters->nbcores=nbcores; - counters->counters=malloc(nb_perf*sizeof(int *)); - for (int i=0; i<nb_perf; i++) { - pe.type = types[i]; - pe.config = names[i]; - counters->counters[i] = malloc(nbcores*sizeof(int)); - - for (unsigned int core=0; core<nbcores; core++) { - counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); - } - } - return counters; -} - -void clean_counters(void *ptr) -{ - counter_t counters = (counter_t) ptr; - for(int counter=0; counter<counters->nbperf; counter++) { - for(int core=0; core<counters->nbcores; core++) - close(counters->counters[counter][core]); - free(counters->counters[counter]); - } - free(counters->counters); - free(counters->counters_values); - free(counters->tmp_counters_values); - free(counters->perf_indexes); - - free(counters); -} - -void start_counters(counter_t counters) -{ - for(int counter=0; counter<counters->nbperf; counter++) - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); -} - -void reset_counters(counter_t counters) -{ - for(int counter=0; counter<counters->nbperf; counter++) - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); -} - -void _get_counters(counter_t counters, uint64_t *values) -{ - for(int i=0; i<counters->nbperf; i++) { - uint64_t accu=0; - uint64_t count=0; - for (int core=0; core<counters->nbcores; core++) { - if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) { - fprintf(stderr, "Cannot read result"); - exit(EXIT_FAILURE); - } - accu += count; - } - values[i] = accu; - } -} - - - - - - -unsigned int init_counters(char *args, void **state) -{ - int nb_perf; - int *perf_indexes=NULL; - - perf_event_list(args, &nb_perf, &perf_indexes); - - __u32 *perf_type; - __u64 *perf_key; - perf_type_key(&perf_type, &perf_key, perf_indexes, nb_perf); - counter_t fd = _init_counters(nb_perf, perf_type, perf_key); - free(perf_type); - free(perf_key); - - fd->perf_indexes = perf_indexes; - fd->counters_values = malloc(nb_perf*sizeof(uint64_t)); - fd->tmp_counters_values = malloc(nb_perf*sizeof(uint64_t)); - start_counters(fd); - _get_counters(fd, fd->counters_values); - *state = (void *) fd; - - return nb_perf; -} - -unsigned int get_counters(uint64_t *results, void *ptr) -{ - counter_t state = (counter_t) ptr; - - _get_counters(state, state->tmp_counters_values); - for(int i=0; i<state->nbperf; i++) - results[i] = state->tmp_counters_values[i] - state->counters_values[i]; - - memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); - return state->nbperf; -} - -void label_counters(char **labels, void *ptr) -{ - counter_t state = (counter_t) ptr; - for(int i=0; i<state->nbperf; i++) - labels[i] = perf_static_info[state->perf_indexes[i]].name; - -} +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <linux/perf_event.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdint.h> +#include <asm/unistd.h> +#include <stdint.h> + +struct _counter_t { + int nbcores; + int nbperf; + int **counters; + uint64_t *counters_values; + uint64_t *tmp_counters_values; + + int *perf_indexes; + +}; +typedef struct _counter_t *counter_t; + +#include "counters_option.h" + +void show_all_counters() +{ + for(unsigned int i=0; i<nb_counter_option; i++) + printf("%s\n", perf_static_info[i].name); +} + +void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) +{ + *perf_type = malloc(nb*sizeof(__u32)); + *perf_key = malloc(nb*sizeof(__u64)); + for(int i=0; i<nb; i++) { + (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; + (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; + } +} +void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) +{ + char *token; + *nb_perf=0; + *perf_indexes=NULL; + while((token=strtok(perf_string, ",")) != NULL) { + perf_string = NULL; + unsigned int i; + for(i=0; i<nb_counter_option; i++) { + if(strcmp(perf_static_info[i].name, token) == 0) { + (*nb_perf)++; + (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); + (*perf_indexes)[*nb_perf-1]=i; + break; + } + } + if(i == nb_counter_option) { + fprintf(stderr, "Unknown performance counter: %s\n", token); + exit(EXIT_FAILURE); + } + } +} + +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) +{ + long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + if (res == -1) { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } + return res; +} + +counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +{ + struct perf_event_attr pe; + unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); + memset(&pe, 0, sizeof(struct perf_event_attr)); + pe.size = sizeof(struct perf_event_attr); + pe.disabled = 1; + + counter_t counters = malloc(sizeof(struct _counter_t)); + counters->nbperf = nb_perf; + counters->nbcores=nbcores; + counters->counters=malloc(nb_perf*sizeof(int *)); + for (int i=0; i<nb_perf; i++) { + pe.type = types[i]; + pe.config = names[i]; + counters->counters[i] = malloc(nbcores*sizeof(int)); + + for (unsigned int core=0; core<nbcores; core++) { + counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); + } + } + return counters; +} + +void clean_counters(void *ptr) +{ + counter_t counters = (counter_t) ptr; + for(int counter=0; counter<counters->nbperf; counter++) { + for(int core=0; core<counters->nbcores; core++) + close(counters->counters[counter][core]); + free(counters->counters[counter]); + } + free(counters->counters); + free(counters->counters_values); + free(counters->tmp_counters_values); + free(counters->perf_indexes); + + free(counters); +} + +void start_counters(counter_t counters) +{ + for(int counter=0; counter<counters->nbperf; counter++) + for(int core=0; core<counters->nbcores; core++) + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); +} + +void reset_counters(counter_t counters) +{ + for(int counter=0; counter<counters->nbperf; counter++) + for(int core=0; core<counters->nbcores; core++) + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); +} + +void _get_counters(counter_t counters, uint64_t *values) +{ + for(int i=0; i<counters->nbperf; i++) { + uint64_t accu=0; + uint64_t count=0; + for (int core=0; core<counters->nbcores; core++) { + if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) { + fprintf(stderr, "Cannot read result"); + exit(EXIT_FAILURE); + } + accu += count; + } + values[i] = accu; + } +} + + + + + + +unsigned int init_counters(char *args, void **state) +{ + int nb_perf; + int *perf_indexes=NULL; + + perf_event_list(args, &nb_perf, &perf_indexes); + + __u32 *perf_type; + __u64 *perf_key; + perf_type_key(&perf_type, &perf_key, perf_indexes, nb_perf); + counter_t fd = _init_counters(nb_perf, perf_type, perf_key); + free(perf_type); + free(perf_key); + + fd->perf_indexes = perf_indexes; + fd->counters_values = malloc(nb_perf*sizeof(uint64_t)); + fd->tmp_counters_values = malloc(nb_perf*sizeof(uint64_t)); + start_counters(fd); + _get_counters(fd, fd->counters_values); + *state = (void *) fd; + + return nb_perf; +} + +unsigned int get_counters(uint64_t *results, void *ptr) +{ + counter_t state = (counter_t) ptr; + + _get_counters(state, state->tmp_counters_values); + for(int i=0; i<state->nbperf; i++) + results[i] = state->tmp_counters_values[i] - state->counters_values[i]; + + memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); + return state->nbperf; +} + +void label_counters(char **labels, void *ptr) +{ + counter_t state = (counter_t) ptr; + for(int i=0; i<state->nbperf; i++) + labels[i] = perf_static_info[state->perf_indexes[i]].name; + +} diff --git a/src/counters.h b/src/counters.h index af20717..bd2d0a5 100644 --- a/src/counters.h +++ b/src/counters.h @@ -1,26 +1,26 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_counters(char *, void **); -unsigned int get_counters(uint64_t *results, void *); -void clean_counters(void *); -void label_counters(char **labels, void *); - -void show_all_counters(); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_counters(char *, void **); +unsigned int get_counters(uint64_t *results, void *); +void clean_counters(void *); +void label_counters(char **labels, void *); + +void show_all_counters(); diff --git a/src/counters_option.py b/src/counters_option.py index 877a33a..d853e41 100755 --- a/src/counters_option.py +++ b/src/counters_option.py @@ -1,62 +1,62 @@ -#! /usr/bin/python3 - -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - -linux_include = '/usr/include/linux/perf_event.h' - -string = """#include <linux/perf_event.h> - -typedef struct counter_option { - char *name; - __u32 perf_type; - __u64 perf_key; -} counter_option; - -static counter_option perf_static_info[] = {""" -print(string) - -nb = 0 - -black_list = ['stalled_cycles_frontend','stalled_cycles_backend', - 'cache_l1i', 'cache_op_write', 'cache_result_miss'] - -with open(linux_include, 'r') as infile: - mode = '' - for line in infile: - if 'perf_hw_id' in line: - mode = 'PERF_TYPE_HARDWARE' - elif 'perf_hw_cache_' in line: - mode = 'PERF_TYPE_HW_CACHE' - elif 'perf_sw_id' in line: - mode = 'PERF_TYPE_SOFTWARE' - elif 'PERF_COUNT_' in line and '=' in line: - perf_name = line.split()[0] - short_perf = perf_name[14:].lower() - if short_perf in black_list: - continue - if mode == 'PERF_TYPE_HW_CACHE': - for op_id, op_id_str in enumerate(['r', 'w', 'p']): - op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] - for result_id, result_id_str in enumerate(['a', 'm']): - result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] - - res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( - short_perf, op_id_str, result_id_str, - mode, - perf_name, - op_id_names[op_id], - result_id_names[result_id]) - - print(res) - nb += 1 - - else: - res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' - print(res) - nb += 1 - - -print('};') - -print('static unsigned int nb_counter_option =',nb,';') +#! /usr/bin/python3 + +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + +linux_include = '/usr/include/linux/perf_event.h' + +string = """#include <linux/perf_event.h> + +typedef struct counter_option { + char *name; + __u32 perf_type; + __u64 perf_key; +} counter_option; + +static counter_option perf_static_info[] = {""" +print(string) + +nb = 0 + +black_list = ['stalled_cycles_frontend','stalled_cycles_backend', + 'cache_l1i', 'cache_op_write', 'cache_result_miss'] + +with open(linux_include, 'r') as infile: + mode = '' + for line in infile: + if 'perf_hw_id' in line: + mode = 'PERF_TYPE_HARDWARE' + elif 'perf_hw_cache_' in line: + mode = 'PERF_TYPE_HW_CACHE' + elif 'perf_sw_id' in line: + mode = 'PERF_TYPE_SOFTWARE' + elif 'PERF_COUNT_' in line and '=' in line: + perf_name = line.split()[0] + short_perf = perf_name[14:].lower() + if short_perf in black_list: + continue + if mode == 'PERF_TYPE_HW_CACHE': + for op_id, op_id_str in enumerate(['r', 'w', 'p']): + op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] + for result_id, result_id_str in enumerate(['a', 'm']): + result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] + + res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( + short_perf, op_id_str, result_id_str, + mode, + perf_name, + op_id_names[op_id], + result_id_names[result_id]) + + print(res) + nb += 1 + + else: + res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' + print(res) + nb += 1 + + +print('};') + +print('static unsigned int nb_counter_option =',nb,';') diff --git a/src/frapl.c b/src/frapl.c index 9874a12..62c94bc 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -1,184 +1,184 @@ -/******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> - - -#define MAX_HEADER 128 -#define UNUSED(expr) do { (void)(expr); } while (0) - - -char *get_frapl_string(const char *filename) -{ - int fd = open(filename, O_RDONLY); - if( fd == -1) { - return NULL; - } - char *result = malloc(MAX_HEADER); - int nb = read(fd, result, MAX_HEADER); - close(fd); - result[nb-1] = 0; - return (result); -} - -void test_append(char *name, int i) -{ - //char last = name[strlen(name)-1]; - //if (last>='0' && last <= '9') - // return; - sprintf(name+strlen(name), "%d", i); -} - - -struct _frapl_t { - unsigned int nb; - char **names; - int *fids; - uint64_t *values; - uint64_t *tmp_values; - -}; -typedef struct _frapl_t _frapl_t; - - -void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) -{ - rapl->nb += 1; - rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); - rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); - - rapl->names[rapl->nb-1] = malloc(strlen(name)+1); - strcpy(rapl->names[rapl->nb-1], name); - //printf("%s\n", energy_uj); - - int fd = open(energy_uj, O_RDONLY); - - if (fd < 0) { - fprintf(stderr, "%s ", energy_uj); - perror("open"); - exit(1); - } - rapl->fids[rapl->nb-1] = fd; -} - - -void _get_frapl(uint64_t *values, _frapl_t *rapl) -{ - static char buffer[512]; - - for (unsigned int i = 0; i < rapl->nb; i++) { - - if (pread(rapl->fids[i], buffer, 100, 0) < 0) { - perror("pread"); - exit(1); - } - values[i] = strtoull(buffer, NULL, 10); - } -} - - -unsigned int init_frapl(char *none, void **ptr) -{ - UNUSED(none); - _frapl_t *rapl = malloc(sizeof(_frapl_t)); - rapl->nb = 0; - rapl->names = NULL; - rapl->fids = NULL; - - char buffer[1024]; - char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; - char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - - for (unsigned int i=0;; i++) { - sprintf(buffer, name_base, i, "name"); - char *tmp = get_frapl_string(buffer); - if (tmp == NULL) break; - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); - add_frapl_source(rapl, tmp, buffer); - free(tmp); - - for (unsigned int j=0;; j++) { - sprintf(buffer, name_sub, i, i, j, "name"); - char *tmp_sub = get_frapl_string(buffer); - if (tmp_sub == NULL) break; - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - - - sprintf(buffer, name_sub, i, i, j, "energy_uj"); - add_frapl_source(rapl, tmp_sub, buffer); - - free(tmp_sub); - } - } - - rapl->values = calloc(sizeof(uint64_t), rapl->nb); - rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); - - _get_frapl(rapl->values, rapl); - - *ptr = (void *)rapl; - return rapl->nb; -} - - -unsigned int get_frapl(uint64_t *results, void *ptr) -{ - _frapl_t *state = (_frapl_t *) ptr; - _get_frapl(state->tmp_values, state); - for(unsigned int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; - - memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); - return state->nb; -} - -void clean_frapl(void *ptr) -{ - _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) { - free(rapl->names[i]); - close(rapl->fids[i]); - } - free(rapl->names); - free(rapl->fids); - free(rapl->values); - free(rapl->tmp_values); - free(rapl); -} - - -void label_frapl(char **labels, void *ptr) -{ - _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) - labels[i] = rapl->names[i]; -} +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> + + +#define MAX_HEADER 128 +#define UNUSED(expr) do { (void)(expr); } while (0) + + +char *get_frapl_string(const char *filename) +{ + int fd = open(filename, O_RDONLY); + if( fd == -1) { + return NULL; + } + char *result = malloc(MAX_HEADER); + int nb = read(fd, result, MAX_HEADER); + close(fd); + result[nb-1] = 0; + return (result); +} + +void test_append(char *name, int i) +{ + //char last = name[strlen(name)-1]; + //if (last>='0' && last <= '9') + // return; + sprintf(name+strlen(name), "%d", i); +} + + +struct _frapl_t { + unsigned int nb; + char **names; + int *fids; + uint64_t *values; + uint64_t *tmp_values; + +}; +typedef struct _frapl_t _frapl_t; + + +void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) +{ + rapl->nb += 1; + rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); + rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); + + rapl->names[rapl->nb-1] = malloc(strlen(name)+1); + strcpy(rapl->names[rapl->nb-1], name); + //printf("%s\n", energy_uj); + + int fd = open(energy_uj, O_RDONLY); + + if (fd < 0) { + fprintf(stderr, "%s ", energy_uj); + perror("open"); + exit(1); + } + rapl->fids[rapl->nb-1] = fd; +} + + +void _get_frapl(uint64_t *values, _frapl_t *rapl) +{ + static char buffer[512]; + + for (unsigned int i = 0; i < rapl->nb; i++) { + + if (pread(rapl->fids[i], buffer, 100, 0) < 0) { + perror("pread"); + exit(1); + } + values[i] = strtoull(buffer, NULL, 10); + } +} + + +unsigned int init_frapl(char *none, void **ptr) +{ + UNUSED(none); + _frapl_t *rapl = malloc(sizeof(_frapl_t)); + rapl->nb = 0; + rapl->names = NULL; + rapl->fids = NULL; + + char buffer[1024]; + char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; + char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; + + for (unsigned int i=0;; i++) { + sprintf(buffer, name_base, i, "name"); + char *tmp = get_frapl_string(buffer); + if (tmp == NULL) break; + //printf("%s\n", tmp); + test_append(tmp, i); + //printf("%s -> %s\n", buffer, tmp); + + sprintf(buffer, name_base, i, "energy_uj"); + add_frapl_source(rapl, tmp, buffer); + free(tmp); + + for (unsigned int j=0;; j++) { + sprintf(buffer, name_sub, i, i, j, "name"); + char *tmp_sub = get_frapl_string(buffer); + if (tmp_sub == NULL) break; + //printf("%s\n", tmp_sub); + test_append(tmp_sub, i); + //printf("%s -> %s\n", buffer, tmp_sub); + + + sprintf(buffer, name_sub, i, i, j, "energy_uj"); + add_frapl_source(rapl, tmp_sub, buffer); + + free(tmp_sub); + } + } + + rapl->values = calloc(sizeof(uint64_t), rapl->nb); + rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); + + _get_frapl(rapl->values, rapl); + + *ptr = (void *)rapl; + return rapl->nb; +} + + +unsigned int get_frapl(uint64_t *results, void *ptr) +{ + _frapl_t *state = (_frapl_t *) ptr; + _get_frapl(state->tmp_values, state); + for(unsigned int i=0; i<state->nb; i++) + results[i] = state->tmp_values[i] - state->values[i]; + + memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); + return state->nb; +} + +void clean_frapl(void *ptr) +{ + _frapl_t *rapl = (_frapl_t *) ptr; + for(unsigned int i=0; i<rapl->nb; i++) { + free(rapl->names[i]); + close(rapl->fids[i]); + } + free(rapl->names); + free(rapl->fids); + free(rapl->values); + free(rapl->tmp_values); + free(rapl); +} + + +void label_frapl(char **labels, void *ptr) +{ + _frapl_t *rapl = (_frapl_t *) ptr; + for(unsigned int i=0; i<rapl->nb; i++) + labels[i] = rapl->names[i]; +} diff --git a/src/frapl.h b/src/frapl.h index 937108e..8ce4e00 100644 --- a/src/frapl.h +++ b/src/frapl.h @@ -1,25 +1,25 @@ -/******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_frapl(char *, void **); -unsigned int get_frapl(uint64_t *results, void *); -void clean_frapl(void *); -void label_frapl(char **labels, void *); - +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_frapl(char *, void **); +unsigned int get_frapl(uint64_t *results, void *); +void clean_frapl(void *); +void label_frapl(char **labels, void *); + diff --git a/src/infiniband.c b/src/infiniband.c index 6621759..bbc2dce 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -1,81 +1,81 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ -#include <stdlib.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> - -#include <glob.h> - -#include <stdint.h> - -#define NB_SENSOR 4 -#define UNUSED(expr) do { (void)(expr); } while (0) - -struct network_t { - uint64_t values[NB_SENSOR]; - uint64_t tmp_values[NB_SENSOR]; - int sources[NB_SENSOR]; -}; -unsigned int _get_network(uint64_t *results, int *sources); - - -unsigned int init_infiniband(char *infi_path, void **ptr) -{ - if(infi_path==NULL) - return 0; - - if(strcmp(infi_path,"X")==0) { - - glob_t res; - - glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); - if(res.gl_pathc == 0) - return 0; - infi_path = res.gl_pathv[0]; - } - - char *filenames[] = {"%s/port_rcv_packets", - "%s/port_rcv_data", - "%s/port_xmit_packets", - "%s/port_xmit_data" - }; - - struct network_t *state = malloc(sizeof(struct network_t)); - - char buffer[1024]; - for(int i=0; i<NB_SENSOR; i++) { - sprintf(buffer, filenames[i], infi_path); - state->sources[i] = open(buffer, O_RDONLY); - } - - *ptr = (void *) state; - _get_network(state->values, state->sources); - - return NB_SENSOR; -} - -char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; -void label_infiniband(char **labels, void *none) -{ - UNUSED(none); - for(int i=0; i<NB_SENSOR; i++) - labels[i] = _labels_infiniband[i]; -} +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ +#include <stdlib.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> + +#include <glob.h> + +#include <stdint.h> + +#define NB_SENSOR 4 +#define UNUSED(expr) do { (void)(expr); } while (0) + +struct network_t { + uint64_t values[NB_SENSOR]; + uint64_t tmp_values[NB_SENSOR]; + int sources[NB_SENSOR]; +}; +unsigned int _get_network(uint64_t *results, int *sources); + + +unsigned int init_infiniband(char *infi_path, void **ptr) +{ + if(infi_path==NULL) + return 0; + + if(strcmp(infi_path,"X")==0) { + + glob_t res; + + glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); + if(res.gl_pathc == 0) + return 0; + infi_path = res.gl_pathv[0]; + } + + char *filenames[] = {"%s/port_rcv_packets", + "%s/port_rcv_data", + "%s/port_xmit_packets", + "%s/port_xmit_data" + }; + + struct network_t *state = malloc(sizeof(struct network_t)); + + char buffer[1024]; + for(int i=0; i<NB_SENSOR; i++) { + sprintf(buffer, filenames[i], infi_path); + state->sources[i] = open(buffer, O_RDONLY); + } + + *ptr = (void *) state; + _get_network(state->values, state->sources); + + return NB_SENSOR; +} + +char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; +void label_infiniband(char **labels, void *none) +{ + UNUSED(none); + for(int i=0; i<NB_SENSOR; i++) + labels[i] = _labels_infiniband[i]; +} diff --git a/src/infiniband.h b/src/infiniband.h index 1f6aaf9..4234964 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -1,22 +1,22 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_infiniband(char *infi_path, void **ptr); -void label_infiniband(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_infiniband(char *infi_path, void **ptr); +void label_infiniband(char **labels, void *); diff --git a/src/load.c b/src/load.c index 4f11346..92b1088 100644 --- a/src/load.c +++ b/src/load.c @@ -1,92 +1,92 @@ -/******************************************************* - Copyright (C) 2019-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ -#include <unistd.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <stdio.h> - -#define LOAD_BUFFER_SIZE 1024 -#define UNUSED(expr) do { (void)(expr); } while (0) -char buffer[LOAD_BUFFER_SIZE]; - -static int load_fid=-1; -static uint64_t load_values[10]= {0,0,0,0,0,0,0,0,0,0}; -static uint64_t tmp_load_values[10]= {0,0,0,0,0,0,0,0,0,0}; -static char *stat = "/proc/stat"; - -void _get_load(uint64_t *results) -{ - if (pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0) < 0) { - perror("pread"); - exit(1); - } - int pos=0; - while(buffer[pos] > '9' || buffer[pos] < '0') pos++; - for(int i=0; i<10; i++) { - results[i] = strtoull(buffer+pos, NULL, 10); - while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; - pos++; - } -} - -// Public interface - -unsigned int init_load(char *argument, void **state) -{ - UNUSED(argument); - UNUSED(state); - load_fid = open(stat, O_RDONLY); - if (load_fid < 0) { - fprintf(stderr,"%s ",stat); - perror("open"); - exit(1); - } - _get_load(load_values); - return 10; -} - -unsigned int get_load(uint64_t *results, void *state) -{ - UNUSED(state); - _get_load(tmp_load_values); - for(int i=0; i<10; i++) - results[i] = tmp_load_values[i] - load_values[i]; - - memcpy(load_values, tmp_load_values, sizeof(load_values)); - return 10; -} - -void clean_load(void *state) -{ - UNUSED(state); - close(load_fid); -} - -char *_labels[10] = {"user","nice","system","idle","iowait","irq", - "softirq","steal","guest","guest_nice" - }; -void label_load(char **labels, void *none) -{ - UNUSED(none); - for(int i=0; i<10; i++) - labels[i] = _labels[i]; -} +/******************************************************* + Copyright (C) 2019-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +#define LOAD_BUFFER_SIZE 1024 +#define UNUSED(expr) do { (void)(expr); } while (0) +char buffer[LOAD_BUFFER_SIZE]; + +static int load_fid=-1; +static uint64_t load_values[10]= {0,0,0,0,0,0,0,0,0,0}; +static uint64_t tmp_load_values[10]= {0,0,0,0,0,0,0,0,0,0}; +static char *stat = "/proc/stat"; + +void _get_load(uint64_t *results) +{ + if (pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0) < 0) { + perror("pread"); + exit(1); + } + int pos=0; + while(buffer[pos] > '9' || buffer[pos] < '0') pos++; + for(int i=0; i<10; i++) { + results[i] = strtoull(buffer+pos, NULL, 10); + while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; + pos++; + } +} + +// Public interface + +unsigned int init_load(char *argument, void **state) +{ + UNUSED(argument); + UNUSED(state); + load_fid = open(stat, O_RDONLY); + if (load_fid < 0) { + fprintf(stderr,"%s ",stat); + perror("open"); + exit(1); + } + _get_load(load_values); + return 10; +} + +unsigned int get_load(uint64_t *results, void *state) +{ + UNUSED(state); + _get_load(tmp_load_values); + for(int i=0; i<10; i++) + results[i] = tmp_load_values[i] - load_values[i]; + + memcpy(load_values, tmp_load_values, sizeof(load_values)); + return 10; +} + +void clean_load(void *state) +{ + UNUSED(state); + close(load_fid); +} + +char *_labels[10] = {"user","nice","system","idle","iowait","irq", + "softirq","steal","guest","guest_nice" + }; +void label_load(char **labels, void *none) +{ + UNUSED(none); + for(int i=0; i<10; i++) + labels[i] = _labels[i]; +} diff --git a/src/load.h b/src/load.h index 299fa3e..78c1b40 100644 --- a/src/load.h +++ b/src/load.h @@ -1,24 +1,24 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_load(char *, void **); -unsigned int get_load(uint64_t *results, void *); -void clean_load(void *); -void label_load(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_load(char *, void **); +unsigned int get_load(uint64_t *results, void *); +void clean_load(void *); +void label_load(char **labels, void *); diff --git a/src/mojitos.c b/src/mojitos.c index 3569d1b..7d680b1 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -1,296 +1,296 @@ -/******************************************************* - - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <time.h> -#include <signal.h> -#include <inttypes.h> -#include <unistd.h> - -#include "counters.h" -#include "rapl.h" -#include "frapl.h" -#include "network.h" -#include "infiniband.h" -#include "load.h" -#include "temperature.h" - -#define UNUSED(expr) do { (void)(expr); } while (0) -#define PANIC(code, fmt, ...) \ - do { \ - fprintf(stderr, "Exit on error: "); \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - fprintf(stderr, "\n"); \ - exit(code); \ - } while (0) - - -void usage(char **argv) -{ - printf("Usage : %s [-rRluc] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" - " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" - "if time==0 then loops infinitively\n" - "if -e is present, time and freq are not used\n" - "-r activates RAPL\n" - "-R activates the file version of RAPL\n" - "-p activates performance counters\n" - " perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n" - "-l lists the possible performance counters and quits\n" - "-d activates network monitoring (if network_device is X, tries to detect it automatically)\n" - "-i activates infiniband monitoring (if infiniband_path is X, tries to detect it automatically)\n" - "-s activates statistics of overhead in nanoseconds\n" - "-u activates report of system load\n" - "-c activates report of processor temperature\n" - , argv[0]); - exit(EXIT_SUCCESS); -} - -void sighandler(int none) -{ - UNUSED(none); -} - -void flush(int none) -{ - UNUSED(none); - exit(0); -} - -FILE *output; -void flushexit() -{ - if (output != NULL) { - fflush(output); - fclose(output); - } -} - -typedef unsigned int (initializer_t)(char *, void **); -typedef void (labeler_t)(char **, void *); -typedef unsigned int (*getter_t)(uint64_t *, void *); -typedef void (*cleaner_t)(void *); - -unsigned int nb_sources = 0; -void **states = NULL; -getter_t *getter = NULL; -cleaner_t *cleaner = NULL; - -unsigned int nb_sensors = 0; -char **labels = NULL; -uint64_t *values = NULL; - -void add_source(initializer_t init, char *arg, labeler_t labeler, - getter_t get, cleaner_t clean) -{ - nb_sources++; - states = realloc(states, nb_sources * sizeof(void *)); - int nb = init(arg, &states[nb_sources - 1]); - if (nb == 0) { - nb_sources--; - states = realloc(states, nb_sources * sizeof(void *)); - return; - } - - getter = realloc(getter, nb_sources * sizeof(void *)); - getter[nb_sources - 1] = get; - cleaner = realloc(cleaner, nb_sources * sizeof(void *)); - cleaner[nb_sources - 1] = clean; - - labels = realloc(labels, (nb_sensors + nb) * sizeof(char *)); - labeler(labels + nb_sensors, states[nb_sources - 1]); - - values = realloc(values, (nb_sensors + nb) * sizeof(uint64_t)); - nb_sensors += nb; -} - -int main(int argc, char **argv) -{ - int total_time = 1; - int delta = 0; - int frequency = 1; - char **application = NULL; - - int stat_mode = -1; - - if (argc == 1) { - usage(argv); - } - - output = stdout; - - atexit(flushexit); - signal(15, flush); - - int c; - while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) - switch (c) { - case 'f': - if (optind >= argc) PANIC(1,"-f, no frequency provided"); - frequency = atoi(argv[optind]); - break; - case 't': - if (optind >= argc) PANIC(1,"-t, no time provided"); - total_time = atoi(argv[optind]); - delta = 1; - if (total_time == 0) { - total_time = 1; - delta = 0; - } - break; - case 'd': - add_source(init_network, argv[optind], label_network, get_network, clean_network); - break; - case 'i': - add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); - break; - case 'o': - if (optind >= argc) PANIC(1,"-o, no logfile provided"); - if ((output = fopen(argv[optind], "wb")) == NULL) { - perror("fopen"); - PANIC(1, "-o %s", argv[optind]); - } - break; - case 'e': - application = &argv[optind]; - signal(17, sighandler); - break; - case 'p': - if (optind >= argc) PANIC(1,"-p, no counter provided"); - add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); - break; - case 'r': - add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); - break; - case 'R': - add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); - break; - case 'u': - add_source(init_load, NULL, label_load, get_load, clean_load); - break; - case 'c': - add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); - break; - case 's': - stat_mode = 0; - break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); - default: - usage(argv); - } - - - setvbuf(output, NULL, _IONBF, BUFSIZ); - struct timespec ts; - struct timespec ts_ref; - - fprintf(output, "#timestamp "); - - for (unsigned int i = 0; i < nb_sensors; i++) { - fprintf(output, "%s ", labels[i]); - } - - if (stat_mode == 0) { - fprintf(output, "overhead "); - } - - fprintf(output, "\n"); - - unsigned long int stat_data = 0; - - for (int temps = 0; temps < total_time * frequency; temps += delta) { - clock_gettime(CLOCK_MONOTONIC, &ts_ref); - - // Get Data - unsigned int current = 0; - for (unsigned int i = 0; i < nb_sources; i++) { - current += getter[i](&values[current], states[i]); - } - - if (application != NULL) { - - if (fork() == 0) { - execvp(application[0], application); - exit(0); - } - pause(); - clock_gettime(CLOCK_MONOTONIC, &ts); - if (ts.tv_nsec >= ts_ref.tv_nsec) { - fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec), ts.tv_nsec - ts_ref.tv_nsec); - } else { - fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000000000 + ts.tv_nsec - ts_ref.tv_nsec); - } - } else { -#ifdef DEBUG - clock_gettime(CLOCK_MONOTONIC, &ts); - fprintf(stderr, "%ld\n", (ts.tv_nsec - ts_ref.tv_nsec) / 1000); - //Indiv: mean: 148 std: 31 % med: 141 std: 28 % - //Group: mean: 309 std: 41 % med: 297 std: 39 % -#endif - if (stat_mode == 0) { - clock_gettime(CLOCK_MONOTONIC, &ts); - if (ts.tv_nsec >= ts_ref.tv_nsec) { - stat_data = ts.tv_nsec - ts_ref.tv_nsec; - } else { - stat_data = 1000000000 + ts.tv_nsec - ts_ref.tv_nsec; - } - } - - // Treat Data - fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); - } - - for (unsigned int i = 0; i < nb_sensors; i++) { - fprintf(output, "%" PRIu64 " ", values[i]); - } - - if (stat_mode == 0) { - fprintf(output, "%ld ", stat_data); - } - - fprintf(output, "\n"); - - if (application != NULL) { - break; - } - - clock_gettime(CLOCK_MONOTONIC, &ts); - usleep(1000 * 1000 / frequency - (ts.tv_nsec / 1000) % (1000 * 1000 / frequency)); - } - - for (unsigned int i = 0; i < nb_sources; i++) { - cleaner[i](states[i]); - } - - if (nb_sources > 0) { - free(getter); - free(cleaner); - free(labels); - free(values); - free(states); - } -} - - - - +/******************************************************* + + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <signal.h> +#include <inttypes.h> +#include <unistd.h> + +#include "counters.h" +#include "rapl.h" +#include "frapl.h" +#include "network.h" +#include "infiniband.h" +#include "load.h" +#include "temperature.h" + +#define UNUSED(expr) do { (void)(expr); } while (0) +#define PANIC(code, fmt, ...) \ + do { \ + fprintf(stderr, "Exit on error: "); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + exit(code); \ + } while (0) + + +void usage(char **argv) +{ + printf("Usage : %s [-rRluc] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" + " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" + "if time==0 then loops infinitively\n" + "if -e is present, time and freq are not used\n" + "-r activates RAPL\n" + "-R activates the file version of RAPL\n" + "-p activates performance counters\n" + " perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n" + "-l lists the possible performance counters and quits\n" + "-d activates network monitoring (if network_device is X, tries to detect it automatically)\n" + "-i activates infiniband monitoring (if infiniband_path is X, tries to detect it automatically)\n" + "-s activates statistics of overhead in nanoseconds\n" + "-u activates report of system load\n" + "-c activates report of processor temperature\n" + , argv[0]); + exit(EXIT_SUCCESS); +} + +void sighandler(int none) +{ + UNUSED(none); +} + +void flush(int none) +{ + UNUSED(none); + exit(0); +} + +FILE *output; +void flushexit() +{ + if (output != NULL) { + fflush(output); + fclose(output); + } +} + +typedef unsigned int (initializer_t)(char *, void **); +typedef void (labeler_t)(char **, void *); +typedef unsigned int (*getter_t)(uint64_t *, void *); +typedef void (*cleaner_t)(void *); + +unsigned int nb_sources = 0; +void **states = NULL; +getter_t *getter = NULL; +cleaner_t *cleaner = NULL; + +unsigned int nb_sensors = 0; +char **labels = NULL; +uint64_t *values = NULL; + +void add_source(initializer_t init, char *arg, labeler_t labeler, + getter_t get, cleaner_t clean) +{ + nb_sources++; + states = realloc(states, nb_sources * sizeof(void *)); + int nb = init(arg, &states[nb_sources - 1]); + if (nb == 0) { + nb_sources--; + states = realloc(states, nb_sources * sizeof(void *)); + return; + } + + getter = realloc(getter, nb_sources * sizeof(void *)); + getter[nb_sources - 1] = get; + cleaner = realloc(cleaner, nb_sources * sizeof(void *)); + cleaner[nb_sources - 1] = clean; + + labels = realloc(labels, (nb_sensors + nb) * sizeof(char *)); + labeler(labels + nb_sensors, states[nb_sources - 1]); + + values = realloc(values, (nb_sensors + nb) * sizeof(uint64_t)); + nb_sensors += nb; +} + +int main(int argc, char **argv) +{ + int total_time = 1; + int delta = 0; + int frequency = 1; + char **application = NULL; + + int stat_mode = -1; + + if (argc == 1) { + usage(argv); + } + + output = stdout; + + atexit(flushexit); + signal(15, flush); + + int c; + while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) + switch (c) { + case 'f': + if (optind >= argc) PANIC(1,"-f, no frequency provided"); + frequency = atoi(argv[optind]); + break; + case 't': + if (optind >= argc) PANIC(1,"-t, no time provided"); + total_time = atoi(argv[optind]); + delta = 1; + if (total_time == 0) { + total_time = 1; + delta = 0; + } + break; + case 'd': + add_source(init_network, argv[optind], label_network, get_network, clean_network); + break; + case 'i': + add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); + break; + case 'o': + if (optind >= argc) PANIC(1,"-o, no logfile provided"); + if ((output = fopen(argv[optind], "wb")) == NULL) { + perror("fopen"); + PANIC(1, "-o %s", argv[optind]); + } + break; + case 'e': + application = &argv[optind]; + signal(17, sighandler); + break; + case 'p': + if (optind >= argc) PANIC(1,"-p, no counter provided"); + add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); + break; + case 'r': + add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); + break; + case 'R': + add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); + break; + case 'u': + add_source(init_load, NULL, label_load, get_load, clean_load); + break; + case 'c': + add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); + break; + case 's': + stat_mode = 0; + break; + case 'l': + show_all_counters(); + exit(EXIT_SUCCESS); + default: + usage(argv); + } + + + setvbuf(output, NULL, _IONBF, BUFSIZ); + struct timespec ts; + struct timespec ts_ref; + + fprintf(output, "#timestamp "); + + for (unsigned int i = 0; i < nb_sensors; i++) { + fprintf(output, "%s ", labels[i]); + } + + if (stat_mode == 0) { + fprintf(output, "overhead "); + } + + fprintf(output, "\n"); + + unsigned long int stat_data = 0; + + for (int temps = 0; temps < total_time * frequency; temps += delta) { + clock_gettime(CLOCK_MONOTONIC, &ts_ref); + + // Get Data + unsigned int current = 0; + for (unsigned int i = 0; i < nb_sources; i++) { + current += getter[i](&values[current], states[i]); + } + + if (application != NULL) { + + if (fork() == 0) { + execvp(application[0], application); + exit(0); + } + pause(); + clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) { + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec), ts.tv_nsec - ts_ref.tv_nsec); + } else { + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000000000 + ts.tv_nsec - ts_ref.tv_nsec); + } + } else { +#ifdef DEBUG + clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stderr, "%ld\n", (ts.tv_nsec - ts_ref.tv_nsec) / 1000); + //Indiv: mean: 148 std: 31 % med: 141 std: 28 % + //Group: mean: 309 std: 41 % med: 297 std: 39 % +#endif + if (stat_mode == 0) { + clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) { + stat_data = ts.tv_nsec - ts_ref.tv_nsec; + } else { + stat_data = 1000000000 + ts.tv_nsec - ts_ref.tv_nsec; + } + } + + // Treat Data + fprintf(output, "%ld.%09ld ", ts_ref.tv_sec, ts_ref.tv_nsec); + } + + for (unsigned int i = 0; i < nb_sensors; i++) { + fprintf(output, "%" PRIu64 " ", values[i]); + } + + if (stat_mode == 0) { + fprintf(output, "%ld ", stat_data); + } + + fprintf(output, "\n"); + + if (application != NULL) { + break; + } + + clock_gettime(CLOCK_MONOTONIC, &ts); + usleep(1000 * 1000 / frequency - (ts.tv_nsec / 1000) % (1000 * 1000 / frequency)); + } + + for (unsigned int i = 0; i < nb_sources; i++) { + cleaner[i](states[i]); + } + + if (nb_sources > 0) { + free(getter); + free(cleaner); + free(labels); + free(values); + free(states); + } +} + + + + diff --git a/src/network.c b/src/network.c index 647b4b3..6896efc 100644 --- a/src/network.c +++ b/src/network.c @@ -1,128 +1,128 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ -#include <unistd.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> - -#define NB_SENSOR 4 -#define UNUSED(expr) do { (void)(expr); } while (0) - -static char *route = "/proc/net/route"; -struct network_t { - uint64_t values[NB_SENSOR]; - uint64_t tmp_values[NB_SENSOR]; - int sources[NB_SENSOR]; -}; - -unsigned int _get_network(uint64_t *results, int *sources) -{ - if(sources==NULL) - return 0; - char buffer[128]; - for(int i=0; i<NB_SENSOR; i++) { - if (pread(sources[i], buffer, 127, 0) < 0) { - perror("pread"); - exit(1); - } - - results[i] = strtoull(buffer, NULL, 10); - } - return NB_SENSOR; -} - - - -unsigned int init_network(char *dev, void **ptr) -{ - if(dev==NULL) - return 0; - - if(strcmp(dev,"X")==0) { - int fd = open(route, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "%s ", route); - perror("open"); - exit(1); - } - char buffer[1000]; - - if ( read(fd, buffer, 999) < 0 ) { - perror("read"); - close(fd); - exit(1); - } - - char *start_of_dev = index(buffer, '\n')+1; - char *end_of_dev = index(start_of_dev, '\t'); - *end_of_dev='\0'; - dev = start_of_dev; - close(fd); - } - - char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", - "/sys/class/net/%s/statistics/rx_bytes", - "/sys/class/net/%s/statistics/tx_packets", - "/sys/class/net/%s/statistics/tx_bytes" - }; - - struct network_t *state = malloc(sizeof(struct network_t)); - - char buffer2[256]; - for(int i=0; i<NB_SENSOR; i++) { - sprintf(buffer2, filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); - } - *ptr = (void *) state; - _get_network(state->values, state->sources); - - return NB_SENSOR; -} - -unsigned int get_network(uint64_t *results, void *ptr) -{ - struct network_t *state = (struct network_t *) ptr; - _get_network(state->tmp_values, state->sources); - for(int i=0; i<NB_SENSOR; i++) - results[i] = state->tmp_values[i] - state->values[i]; - - memcpy(state->values, state->tmp_values, NB_SENSOR*sizeof(uint64_t)); - return NB_SENSOR; -} - -void clean_network(void *ptr) -{ - struct network_t *state = (struct network_t *) ptr; - if(state==NULL) - return; - for(int i=0; i<NB_SENSOR; i++) - close(state->sources[i]); - free(state); -} - -char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; -void label_network(char **labels, void *none) -{ - UNUSED(none); - for(int i=0; i<NB_SENSOR; i++) - labels[i] = _labels_network[i]; -} +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#define NB_SENSOR 4 +#define UNUSED(expr) do { (void)(expr); } while (0) + +static char *route = "/proc/net/route"; +struct network_t { + uint64_t values[NB_SENSOR]; + uint64_t tmp_values[NB_SENSOR]; + int sources[NB_SENSOR]; +}; + +unsigned int _get_network(uint64_t *results, int *sources) +{ + if(sources==NULL) + return 0; + char buffer[128]; + for(int i=0; i<NB_SENSOR; i++) { + if (pread(sources[i], buffer, 127, 0) < 0) { + perror("pread"); + exit(1); + } + + results[i] = strtoull(buffer, NULL, 10); + } + return NB_SENSOR; +} + + + +unsigned int init_network(char *dev, void **ptr) +{ + if(dev==NULL) + return 0; + + if(strcmp(dev,"X")==0) { + int fd = open(route, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s ", route); + perror("open"); + exit(1); + } + char buffer[1000]; + + if ( read(fd, buffer, 999) < 0 ) { + perror("read"); + close(fd); + exit(1); + } + + char *start_of_dev = index(buffer, '\n')+1; + char *end_of_dev = index(start_of_dev, '\t'); + *end_of_dev='\0'; + dev = start_of_dev; + close(fd); + } + + char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", + "/sys/class/net/%s/statistics/rx_bytes", + "/sys/class/net/%s/statistics/tx_packets", + "/sys/class/net/%s/statistics/tx_bytes" + }; + + struct network_t *state = malloc(sizeof(struct network_t)); + + char buffer2[256]; + for(int i=0; i<NB_SENSOR; i++) { + sprintf(buffer2, filenames[i], dev); + state->sources[i] = open(buffer2, O_RDONLY); + } + *ptr = (void *) state; + _get_network(state->values, state->sources); + + return NB_SENSOR; +} + +unsigned int get_network(uint64_t *results, void *ptr) +{ + struct network_t *state = (struct network_t *) ptr; + _get_network(state->tmp_values, state->sources); + for(int i=0; i<NB_SENSOR; i++) + results[i] = state->tmp_values[i] - state->values[i]; + + memcpy(state->values, state->tmp_values, NB_SENSOR*sizeof(uint64_t)); + return NB_SENSOR; +} + +void clean_network(void *ptr) +{ + struct network_t *state = (struct network_t *) ptr; + if(state==NULL) + return; + for(int i=0; i<NB_SENSOR; i++) + close(state->sources[i]); + free(state); +} + +char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; +void label_network(char **labels, void *none) +{ + UNUSED(none); + for(int i=0; i<NB_SENSOR; i++) + labels[i] = _labels_network[i]; +} diff --git a/src/network.h b/src/network.h index 3ba9ae5..b770560 100644 --- a/src/network.h +++ b/src/network.h @@ -1,25 +1,25 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_network(char *, void **); -unsigned int get_network(uint64_t *results, void *); -void clean_network(void *); -void label_network(char **labels, void *); - +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_network(char *, void **); +unsigned int get_network(uint64_t *results, void *); +void clean_network(void *); +void label_network(char **labels, void *); + diff --git a/src/rapl.c b/src/rapl.c index 30d38c1..eb4666a 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -1,174 +1,174 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <powercap/powercap-rapl.h> - -#define UNUSED(expr) do { (void)(expr); } while (0) - -struct _rapl_t { - powercap_rapl_pkg *pkgs; - uint32_t nb_pkgs; - uint32_t nb; - char **names; - uint32_t *zones; - uint32_t *packages; - uint64_t *values; - uint64_t *tmp_values; -}; - -typedef struct _rapl_t _rapl_t; - - - - - - -const int nb_zones = 3; -const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_CORE, POWERCAP_RAPL_ZONE_DRAM}; - - -#define MAX_LEN_NAME 100 - -// values [zone + package *nbzones] microjoules -void _get_rapl(uint64_t *values, _rapl_t *rapl) -{ - for (unsigned int i = 0; i < rapl->nb; i++) { -#ifdef DEBUG - int ret = -#endif - powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], - rapl->zones[i], - &values[i]); -#ifdef DEBUG - printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); -#endif - } -} - -unsigned int init_rapl(char *none, void **ptr) -{ - UNUSED(none); - // get number of processor sockets - _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); - rapl->nb = 0; - rapl->packages = NULL; - rapl->zones = NULL; - - rapl->nb_pkgs = powercap_rapl_get_num_instances(); - //rapl->nb_pkgs = powercap_rapl_get_num_packages(); - - if (rapl->nb_pkgs == 0) { - perror("no packages found (maybe the kernel module isn't loaded?)"); - exit(-1); - } - rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { - perror("powercap_rapl_init, check access (root needed ?)"); - exit(-1); - } - - rapl->names = NULL; - - char _name[MAX_LEN_NAME+1]; - char _name2[MAX_LEN_NAME+11]; - - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { - for(unsigned int zone=0; zone < nb_zones; zone++) { - int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], - _name, MAX_LEN_NAME); - if (length>0) { - - sprintf(_name2, "%s%u", _name, package); - - rapl->nb++; - rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); - rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); - rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); - - strcpy(rapl->names[rapl->nb-1], _name2); - rapl->zones[rapl->nb-1] = rapl_zones[zone]; - rapl->packages[rapl->nb-1] = package; - } -#ifdef DEBUG - printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); -#endif - } - } -#ifdef DEBUG - printf("Result of init\n"); - for(unsigned int i=0; i<rapl->nb; i++) - printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); -#endif - - rapl->values = calloc(sizeof(uint64_t), rapl->nb); - rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); - - _get_rapl(rapl->values, rapl); - - *ptr = (void *)rapl; - return rapl->nb; -} - - - -unsigned int get_rapl(uint64_t *results, void *ptr) -{ - _rapl_t *state = (_rapl_t *) ptr; - _get_rapl(state->tmp_values, state); - for(unsigned int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; - - memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); - return state->nb; -} - - - - -void clean_rapl(void *ptr) -{ - _rapl_t *rapl = (_rapl_t *) ptr; - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_destroy(&rapl->pkgs[package])) - perror("powercap_rapl_destroy"); - for (unsigned int elem=0; elem<rapl->nb; elem++) - free(rapl->names[elem]); - - free(rapl->names); - free(rapl->pkgs); - free(rapl->zones); - free(rapl->packages); - free(rapl->values); - free(rapl->tmp_values); - free(rapl); -} - -void label_rapl(char **labels, void *ptr) -{ - _rapl_t *rapl = (_rapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) - labels[i] = rapl->names[i]; -} +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <powercap/powercap-rapl.h> + +#define UNUSED(expr) do { (void)(expr); } while (0) + +struct _rapl_t { + powercap_rapl_pkg *pkgs; + uint32_t nb_pkgs; + uint32_t nb; + char **names; + uint32_t *zones; + uint32_t *packages; + uint64_t *values; + uint64_t *tmp_values; +}; + +typedef struct _rapl_t _rapl_t; + + + + + + +const int nb_zones = 3; +const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_CORE, POWERCAP_RAPL_ZONE_DRAM}; + + +#define MAX_LEN_NAME 100 + +// values [zone + package *nbzones] microjoules +void _get_rapl(uint64_t *values, _rapl_t *rapl) +{ + for (unsigned int i = 0; i < rapl->nb; i++) { +#ifdef DEBUG + int ret = +#endif + powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], + rapl->zones[i], + &values[i]); +#ifdef DEBUG + printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); +#endif + } +} + +unsigned int init_rapl(char *none, void **ptr) +{ + UNUSED(none); + // get number of processor sockets + _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); + rapl->nb = 0; + rapl->packages = NULL; + rapl->zones = NULL; + + rapl->nb_pkgs = powercap_rapl_get_num_instances(); + //rapl->nb_pkgs = powercap_rapl_get_num_packages(); + + if (rapl->nb_pkgs == 0) { + perror("no packages found (maybe the kernel module isn't loaded?)"); + exit(-1); + } + rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) + if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { + perror("powercap_rapl_init, check access (root needed ?)"); + exit(-1); + } + + rapl->names = NULL; + + char _name[MAX_LEN_NAME+1]; + char _name2[MAX_LEN_NAME+11]; + + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { + for(unsigned int zone=0; zone < nb_zones; zone++) { + int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], + _name, MAX_LEN_NAME); + if (length>0) { + + sprintf(_name2, "%s%u", _name, package); + + rapl->nb++; + rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); + rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); + rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); + rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); + + strcpy(rapl->names[rapl->nb-1], _name2); + rapl->zones[rapl->nb-1] = rapl_zones[zone]; + rapl->packages[rapl->nb-1] = package; + } +#ifdef DEBUG + printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); +#endif + } + } +#ifdef DEBUG + printf("Result of init\n"); + for(unsigned int i=0; i<rapl->nb; i++) + printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); +#endif + + rapl->values = calloc(sizeof(uint64_t), rapl->nb); + rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); + + _get_rapl(rapl->values, rapl); + + *ptr = (void *)rapl; + return rapl->nb; +} + + + +unsigned int get_rapl(uint64_t *results, void *ptr) +{ + _rapl_t *state = (_rapl_t *) ptr; + _get_rapl(state->tmp_values, state); + for(unsigned int i=0; i<state->nb; i++) + results[i] = state->tmp_values[i] - state->values[i]; + + memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); + return state->nb; +} + + + + +void clean_rapl(void *ptr) +{ + _rapl_t *rapl = (_rapl_t *) ptr; + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) + if (powercap_rapl_destroy(&rapl->pkgs[package])) + perror("powercap_rapl_destroy"); + for (unsigned int elem=0; elem<rapl->nb; elem++) + free(rapl->names[elem]); + + free(rapl->names); + free(rapl->pkgs); + free(rapl->zones); + free(rapl->packages); + free(rapl->values); + free(rapl->tmp_values); + free(rapl); +} + +void label_rapl(char **labels, void *ptr) +{ + _rapl_t *rapl = (_rapl_t *) ptr; + for(unsigned int i=0; i<rapl->nb; i++) + labels[i] = rapl->names[i]; +} diff --git a/src/rapl.h b/src/rapl.h index 74cc515..78006d3 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -1,25 +1,25 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_rapl(char *, void **); -unsigned int get_rapl(uint64_t *results, void *); -void clean_rapl(void *); -void label_rapl(char **labels, void *); - +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_rapl(char *, void **); +unsigned int get_rapl(uint64_t *results, void *); +void clean_rapl(void *); +void label_rapl(char **labels, void *); + diff --git a/src/temperature.c b/src/temperature.c index cdef158..7f673b4 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -1,155 +1,155 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <stdio.h> -#include <stdint.h> - -#define UNUSED(expr) do { (void)(expr); } while (0) - -struct temperature_t { - char **label_list; - int *fid_list; - int nb_elem; -}; - -int get_string(char *filename, char *buffer, int max_size) -{ - int fid = open(filename, O_RDONLY); - //printf("Tries to open : %s : %d\n", filename, fid); - if(fid == -1) - return -1; - - int nb = read(fid, buffer, max_size); - if(nb == -1) { - close(fid); - return -1; - } - - buffer[nb]=0; - close(fid); - return 0; -} - -void add_to_list(char ***list_name, char *source, int nb_elem) -{ - //printf("Adds: %s\n", source); - *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char *)); - (*list_name)[nb_elem] = malloc(strlen(source)+1); - strcpy((*list_name)[nb_elem], source); - -} - -void add_temperature_sensor(int id_rep, struct temperature_t *state) -{ - static int key=0; - static char buffer_filename[512]; - static char buffer_label[512]; - - int delta = sprintf(buffer_label, "Temp_%d_", key); - - for(int i=1;; i++) { - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); - if(get_string(buffer_filename, buffer_label+delta, 100) == -1) - break; - - for(unsigned int pos = 0; pos < strlen(buffer_label); pos++) { - if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; - if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; - } - add_to_list(&state->label_list, buffer_label, state->nb_elem); - - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); - state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); - int fd = open(buffer_filename, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "%s ", buffer_filename); - perror("open"); - exit(1); - } - state->fid_list[state->nb_elem] = fd; - state->nb_elem++; - // printf("%s : %s\n", buffer_label, buffer_filename); - } - - key++; -} - -unsigned int init_temperature(char *args, void **ptr) -{ - UNUSED(args); - struct temperature_t *state = malloc(sizeof(struct temperature_t)); - state->nb_elem = 0; - state->label_list = NULL; - state->fid_list = NULL; - - char base_name[] = "/sys/class/hwmon/hwmon%d/name"; - static char name[512]; - static char buffer[512]; - - int i = 0; - sprintf(name, base_name, i); - while(get_string(name, buffer, 8) != -1) { - if (strcmp(buffer, "coretemp")==0) - add_temperature_sensor(i, state); - - i++; - sprintf(name, base_name, i); - } - *ptr = (void *) state; - return state->nb_elem; -} - -unsigned int get_temperature(uint64_t *results, void *ptr) -{ - struct temperature_t *state = (struct temperature_t *)ptr; - static char buffer[512]; - for(int i=0; i<state->nb_elem; i++) { - if (pread(state->fid_list[i], buffer, 100, 0) < 0) { - perror("pread"); - exit(1); - } - results[i] = strtoull(buffer, NULL, 10); - } - return state->nb_elem; -} - -void clean_temperature(void *ptr) -{ - struct temperature_t *state = (struct temperature_t *)ptr; - - for(int i=0; i<state->nb_elem; i++) { - free(state->label_list[i]); - close(state->fid_list[i]); - } - free(state->label_list); - free(state->fid_list); - free(state); -} - -void label_temperature(char **labels, void *ptr) -{ - struct temperature_t *state = (struct temperature_t *)ptr; - for(int i=0; i<state->nb_elem; i++) - labels[i] = state->label_list[i]; -} +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> + +#define UNUSED(expr) do { (void)(expr); } while (0) + +struct temperature_t { + char **label_list; + int *fid_list; + int nb_elem; +}; + +int get_string(char *filename, char *buffer, int max_size) +{ + int fid = open(filename, O_RDONLY); + //printf("Tries to open : %s : %d\n", filename, fid); + if(fid == -1) + return -1; + + int nb = read(fid, buffer, max_size); + if(nb == -1) { + close(fid); + return -1; + } + + buffer[nb]=0; + close(fid); + return 0; +} + +void add_to_list(char ***list_name, char *source, int nb_elem) +{ + //printf("Adds: %s\n", source); + *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char *)); + (*list_name)[nb_elem] = malloc(strlen(source)+1); + strcpy((*list_name)[nb_elem], source); + +} + +void add_temperature_sensor(int id_rep, struct temperature_t *state) +{ + static int key=0; + static char buffer_filename[512]; + static char buffer_label[512]; + + int delta = sprintf(buffer_label, "Temp_%d_", key); + + for(int i=1;; i++) { + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); + if(get_string(buffer_filename, buffer_label+delta, 100) == -1) + break; + + for(unsigned int pos = 0; pos < strlen(buffer_label); pos++) { + if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; + if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; + } + add_to_list(&state->label_list, buffer_label, state->nb_elem); + + sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); + state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); + int fd = open(buffer_filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s ", buffer_filename); + perror("open"); + exit(1); + } + state->fid_list[state->nb_elem] = fd; + state->nb_elem++; + // printf("%s : %s\n", buffer_label, buffer_filename); + } + + key++; +} + +unsigned int init_temperature(char *args, void **ptr) +{ + UNUSED(args); + struct temperature_t *state = malloc(sizeof(struct temperature_t)); + state->nb_elem = 0; + state->label_list = NULL; + state->fid_list = NULL; + + char base_name[] = "/sys/class/hwmon/hwmon%d/name"; + static char name[512]; + static char buffer[512]; + + int i = 0; + sprintf(name, base_name, i); + while(get_string(name, buffer, 8) != -1) { + if (strcmp(buffer, "coretemp")==0) + add_temperature_sensor(i, state); + + i++; + sprintf(name, base_name, i); + } + *ptr = (void *) state; + return state->nb_elem; +} + +unsigned int get_temperature(uint64_t *results, void *ptr) +{ + struct temperature_t *state = (struct temperature_t *)ptr; + static char buffer[512]; + for(int i=0; i<state->nb_elem; i++) { + if (pread(state->fid_list[i], buffer, 100, 0) < 0) { + perror("pread"); + exit(1); + } + results[i] = strtoull(buffer, NULL, 10); + } + return state->nb_elem; +} + +void clean_temperature(void *ptr) +{ + struct temperature_t *state = (struct temperature_t *)ptr; + + for(int i=0; i<state->nb_elem; i++) { + free(state->label_list[i]); + close(state->fid_list[i]); + } + free(state->label_list); + free(state->fid_list); + free(state); +} + +void label_temperature(char **labels, void *ptr) +{ + struct temperature_t *state = (struct temperature_t *)ptr; + for(int i=0; i<state->nb_elem; i++) + labels[i] = state->label_list[i]; +} diff --git a/src/temperature.h b/src/temperature.h index e49e416..ac8e34b 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -1,24 +1,24 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_temperature(char *, void **); -unsigned int get_temperature(uint64_t *results, void *); -void clean_temperature(void *); -void label_temperature(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_temperature(char *, void **); +unsigned int get_temperature(uint64_t *results, void *); +void clean_temperature(void *); +void label_temperature(char **labels, void *); -- GitLab From 01973a528ebefac91d183adc2919fd865f5591e4 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 9 Jan 2023 16:39:09 +0100 Subject: [PATCH 020/125] add a dummy counter as an example --- doc/counter_ex.c | 23 +++++++++++++++++++++++ doc/counter_ex.h | 7 +++++++ 2 files changed, 30 insertions(+) create mode 100644 doc/counter_ex.c create mode 100644 doc/counter_ex.h diff --git a/doc/counter_ex.c b/doc/counter_ex.c new file mode 100644 index 0000000..3dda06d --- /dev/null +++ b/doc/counter_ex.c @@ -0,0 +1,23 @@ +#include "counter_ex.h" + +static int acc; + +unsigned int +init_acc(char *a, void **b) +{ + acc = 0; +} + +unsigned int +get_acc(uint64_t *results, void *none) +{ + UNUSED(none); + return a++; +} + +void +label_acc(char **labels, void *none) +{ + UNUSED(none); + labels[0] = "acc"; +} diff --git a/doc/counter_ex.h b/doc/counter_ex.h new file mode 100644 index 0000000..d85573b --- /dev/null +++ b/doc/counter_ex.h @@ -0,0 +1,7 @@ +/* + * Example of a basic counter: an accumulator +**/ + +unsigned int init_acc(char*, void**); +unsigned int get_acc(uint64_t *results, void*); +void label_counter(char **labels, void*); -- GitLab From ae671211dc1c30772861775cfb57d913e146757a Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 9 Jan 2023 16:48:16 +0100 Subject: [PATCH 021/125] add a man page --- README.md | 70 ++++++++++++++------------------- doc/mojitos.1 | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 40 deletions(-) create mode 100644 doc/mojitos.1 diff --git a/README.md b/README.md index 2cf04f1..a344fe0 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,19 @@ # MOJITO/S An Open Source System, Energy and Network Monitoring Tools at the O/S level - -## Documentation - MojitO/S runs on GNU/Linux -Usage -```python -Usage : ./mojitos [-t time] [-f freq] [-r] [-p perf_list] [-l] \ +## Usage + +```bash +Usage : mojitos [-Rsu] [-t time] [-f freq] [-p perf_list] \ [-u] [-d network_device] [-o logfile] [-e command arguments...] + mojitos [-l] ``` -Timing -- If time is 0 then mojitos loops infinitively -- If -e is present, time and freq are not used +For more information, see [mojitos(1)](doc/mojitos.1) under [doc/](doc). -Configuration -- -r activates RAPL (deprecated) -- -R activates RAPL -- -p activates performance counters. perf_list is coma separated list of performance counters without space. -- -l lists the possible performance counters and quits -- -d activates network monitoring -- -u activates system-level load monitoring -- -s activates statistics of overhead in nanoseconds +## License MojitO/S is published under the GPL3 license and is part of the [Energumen Project](https://www.irit.fr/energumen/) @@ -59,42 +49,42 @@ sudo chmod a+w /sys/class/powercap/intel-rapl/*/*/* RAPL values during 2 seconds with a frequency of 2 Hz ```bash $ ./mojitos -t 2 -f 2 -r -#timestamp package-00 core0 dram0 -1036389.135659868 10986 2869 1526 -1036389.500183551 1291440 255736 515562 -1036390.000754048 1333553 228393 689513 -1036390.500113978 1581967 267944 701536 +#timestamp package-00 core0 dram0 +1036389.135659868 10986 2869 1526 +1036389.500183551 1291440 255736 515562 +1036390.000754048 1333553 228393 689513 +1036390.500113978 1581967 267944 701536 ``` Performance counters (cpu_cycle, cache_ll_r_a and page_faults) during 4 seconds with a frequency of 1Hz. For cache performance counters, _r and _w are respectively read and write, and _a, _m and _p are respectively access, miss, pending. ```bash $ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults -#timestamp cpu_cycles cache_ll page_faults -1036846.351749455 571199 1232 0 -1036847.001098880 348173344 2451387 872 -1036848.000166158 388112961 2509305 791 -1036849.000191883 402255979 2625283 799 +#timestamp cpu_cycles cache_ll page_faults +1036846.351749455 571199 1232 0 +1036847.001098880 348173344 2451387 872 +1036848.000166158 388112961 2509305 791 +1036849.000191883 402255979 2625283 799 ``` Network values with no time limit with a frequency of 1Hz. rxp and txp are the number of received and sent packets, while rxb and txp are the number of received and sent bytes. ```bash $ ./mojitos -t 0 -f 1 -d enp0s25 -#timestamp rxp rxb txp txb -1036559.277376027 0 0 0 0 -1036560.000161101 4 581 2 179 -1036561.000083968 178 268675 55 4954 -1036562.000076162 11 1010 5 510 -1036563.000069724 17 1643 12 3602 -1036564.000113394 990 1493008 369 27299 +#timestamp rxp rxb txp txb +1036559.277376027 0 0 0 0 +1036560.000161101 4 581 2 179 +1036561.000083968 178 268675 55 4954 +1036562.000076162 11 1010 5 510 +1036563.000069724 17 1643 12 3602 +1036564.000113394 990 1493008 369 27299 ``` Overhead of the monitoring for RAPL and cpu_cycle ```bash $ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s -#timestamp cpu_cycles package-00 core0 dram0 overhead -1036988.197227391 162214 19898 4944 1586 149612 -1036989.000151326 332613664 2513116 379577 1115171 739573 -1036990.000116433 482150700 3321341 587218 1380673 315719 -1036991.000182835 525984292 3592582 691221 1385982 272182 -1036992.000165117 397678789 2770561 444030 1375729 510379 +#timestamp cpu_cycles package-00 core0 dram0 overhead +1036988.197227391 162214 19898 4944 1586 149612 +1036989.000151326 332613664 2513116 379577 1115171 739573 +1036990.000116433 482150700 3321341 587218 1380673 315719 +1036991.000182835 525984292 3592582 691221 1385982 272182 +1036992.000165117 397678789 2770561 444030 1375729 510379 ``` diff --git a/doc/mojitos.1 b/doc/mojitos.1 new file mode 100644 index 0000000..37e1876 --- /dev/null +++ b/doc/mojitos.1 @@ -0,0 +1,107 @@ +.Dd January 9, 2023 +.Dt MOJITOS 1 +.Os +.Sh NAME +.Nm mojitos +.Nd An open source system, energy and network monitoring tool. +.Sh SYNOPSIS +.Nm mojitos +.Op Fl rsu +.Op Fl t Ar time +.Op Fl f Ar freq +.Op Fl p Ar perf_list +.Op Fl d Ar net_device +.Op Fl o Ar logfile +.Op Fl e Ar cmd ... +.Nm mojitos +.Op Fl l +.Sh DESCRIPTION +.Nm +enables to monitor the system, its energy comsumption and the network activity, at the OS level. +It runs on GNU/Linux. +.Pp +.Nm +supports the following options: +.Bl -tag -width Ds +.It Fl s +Enable overhead statistics (in nanoseconds). +.It Fl u +Enable system-level load monitoring. +.It Fl r +Enable RAPL. +.It Fl p Ar perf_list +Enable performance counters. +The argument is a coma separated list of performance counters. +.It Fl d Ar net_device +Enable network monitoring. +.It Fl l +List the available performance counters and quit. +.It Fl t Ar time +Set duration value (in seconds). If 0, then loops indefinitely. +.It Fl f Ar freq +Set amount of measurements per second. +.It Fl e Ar cmd ... +Execute a command with optional arguments. +If this option is used, any usage of -t or -f is ignored. +.El +.Sh EXIT STATUS +.Ex +.Sh EXAMPLES +RAPL values during 2 seconds with a frequency of 2Hz: +.Bd -literal -offset indent +$ mojitos -t 2 -f 2 -r +#timestamp package-00 core0 dram0 +1036389.135659868 10986 2869 1526 +1036389.500183551 1291440 255736 515562 +1036390.000754048 1333553 228393 689513 +1036390.500113978 1581967 267944 701536 +.Ed +.Pp +Performance counters (cpu_cycle, cache_ll_r_a and page_faults) during 4 seconds +with a frequency of 1Hz. +In the context of cache performance counters (as with "cache_ll_r_a"), + _r and _w suffixes mean respectively read and write, +while the _a, _m and _p ones mean respectively access, miss and pending. +.Pp +.Bd -literal -offset indent +$ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults +#timestamp cpu_cycles cache_ll page_faults +1036846.351749455 571199 1232 0 +1036847.001098880 348173344 2451387 872 +1036848.000166158 388112961 2509305 791 +1036849.000191883 402255979 2625283 799 +.Ed +.Pp +Network values with no time limit with a frequency of 1Hz. +rxp and txp are the number of received and sent packets, while rxb and txp are +the number of received and sent bytes. +.Pp +.Bd -literal -offset indent +$ ./mojitos -t 0 -f 1 -d enp0s25 +#timestamp rxp rxb txp txb +1036559.277376027 0 0 0 0 +1036560.000161101 4 581 2 179 +1036561.000083968 178 268675 55 4954 +1036562.000076162 11 1010 5 510 +1036563.000069724 17 1643 12 3602 +1036564.000113394 990 1493008 369 27299 +.Ed +.Pp +overhead of the monitoring when using RAPL and the cpu_cycle performance counter: +.Pp +.Bd -literal -offset indent +$ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s +#timestamp cpu_cycles package-00 core0 dram0 overhead +1036988.197227391 162214 19898 4944 1586 149612 +1036989.000151326 332613664 2513116 379577 1115171 739573 +1036990.000116433 482150700 3321341 587218 1380673 315719 +1036991.000182835 525984292 3592582 691221 1385982 272182 +1036992.000165117 397678789 2770561 444030 1375729 510379 +.Ed +.Sh SEE ALSO +.Xr perf 1 , +.Xr lscpu 1 , +.Xr sysfs 5 , +.Xr proc 5 +.Sh BUGS +Yes. -- GitLab From 598d2f8e15d8b16bcf1e57efdef16933a793b783 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 9 Jan 2023 16:48:45 +0100 Subject: [PATCH 022/125] msc changes (mostly reformating) --- src/counters.c | 40 +++++++----- src/counters_group.c | 143 +++++++++++++++++++++++++++++++++++++++++++ src/frapl.c | 14 +++-- src/infiniband.c | 6 +- src/load.c | 16 ++--- src/mojitos.c | 10 +-- src/network.c | 32 ++++++---- src/rapl.c | 34 ++++++---- src/temperature.c | 20 +++--- 9 files changed, 249 insertions(+), 66 deletions(-) create mode 100644 src/counters_group.c diff --git a/src/counters.c b/src/counters.c index 5a24eed..244e60c 100644 --- a/src/counters.c +++ b/src/counters.c @@ -44,8 +44,10 @@ typedef struct _counter_t *counter_t; void show_all_counters() { - for(unsigned int i=0; i<nb_counter_option; i++) - printf("%s\n", perf_static_info[i].name); + for (unsigned int i = 0; i < nb_counter_option; i++) + { + printf("%s\n", perf_static_info[i].name); + } } void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) @@ -134,16 +136,20 @@ void clean_counters(void *ptr) void start_counters(counter_t counters) { - for(int counter=0; counter<counters->nbperf; counter++) - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); + for (int counter = 0; counter < counters->nbperf; counter++) + for (int core = 0; core < counters->nbcores; core++) + { + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); + } } void reset_counters(counter_t counters) { - for(int counter=0; counter<counters->nbperf; counter++) - for(int core=0; core<counters->nbcores; core++) - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); + for (int counter = 0; counter < counters->nbperf; counter++) + for (int core = 0; core < counters->nbcores; core++) + { + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); + } } void _get_counters(counter_t counters, uint64_t *values) @@ -170,7 +176,7 @@ void _get_counters(counter_t counters, uint64_t *values) unsigned int init_counters(char *args, void **state) { int nb_perf; - int *perf_indexes=NULL; + int *perf_indexes = NULL; perf_event_list(args, &nb_perf, &perf_indexes); @@ -182,8 +188,8 @@ unsigned int init_counters(char *args, void **state) free(perf_key); fd->perf_indexes = perf_indexes; - fd->counters_values = malloc(nb_perf*sizeof(uint64_t)); - fd->tmp_counters_values = malloc(nb_perf*sizeof(uint64_t)); + fd->counters_values = malloc(nb_perf * sizeof(uint64_t)); + fd->tmp_counters_values = malloc(nb_perf * sizeof(uint64_t)); start_counters(fd); _get_counters(fd, fd->counters_values); *state = (void *) fd; @@ -196,8 +202,10 @@ unsigned int get_counters(uint64_t *results, void *ptr) counter_t state = (counter_t) ptr; _get_counters(state, state->tmp_counters_values); - for(int i=0; i<state->nbperf; i++) - results[i] = state->tmp_counters_values[i] - state->counters_values[i]; + for (int i = 0; i < state->nbperf; i++) + { + results[i] = state->tmp_counters_values[i] - state->counters_values[i]; + } memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); return state->nbperf; @@ -206,7 +214,9 @@ unsigned int get_counters(uint64_t *results, void *ptr) void label_counters(char **labels, void *ptr) { counter_t state = (counter_t) ptr; - for(int i=0; i<state->nbperf; i++) - labels[i] = perf_static_info[state->perf_indexes[i]].name; + for (int i = 0; i < state->nbperf; i++) + { + labels[i] = perf_static_info[state->perf_indexes[i]].name; + } } diff --git a/src/counters_group.c b/src/counters_group.c new file mode 100644 index 0000000..8a4de79 --- /dev/null +++ b/src/counters_group.c @@ -0,0 +1,143 @@ +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <linux/perf_event.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdint.h> +#include <asm/unistd.h> + +#include "counters.h" + +struct _counter_t +{ + int nbcores; + int nbperf; + int *counters; +}; + +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) +{ + long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + if (res == -1) + { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } + return res; +} + +counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +{ + struct perf_event_attr pe; + struct _counter_t *counters = malloc(sizeof(struct _counter_t)); + + unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); + counters->nbcores = nbcores; + counters->nbperf = nb_perf; + memset(&pe, 0, sizeof(struct perf_event_attr)); + pe.size = sizeof(struct perf_event_attr); + pe.disabled = 1; + + pe.read_format = PERF_FORMAT_GROUP; + counters->counters = malloc((nbcores + 1) * sizeof(int)); + + for (int core = 0; core < nbcores; core++) + { + counters->counters[core] = -1; + for (int idperf = 0; idperf < nb_perf; idperf ++) + { + pe.type = types[idperf]; + pe.config = names[idperf]; + int res = perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); + if (counters->counters[core] == -1) + { + counters->counters[core] = res; + } + } + } + return counters; +} + +void clean_counters(counter_t counters) +{ + for (int core = 0; core < counters->nbcores; core++) + { + close(counters->counters[core]); + } + free(counters->counters); + free(counters); +} + +void start_counters(counter_t counters) +{ + for (int core = 0; core < counters->nbcores; core++) + { + ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); + } +} +void reset_counters(counter_t counters) +{ + for (int core = 0; core < counters->nbcores; core++) + { + ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); + } +} + +struct read_format +{ + uint64_t nr; + struct + { + uint64_t value; + } values[]; +}; + +void get_counters(counter_t counters, long long *values) +{ + int nb_perf = counters->nbperf; + size_t buffer_size = sizeof(uint64_t) * (1 + nb_perf); + struct read_format *buffer = NULL; + if (buffer == NULL) + { + buffer = malloc(buffer_size); + } + + memset(values, 0, nb_perf * sizeof(long long)); + + for (int core = 0; core < counters->nbcores; core++) + { + if (-1 == read(counters->counters[core], buffer, buffer_size)) + { + perror("PB Lecture resultat"); + exit(EXIT_FAILURE); + } + for (int idperf = 0; idperf <= nb_perf; idperf++) + { + values[idperf] += buffer->values[idperf].value; + } + } + reset_counters(counters); +} diff --git a/src/frapl.c b/src/frapl.c index 9874a12..ab17b14 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -40,7 +40,7 @@ char *get_frapl_string(const char *filename) char *result = malloc(MAX_HEADER); int nb = read(fd, result, MAX_HEADER); close(fd); - result[nb-1] = 0; + result[nb - 1] = 0; return (result); } @@ -49,7 +49,7 @@ void test_append(char *name, int i) //char last = name[strlen(name)-1]; //if (last>='0' && last <= '9') // return; - sprintf(name+strlen(name), "%d", i); + sprintf(name + strlen(name), "%d", i); } @@ -70,8 +70,8 @@ void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(strlen(name)+1); - strcpy(rapl->names[rapl->nb-1], name); + rapl->names[rapl->nb - 1] = malloc(strlen(name) + 1); + strcpy(rapl->names[rapl->nb - 1], name); //printf("%s\n", energy_uj); int fd = open(energy_uj, O_RDONLY); @@ -154,8 +154,10 @@ unsigned int get_frapl(uint64_t *results, void *ptr) { _frapl_t *state = (_frapl_t *) ptr; _get_frapl(state->tmp_values, state); - for(unsigned int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; + for (unsigned int i = 0; i < state->nb; i++) + { + results[i] = state->tmp_values[i] - state->values[i]; + } memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); return state->nb; diff --git a/src/infiniband.c b/src/infiniband.c index 6621759..44d0b9e 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -39,8 +39,10 @@ unsigned int _get_network(uint64_t *results, int *sources); unsigned int init_infiniband(char *infi_path, void **ptr) { - if(infi_path==NULL) - return 0; + if (infi_path == NULL) + { + return 0; + } if(strcmp(infi_path,"X")==0) { diff --git a/src/load.c b/src/load.c index 4f11346..c40819c 100644 --- a/src/load.c +++ b/src/load.c @@ -28,9 +28,9 @@ #define UNUSED(expr) do { (void)(expr); } while (0) char buffer[LOAD_BUFFER_SIZE]; -static int load_fid=-1; -static uint64_t load_values[10]= {0,0,0,0,0,0,0,0,0,0}; -static uint64_t tmp_load_values[10]= {0,0,0,0,0,0,0,0,0,0}; +static int load_fid = -1; +static uint64_t load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static uint64_t tmp_load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static char *stat = "/proc/stat"; void _get_load(uint64_t *results) @@ -68,8 +68,10 @@ unsigned int get_load(uint64_t *results, void *state) { UNUSED(state); _get_load(tmp_load_values); - for(int i=0; i<10; i++) - results[i] = tmp_load_values[i] - load_values[i]; + for (int i = 0; i < 10; i++) + { + results[i] = tmp_load_values[i] - load_values[i]; + } memcpy(load_values, tmp_load_values, sizeof(load_values)); return 10; @@ -81,8 +83,8 @@ void clean_load(void *state) close(load_fid); } -char *_labels[10] = {"user","nice","system","idle","iowait","irq", - "softirq","steal","guest","guest_nice" +char *_labels[10] = {"user", "nice", "system", "idle", "iowait", "irq", + "softirq", "steal", "guest", "guest_nice" }; void label_load(char **labels, void *none) { diff --git a/src/mojitos.c b/src/mojitos.c index 3569d1b..3d61aa7 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -19,19 +19,19 @@ *******************************************************/ -#include <stdlib.h> +#include <inttypes.h> +#include <signal.h> #include <stdio.h> +#include <stdlib.h> #include <time.h> -#include <signal.h> -#include <inttypes.h> #include <unistd.h> #include "counters.h" -#include "rapl.h" #include "frapl.h" -#include "network.h" #include "infiniband.h" #include "load.h" +#include "network.h" +#include "rapl.h" #include "temperature.h" #define UNUSED(expr) do { (void)(expr); } while (0) diff --git a/src/network.c b/src/network.c index 647b4b3..2cb95ba 100644 --- a/src/network.c +++ b/src/network.c @@ -36,8 +36,10 @@ struct network_t { unsigned int _get_network(uint64_t *results, int *sources) { - if(sources==NULL) - return 0; + if (sources == NULL) + { + return 0; + } char buffer[128]; for(int i=0; i<NB_SENSOR; i++) { if (pread(sources[i], buffer, 127, 0) < 0) { @@ -54,8 +56,10 @@ unsigned int _get_network(uint64_t *results, int *sources) unsigned int init_network(char *dev, void **ptr) { - if(dev==NULL) - return 0; + if (dev == NULL) + { + return 0; + } if(strcmp(dev,"X")==0) { int fd = open(route, O_RDONLY); @@ -102,20 +106,26 @@ unsigned int get_network(uint64_t *results, void *ptr) { struct network_t *state = (struct network_t *) ptr; _get_network(state->tmp_values, state->sources); - for(int i=0; i<NB_SENSOR; i++) - results[i] = state->tmp_values[i] - state->values[i]; + for (int i = 0; i < NB_SENSOR; i++) + { + results[i] = state->tmp_values[i] - state->values[i]; + } - memcpy(state->values, state->tmp_values, NB_SENSOR*sizeof(uint64_t)); + memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); return NB_SENSOR; } void clean_network(void *ptr) { struct network_t *state = (struct network_t *) ptr; - if(state==NULL) - return; - for(int i=0; i<NB_SENSOR; i++) - close(state->sources[i]); + if (state == NULL) + { + return; + } + for (int i = 0; i < NB_SENSOR; i++) + { + close(state->sources[i]); + } free(state); } diff --git a/src/rapl.c b/src/rapl.c index 30d38c1..103007a 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -70,7 +70,7 @@ unsigned int init_rapl(char *none, void **ptr) { UNUSED(none); // get number of processor sockets - _rapl_t *rapl= malloc(sizeof(struct _rapl_t)); + _rapl_t *rapl = malloc(sizeof(struct _rapl_t)); rapl->nb = 0; rapl->packages = NULL; rapl->zones = NULL; @@ -91,8 +91,8 @@ unsigned int init_rapl(char *none, void **ptr) rapl->names = NULL; - char _name[MAX_LEN_NAME+1]; - char _name2[MAX_LEN_NAME+11]; + char _name[MAX_LEN_NAME + 1]; + char _name2[MAX_LEN_NAME + 11]; for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { for(unsigned int zone=0; zone < nb_zones; zone++) { @@ -119,8 +119,10 @@ unsigned int init_rapl(char *none, void **ptr) } #ifdef DEBUG printf("Result of init\n"); - for(unsigned int i=0; i<rapl->nb; i++) - printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); + for (unsigned int i = 0; i < rapl->nb; i++) + { + printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); + } #endif rapl->values = calloc(sizeof(uint64_t), rapl->nb); @@ -138,8 +140,10 @@ unsigned int get_rapl(uint64_t *results, void *ptr) { _rapl_t *state = (_rapl_t *) ptr; _get_rapl(state->tmp_values, state); - for(unsigned int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; + for (unsigned int i = 0; i < state->nb; i++) + { + results[i] = state->tmp_values[i] - state->values[i]; + } memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); return state->nb; @@ -153,9 +157,13 @@ void clean_rapl(void *ptr) _rapl_t *rapl = (_rapl_t *) ptr; for (unsigned int package = 0; package < rapl->nb_pkgs; package++) if (powercap_rapl_destroy(&rapl->pkgs[package])) - perror("powercap_rapl_destroy"); - for (unsigned int elem=0; elem<rapl->nb; elem++) - free(rapl->names[elem]); + { + perror("powercap_rapl_destroy"); + } + for (unsigned int elem = 0; elem < rapl->nb; elem++) + { + free(rapl->names[elem]); + } free(rapl->names); free(rapl->pkgs); @@ -169,6 +177,8 @@ void clean_rapl(void *ptr) void label_rapl(char **labels, void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) - labels[i] = rapl->names[i]; + for (unsigned int i = 0; i < rapl->nb; i++) + { + labels[i] = rapl->names[i]; + } } diff --git a/src/temperature.c b/src/temperature.c index cdef158..6331d20 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -37,8 +37,10 @@ int get_string(char *filename, char *buffer, int max_size) { int fid = open(filename, O_RDONLY); //printf("Tries to open : %s : %d\n", filename, fid); - if(fid == -1) - return -1; + if (fid == -1) + { + return -1; + } int nb = read(fid, buffer, max_size); if(nb == -1) { @@ -46,7 +48,7 @@ int get_string(char *filename, char *buffer, int max_size) return -1; } - buffer[nb]=0; + buffer[nb] = 0; close(fid); return 0; } @@ -54,15 +56,15 @@ int get_string(char *filename, char *buffer, int max_size) void add_to_list(char ***list_name, char *source, int nb_elem) { //printf("Adds: %s\n", source); - *list_name = realloc(*list_name, (nb_elem+1)*sizeof(char *)); - (*list_name)[nb_elem] = malloc(strlen(source)+1); + *list_name = realloc(*list_name, (nb_elem + 1) * sizeof(char *)); + (*list_name)[nb_elem] = malloc(strlen(source) + 1); strcpy((*list_name)[nb_elem], source); } void add_temperature_sensor(int id_rep, struct temperature_t *state) { - static int key=0; + static int key = 0; static char buffer_filename[512]; static char buffer_label[512]; @@ -150,6 +152,8 @@ void clean_temperature(void *ptr) void label_temperature(char **labels, void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; - for(int i=0; i<state->nb_elem; i++) - labels[i] = state->label_list[i]; + for (int i = 0; i < state->nb_elem; i++) + { + labels[i] = state->label_list[i]; + } } -- GitLab From b369bde06c0d49538b72ef0cde1c8d320b1d24da Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 11:26:35 +0100 Subject: [PATCH 023/125] make the README file as complete as possible --- README.md | 37 ++++++++++++++++++++++++++++++------- doc/mojitos.1 | 5 ++++- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a344fe0..6422ce0 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,35 @@ MojitO/S runs on GNU/Linux ## Usage ```bash -Usage : mojitos [-Rsu] [-t time] [-f freq] [-p perf_list] \ - [-u] [-d network_device] [-o logfile] [-e command arguments...] +Usage : mojitos [-rsu] [-t time] [-f freq] [-p perf_list] \ + [-d network_device] [-o logfile] [-e command arguments...] mojitos [-l] -``` -For more information, see [mojitos(1)](doc/mojitos.1) under [doc/](doc). + -s Enable overhead statistics (in nanoseconds). -## License + -u Enable system-level load monitoring. -MojitO/S is published under the GPL3 license and is part of the [Energumen Project](https://www.irit.fr/energumen/) + -r Enable RAPL. -<img src="https://www.irit.fr/energumen/images/energumen.png" width="100"> + -p perf_list + Enable performance counters. The argument is a coma separated + list of performance counters. + + -d net_device + Enable network monitoring. + + -l List the available performance counters and quit. + + -t time + Set duration value (in seconds). If 0, then loops indefinitely. + + -f freq + Set amount of measurements per second. + + -e cmd ... + Execute a command with optional arguments. If this option is + used, any usage of -t or -f is ignored. +``` ## Installation Instructions @@ -88,3 +105,9 @@ $ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s 1036991.000182835 525984292 3592582 691221 1385982 272182 1036992.000165117 397678789 2770561 444030 1375729 510379 ``` + +## License + +MojitO/S is published under the GPL3 license and is part of the [Energumen Project](https://www.irit.fr/energumen/) + +<img src="https://www.irit.fr/energumen/images/energumen.png" width="100"> diff --git a/doc/mojitos.1 b/doc/mojitos.1 index 37e1876..a7927e8 100644 --- a/doc/mojitos.1 +++ b/doc/mojitos.1 @@ -17,7 +17,7 @@ .Op Fl l .Sh DESCRIPTION .Nm -enables to monitor the system, its energy comsumption and the network activity, at the OS level. +enables monitoring the system, its energy comsumption and the network activity, at the OS level. It runs on GNU/Linux. .Pp .Nm @@ -103,5 +103,8 @@ $ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s .Xr lscpu 1 , .Xr sysfs 5 , .Xr proc 5 +.Sh LICENSE +MojitO/S is published under the GPL3 license and is part of the +.Lk https://www.irit.fr/energumen/ [Energumen Project] .Sh BUGS Yes. -- GitLab From 3ac574c814e9eae8a76f9be2cb97f0e7beb3efdf Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 11:32:32 +0100 Subject: [PATCH 024/125] properly reformat using new style (kr) --- doc/counter_ex.c | 10 ++-- doc/counter_ex.h | 6 +- src/counters.c | 138 +++++++++++++++++++++++++------------------ src/counters_group.c | 119 +++++++++++++++++++------------------ src/frapl.c | 63 +++++++++++++------- src/infiniband.c | 26 ++++---- src/load.c | 51 ++++++++++------ src/mojitos.c | 39 +++++++----- src/network.c | 76 ++++++++++++++---------- src/rapl.c | 79 ++++++++++++++----------- src/temperature.c | 75 +++++++++++++++-------- 11 files changed, 405 insertions(+), 277 deletions(-) diff --git a/doc/counter_ex.c b/doc/counter_ex.c index 3dda06d..5067003 100644 --- a/doc/counter_ex.c +++ b/doc/counter_ex.c @@ -5,19 +5,19 @@ static int acc; unsigned int init_acc(char *a, void **b) { - acc = 0; + acc = 0; } unsigned int get_acc(uint64_t *results, void *none) { - UNUSED(none); - return a++; + UNUSED(none); + return a++; } void label_acc(char **labels, void *none) { - UNUSED(none); - labels[0] = "acc"; + UNUSED(none); + labels[0] = "acc"; } diff --git a/doc/counter_ex.h b/doc/counter_ex.h index d85573b..49e185c 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -2,6 +2,6 @@ * Example of a basic counter: an accumulator **/ -unsigned int init_acc(char*, void**); -unsigned int get_acc(uint64_t *results, void*); -void label_counter(char **labels, void*); +unsigned int init_acc(char *, void **); +unsigned int get_acc(uint64_t *results, void *); +void label_counter(char **labels, void *); diff --git a/src/counters.c b/src/counters.c index 244e60c..7441a07 100644 --- a/src/counters.c +++ b/src/counters.c @@ -42,59 +42,69 @@ typedef struct _counter_t *counter_t; #include "counters_option.h" -void show_all_counters() +void +show_all_counters() { - for (unsigned int i = 0; i < nb_counter_option; i++) - { - printf("%s\n", perf_static_info[i].name); - } + for (unsigned int i = 0; i < nb_counter_option; i++) { + printf("%s\n", perf_static_info[i].name); + } } -void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) +void +perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) { - *perf_type = malloc(nb*sizeof(__u32)); - *perf_key = malloc(nb*sizeof(__u64)); - for(int i=0; i<nb; i++) { + *perf_type = malloc(nb * sizeof(__u32)); + *perf_key = malloc(nb * sizeof(__u64)); + + for (int i = 0; i < nb; i++) { (*perf_key)[i] = perf_static_info[indexes[i]].perf_key; (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; } } -void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) +void +perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) { char *token; - *nb_perf=0; - *perf_indexes=NULL; - while((token=strtok(perf_string, ",")) != NULL) { + *nb_perf = 0; + *perf_indexes = NULL; + + while ((token = strtok(perf_string, ",")) != NULL) { perf_string = NULL; unsigned int i; - for(i=0; i<nb_counter_option; i++) { - if(strcmp(perf_static_info[i].name, token) == 0) { + + for (i = 0; i < nb_counter_option; i++) { + if (strcmp(perf_static_info[i].name, token) == 0) { (*nb_perf)++; - (*perf_indexes) = realloc(*perf_indexes, sizeof(int)*(*nb_perf)); - (*perf_indexes)[*nb_perf-1]=i; + (*perf_indexes) = realloc(*perf_indexes, sizeof(int) * (*nb_perf)); + (*perf_indexes)[*nb_perf - 1] = i; break; } } - if(i == nb_counter_option) { + + if (i == nb_counter_option) { fprintf(stderr, "Unknown performance counter: %s\n", token); exit(EXIT_FAILURE); } } } -static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) +static long +perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) { long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + if (res == -1) { perror("perf_event_open"); fprintf(stderr, "Error opening leader %llx\n", hw_event->config); exit(EXIT_FAILURE); } + return res; } -counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +counter_t +_init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { struct perf_event_attr pe; unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); @@ -104,28 +114,35 @@ counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *nam counter_t counters = malloc(sizeof(struct _counter_t)); counters->nbperf = nb_perf; - counters->nbcores=nbcores; - counters->counters=malloc(nb_perf*sizeof(int *)); - for (int i=0; i<nb_perf; i++) { + counters->nbcores = nbcores; + counters->counters = malloc(nb_perf * sizeof(int *)); + + for (int i = 0; i < nb_perf; i++) { pe.type = types[i]; pe.config = names[i]; - counters->counters[i] = malloc(nbcores*sizeof(int)); + counters->counters[i] = malloc(nbcores * sizeof(int)); - for (unsigned int core=0; core<nbcores; core++) { + for (unsigned int core = 0; core < nbcores; core++) { counters->counters[i][core] = perf_event_open(&pe, -1, core, -1, PERF_FLAG_FD_CLOEXEC); } } + return counters; } -void clean_counters(void *ptr) +void +clean_counters(void *ptr) { counter_t counters = (counter_t) ptr; - for(int counter=0; counter<counters->nbperf; counter++) { - for(int core=0; core<counters->nbcores; core++) + + for (int counter = 0; counter < counters->nbperf; counter++) { + for (int core = 0; core < counters->nbcores; core++) { close(counters->counters[counter][core]); + } + free(counters->counters[counter]); } + free(counters->counters); free(counters->counters_values); free(counters->tmp_counters_values); @@ -134,36 +151,41 @@ void clean_counters(void *ptr) free(counters); } -void start_counters(counter_t counters) +void +start_counters(counter_t counters) { - for (int counter = 0; counter < counters->nbperf; counter++) - for (int core = 0; core < counters->nbcores; core++) - { - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); - } + for (int counter = 0; counter < counters->nbperf; counter++) { + for (int core = 0; core < counters->nbcores; core++) { + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_ENABLE, 0); + } + } } -void reset_counters(counter_t counters) +void +reset_counters(counter_t counters) { - for (int counter = 0; counter < counters->nbperf; counter++) - for (int core = 0; core < counters->nbcores; core++) - { - ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); - } + for (int counter = 0; counter < counters->nbperf; counter++) { + for (int core = 0; core < counters->nbcores; core++) { + ioctl(counters->counters[counter][core], PERF_EVENT_IOC_RESET, 0); + } + } } -void _get_counters(counter_t counters, uint64_t *values) +void +_get_counters(counter_t counters, uint64_t *values) { - for(int i=0; i<counters->nbperf; i++) { - uint64_t accu=0; - uint64_t count=0; - for (int core=0; core<counters->nbcores; core++) { + for (int i = 0; i < counters->nbperf; i++) { + uint64_t accu = 0; + uint64_t count = 0; + + for (int core = 0; core < counters->nbcores; core++) { if (-1 == read(counters->counters[i][core], &count, sizeof(uint64_t))) { fprintf(stderr, "Cannot read result"); exit(EXIT_FAILURE); } accu += count; } + values[i] = accu; } } @@ -173,7 +195,8 @@ void _get_counters(counter_t counters, uint64_t *values) -unsigned int init_counters(char *args, void **state) +unsigned int +init_counters(char *args, void **state) { int nb_perf; int *perf_indexes = NULL; @@ -197,26 +220,27 @@ unsigned int init_counters(char *args, void **state) return nb_perf; } -unsigned int get_counters(uint64_t *results, void *ptr) +unsigned int +get_counters(uint64_t *results, void *ptr) { counter_t state = (counter_t) ptr; _get_counters(state, state->tmp_counters_values); - for (int i = 0; i < state->nbperf; i++) - { - results[i] = state->tmp_counters_values[i] - state->counters_values[i]; - } + + for (int i = 0; i < state->nbperf; i++) { + results[i] = state->tmp_counters_values[i] - state->counters_values[i]; + } memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); return state->nbperf; } -void label_counters(char **labels, void *ptr) +void +label_counters(char **labels, void *ptr) { counter_t state = (counter_t) ptr; - for (int i = 0; i < state->nbperf; i++) - { - labels[i] = perf_static_info[state->perf_indexes[i]].name; - } + for (int i = 0; i < state->nbperf; i++) { + labels[i] = perf_static_info[state->perf_indexes[i]].name; + } } diff --git a/src/counters_group.c b/src/counters_group.c index 8a4de79..aa441d5 100644 --- a/src/counters_group.c +++ b/src/counters_group.c @@ -29,27 +29,29 @@ #include "counters.h" -struct _counter_t -{ +struct _counter_t { int nbcores; int nbperf; int *counters; }; -static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) +static long +perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) { long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - if (res == -1) - { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } + + if (res == -1) { + perror("perf_event_open"); + fprintf(stderr, "Error opening leader %llx\n", hw_event->config); + exit(EXIT_FAILURE); + } + return res; } -counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +counter_t +init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { struct perf_event_attr pe; struct _counter_t *counters = malloc(sizeof(struct _counter_t)); @@ -64,80 +66,79 @@ counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *name pe.read_format = PERF_FORMAT_GROUP; counters->counters = malloc((nbcores + 1) * sizeof(int)); - for (int core = 0; core < nbcores; core++) - { - counters->counters[core] = -1; - for (int idperf = 0; idperf < nb_perf; idperf ++) - { - pe.type = types[idperf]; - pe.config = names[idperf]; - int res = perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); - if (counters->counters[core] == -1) - { - counters->counters[core] = res; - } - } + for (int core = 0; core < nbcores; core++) { + counters->counters[core] = -1; + + for (int idperf = 0; idperf < nb_perf; idperf ++) { + pe.type = types[idperf]; + pe.config = names[idperf]; + int res = perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); + + if (counters->counters[core] == -1) { + counters->counters[core] = res; + } } + } + return counters; } -void clean_counters(counter_t counters) +void +clean_counters(counter_t counters) { - for (int core = 0; core < counters->nbcores; core++) - { - close(counters->counters[core]); - } + for (int core = 0; core < counters->nbcores; core++) { + close(counters->counters[core]); + } + free(counters->counters); free(counters); } -void start_counters(counter_t counters) +void +start_counters(counter_t counters) { - for (int core = 0; core < counters->nbcores; core++) - { - ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); - } + for (int core = 0; core < counters->nbcores; core++) { + ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); + } } -void reset_counters(counter_t counters) +void +reset_counters(counter_t counters) { - for (int core = 0; core < counters->nbcores; core++) - { - ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); - } + for (int core = 0; core < counters->nbcores; core++) { + ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); + } } -struct read_format -{ +struct read_format { uint64_t nr; - struct - { + struct { uint64_t value; } values[]; }; -void get_counters(counter_t counters, long long *values) +void +get_counters(counter_t counters, long long *values) { int nb_perf = counters->nbperf; size_t buffer_size = sizeof(uint64_t) * (1 + nb_perf); struct read_format *buffer = NULL; - if (buffer == NULL) - { - buffer = malloc(buffer_size); - } + + if (buffer == NULL) { + buffer = malloc(buffer_size); + } memset(values, 0, nb_perf * sizeof(long long)); - for (int core = 0; core < counters->nbcores; core++) - { - if (-1 == read(counters->counters[core], buffer, buffer_size)) - { - perror("PB Lecture resultat"); - exit(EXIT_FAILURE); - } - for (int idperf = 0; idperf <= nb_perf; idperf++) - { - values[idperf] += buffer->values[idperf].value; - } + for (int core = 0; core < counters->nbcores; core++) { + if (-1 == read(counters->counters[core], buffer, buffer_size)) { + perror("PB Lecture resultat"); + exit(EXIT_FAILURE); + } + + for (int idperf = 0; idperf <= nb_perf; idperf++) { + values[idperf] += buffer->values[idperf].value; } + } + reset_counters(counters); } diff --git a/src/frapl.c b/src/frapl.c index ab17b14..42842cf 100644 --- a/src/frapl.c +++ b/src/frapl.c @@ -31,12 +31,14 @@ #define UNUSED(expr) do { (void)(expr); } while (0) -char *get_frapl_string(const char *filename) +char * +get_frapl_string(const char *filename) { int fd = open(filename, O_RDONLY); - if( fd == -1) { + if (fd == -1) { return NULL; } + char *result = malloc(MAX_HEADER); int nb = read(fd, result, MAX_HEADER); close(fd); @@ -44,7 +46,8 @@ char *get_frapl_string(const char *filename) return (result); } -void test_append(char *name, int i) +void +test_append(char *name, int i) { //char last = name[strlen(name)-1]; //if (last>='0' && last <= '9') @@ -64,7 +67,8 @@ struct _frapl_t { typedef struct _frapl_t _frapl_t; -void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) +void +add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) { rapl->nb += 1; rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); @@ -81,11 +85,13 @@ void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) perror("open"); exit(1); } - rapl->fids[rapl->nb-1] = fd; + + rapl->fids[rapl->nb - 1] = fd; } -void _get_frapl(uint64_t *values, _frapl_t *rapl) +void +_get_frapl(uint64_t *values, _frapl_t *rapl) { static char buffer[512]; @@ -95,12 +101,14 @@ void _get_frapl(uint64_t *values, _frapl_t *rapl) perror("pread"); exit(1); } + values[i] = strtoull(buffer, NULL, 10); } } -unsigned int init_frapl(char *none, void **ptr) +unsigned int +init_frapl(char *none, void **ptr) { UNUSED(none); _frapl_t *rapl = malloc(sizeof(_frapl_t)); @@ -112,10 +120,14 @@ unsigned int init_frapl(char *none, void **ptr) char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - for (unsigned int i=0;; i++) { + for (unsigned int i = 0;; i++) { sprintf(buffer, name_base, i, "name"); char *tmp = get_frapl_string(buffer); - if (tmp == NULL) break; + + if (tmp == NULL) { + break; + } + //printf("%s\n", tmp); test_append(tmp, i); //printf("%s -> %s\n", buffer, tmp); @@ -124,10 +136,14 @@ unsigned int init_frapl(char *none, void **ptr) add_frapl_source(rapl, tmp, buffer); free(tmp); - for (unsigned int j=0;; j++) { + for (unsigned int j = 0;; j++) { sprintf(buffer, name_sub, i, i, j, "name"); char *tmp_sub = get_frapl_string(buffer); - if (tmp_sub == NULL) break; + + if (tmp_sub == NULL) { + break; + } + //printf("%s\n", tmp_sub); test_append(tmp_sub, i); //printf("%s -> %s\n", buffer, tmp_sub); @@ -150,26 +166,30 @@ unsigned int init_frapl(char *none, void **ptr) } -unsigned int get_frapl(uint64_t *results, void *ptr) +unsigned int +get_frapl(uint64_t *results, void *ptr) { _frapl_t *state = (_frapl_t *) ptr; _get_frapl(state->tmp_values, state); - for (unsigned int i = 0; i < state->nb; i++) - { - results[i] = state->tmp_values[i] - state->values[i]; - } + + for (unsigned int i = 0; i < state->nb; i++) { + results[i] = state->tmp_values[i] - state->values[i]; + } memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); return state->nb; } -void clean_frapl(void *ptr) +void +clean_frapl(void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) { + + for (unsigned int i = 0; i < rapl->nb; i++) { free(rapl->names[i]); close(rapl->fids[i]); } + free(rapl->names); free(rapl->fids); free(rapl->values); @@ -178,9 +198,12 @@ void clean_frapl(void *ptr) } -void label_frapl(char **labels, void *ptr) +void +label_frapl(char **labels, void *ptr) { _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) + + for (unsigned int i = 0; i < rapl->nb; i++) { labels[i] = rapl->names[i]; + } } diff --git a/src/infiniband.c b/src/infiniband.c index 44d0b9e..d5da4eb 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -37,20 +37,23 @@ struct network_t { unsigned int _get_network(uint64_t *results, int *sources); -unsigned int init_infiniband(char *infi_path, void **ptr) +unsigned int +init_infiniband(char *infi_path, void **ptr) { - if (infi_path == NULL) - { - return 0; - } + if (infi_path == NULL) { + return 0; + } - if(strcmp(infi_path,"X")==0) { + if (strcmp(infi_path, "X") == 0) { glob_t res; glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); - if(res.gl_pathc == 0) + + if (res.gl_pathc == 0) { return 0; + } + infi_path = res.gl_pathv[0]; } @@ -63,7 +66,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) struct network_t *state = malloc(sizeof(struct network_t)); char buffer[1024]; - for(int i=0; i<NB_SENSOR; i++) { + for (int i = 0; i < NB_SENSOR; i++) { sprintf(buffer, filenames[i], infi_path); state->sources[i] = open(buffer, O_RDONLY); } @@ -75,9 +78,12 @@ unsigned int init_infiniband(char *infi_path, void **ptr) } char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; -void label_infiniband(char **labels, void *none) +void +label_infiniband(char **labels, void *none) { UNUSED(none); - for(int i=0; i<NB_SENSOR; i++) + + for (int i = 0; i < NB_SENSOR; i++) { labels[i] = _labels_infiniband[i]; + } } diff --git a/src/load.c b/src/load.c index c40819c..c0013ab 100644 --- a/src/load.c +++ b/src/load.c @@ -33,51 +33,65 @@ static uint64_t load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static uint64_t tmp_load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static char *stat = "/proc/stat"; -void _get_load(uint64_t *results) +void +_get_load(uint64_t *results) { - if (pread(load_fid, buffer, LOAD_BUFFER_SIZE-1, 0) < 0) { + if (pread(load_fid, buffer, LOAD_BUFFER_SIZE - 1, 0) < 0) { perror("pread"); exit(1); } - int pos=0; - while(buffer[pos] > '9' || buffer[pos] < '0') pos++; - for(int i=0; i<10; i++) { - results[i] = strtoull(buffer+pos, NULL, 10); - while(buffer[pos] <= '9' && buffer[pos] >= '0') pos++; + + int pos = 0; + + while (buffer[pos] > '9' || buffer[pos] < '0') { + pos++; + } + + for (int i = 0; i < 10; i++) { + results[i] = strtoull(buffer + pos, NULL, 10); + + while (buffer[pos] <= '9' && buffer[pos] >= '0') { + pos++; + } + pos++; } } // Public interface -unsigned int init_load(char *argument, void **state) +unsigned int +init_load(char *argument, void **state) { UNUSED(argument); UNUSED(state); load_fid = open(stat, O_RDONLY); if (load_fid < 0) { - fprintf(stderr,"%s ",stat); + fprintf(stderr, "%s ", stat); perror("open"); exit(1); } + _get_load(load_values); return 10; } -unsigned int get_load(uint64_t *results, void *state) +unsigned int +get_load(uint64_t *results, void *state) { UNUSED(state); _get_load(tmp_load_values); - for (int i = 0; i < 10; i++) - { - results[i] = tmp_load_values[i] - load_values[i]; - } + + for (int i = 0; i < 10; i++) { + results[i] = tmp_load_values[i] - load_values[i]; + } memcpy(load_values, tmp_load_values, sizeof(load_values)); return 10; } -void clean_load(void *state) +void +clean_load(void *state) { UNUSED(state); close(load_fid); @@ -86,9 +100,12 @@ void clean_load(void *state) char *_labels[10] = {"user", "nice", "system", "idle", "iowait", "irq", "softirq", "steal", "guest", "guest_nice" }; -void label_load(char **labels, void *none) +void +label_load(char **labels, void *none) { UNUSED(none); - for(int i=0; i<10; i++) + + for (int i = 0; i < 10; i++) { labels[i] = _labels[i]; + } } diff --git a/src/mojitos.c b/src/mojitos.c index 3d61aa7..c0a5655 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -44,7 +44,8 @@ } while (0) -void usage(char **argv) +void +usage(char **argv) { printf("Usage : %s [-rRluc] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" @@ -64,19 +65,22 @@ void usage(char **argv) exit(EXIT_SUCCESS); } -void sighandler(int none) +void +sighandler(int none) { UNUSED(none); } -void flush(int none) +void +flush(int none) { UNUSED(none); exit(0); } FILE *output; -void flushexit() +void +flushexit() { if (output != NULL) { fflush(output); @@ -98,12 +102,14 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void add_source(initializer_t init, char *arg, labeler_t labeler, - getter_t get, cleaner_t clean) +void +add_source(initializer_t init, char *arg, labeler_t labeler, + getter_t get, cleaner_t clean) { nb_sources++; states = realloc(states, nb_sources * sizeof(void *)); int nb = init(arg, &states[nb_sources - 1]); + if (nb == 0) { nb_sources--; states = realloc(states, nb_sources * sizeof(void *)); @@ -122,7 +128,8 @@ void add_source(initializer_t init, char *arg, labeler_t labeler, nb_sensors += nb; } -int main(int argc, char **argv) +int +main(int argc, char **argv) { int total_time = 1; int delta = 0; @@ -141,7 +148,8 @@ int main(int argc, char **argv) signal(15, flush); int c; - while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) + + while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) { switch (c) { case 'f': if (optind >= argc) PANIC(1,"-f, no frequency provided"); @@ -198,7 +206,7 @@ int main(int argc, char **argv) default: usage(argv); } - + } setvbuf(output, NULL, _IONBF, BUFSIZ); struct timespec ts; @@ -223,6 +231,7 @@ int main(int argc, char **argv) // Get Data unsigned int current = 0; + for (unsigned int i = 0; i < nb_sources; i++) { current += getter[i](&values[current], states[i]); } @@ -233,12 +242,14 @@ int main(int argc, char **argv) execvp(application[0], application); exit(0); } + pause(); clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) { fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec), ts.tv_nsec - ts_ref.tv_nsec); } else { - fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000000000 + ts.tv_nsec - ts_ref.tv_nsec); + fprintf(output, "%ld.%09ld ", (ts.tv_sec - ts_ref.tv_sec) - 1, 1000 * 1000 * 1000 + ts.tv_nsec - ts_ref.tv_nsec); } } else { #ifdef DEBUG @@ -247,12 +258,14 @@ int main(int argc, char **argv) //Indiv: mean: 148 std: 31 % med: 141 std: 28 % //Group: mean: 309 std: 41 % med: 297 std: 39 % #endif + if (stat_mode == 0) { clock_gettime(CLOCK_MONOTONIC, &ts); + if (ts.tv_nsec >= ts_ref.tv_nsec) { stat_data = ts.tv_nsec - ts_ref.tv_nsec; } else { - stat_data = 1000000000 + ts.tv_nsec - ts_ref.tv_nsec; + stat_data = 1000 * 1000 * 1000 + ts.tv_nsec - ts_ref.tv_nsec; } } @@ -261,6 +274,7 @@ int main(int argc, char **argv) } for (unsigned int i = 0; i < nb_sensors; i++) { + /* "PRIu64" is a format specifier to print uint64_t values */ fprintf(output, "%" PRIu64 " ", values[i]); } @@ -291,6 +305,3 @@ int main(int argc, char **argv) } } - - - diff --git a/src/network.c b/src/network.c index 2cb95ba..5b94151 100644 --- a/src/network.c +++ b/src/network.c @@ -34,14 +34,16 @@ struct network_t { int sources[NB_SENSOR]; }; -unsigned int _get_network(uint64_t *results, int *sources) +unsigned int +_get_network(uint64_t *results, int *sources) { - if (sources == NULL) - { - return 0; - } + if (sources == NULL) { + return 0; + } + char buffer[128]; - for(int i=0; i<NB_SENSOR; i++) { + + for (int i = 0; i < NB_SENSOR; i++) { if (pread(sources[i], buffer, 127, 0) < 0) { perror("pread"); exit(1); @@ -49,36 +51,39 @@ unsigned int _get_network(uint64_t *results, int *sources) results[i] = strtoull(buffer, NULL, 10); } + return NB_SENSOR; } -unsigned int init_network(char *dev, void **ptr) +unsigned int +init_network(char *dev, void **ptr) { - if (dev == NULL) - { - return 0; - } + if (dev == NULL) { + return 0; + } - if(strcmp(dev,"X")==0) { + if (strcmp(dev, "X") == 0) { int fd = open(route, O_RDONLY); + if (fd < 0) { fprintf(stderr, "%s ", route); perror("open"); exit(1); } + char buffer[1000]; - if ( read(fd, buffer, 999) < 0 ) { + if (read(fd, buffer, 999) < 0 ) { perror("read"); close(fd); exit(1); } - char *start_of_dev = index(buffer, '\n')+1; + char *start_of_dev = index(buffer, '\n') + 1; char *end_of_dev = index(start_of_dev, '\t'); - *end_of_dev='\0'; + *end_of_dev = '\0'; dev = start_of_dev; close(fd); } @@ -92,47 +97,54 @@ unsigned int init_network(char *dev, void **ptr) struct network_t *state = malloc(sizeof(struct network_t)); char buffer2[256]; - for(int i=0; i<NB_SENSOR; i++) { + for (int i = 0; i < NB_SENSOR; i++) { sprintf(buffer2, filenames[i], dev); state->sources[i] = open(buffer2, O_RDONLY); } + *ptr = (void *) state; _get_network(state->values, state->sources); return NB_SENSOR; } -unsigned int get_network(uint64_t *results, void *ptr) +unsigned int +get_network(uint64_t *results, void *ptr) { struct network_t *state = (struct network_t *) ptr; _get_network(state->tmp_values, state->sources); - for (int i = 0; i < NB_SENSOR; i++) - { - results[i] = state->tmp_values[i] - state->values[i]; - } + + for (int i = 0; i < NB_SENSOR; i++) { + results[i] = state->tmp_values[i] - state->values[i]; + } memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); return NB_SENSOR; } -void clean_network(void *ptr) +void +clean_network(void *ptr) { struct network_t *state = (struct network_t *) ptr; - if (state == NULL) - { - return; - } - for (int i = 0; i < NB_SENSOR; i++) - { - close(state->sources[i]); - } + + if (state == NULL) { + return; + } + + for (int i = 0; i < NB_SENSOR; i++) { + close(state->sources[i]); + } + free(state); } char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; -void label_network(char **labels, void *none) +void +label_network(char **labels, void *none) { UNUSED(none); - for(int i=0; i<NB_SENSOR; i++) + + for (int i = 0; i < NB_SENSOR; i++) { labels[i] = _labels_network[i]; + } } diff --git a/src/rapl.c b/src/rapl.c index 103007a..0119a4f 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -51,7 +51,8 @@ const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_COR #define MAX_LEN_NAME 100 // values [zone + package *nbzones] microjoules -void _get_rapl(uint64_t *values, _rapl_t *rapl) +void +_get_rapl(uint64_t *values, _rapl_t *rapl) { for (unsigned int i = 0; i < rapl->nb; i++) { #ifdef DEBUG @@ -66,7 +67,8 @@ void _get_rapl(uint64_t *values, _rapl_t *rapl) } } -unsigned int init_rapl(char *none, void **ptr) +unsigned int +init_rapl(char *none, void **ptr) { UNUSED(none); // get number of processor sockets @@ -82,7 +84,9 @@ unsigned int init_rapl(char *none, void **ptr) perror("no packages found (maybe the kernel module isn't loaded?)"); exit(-1); } + rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { perror("powercap_rapl_init, check access (root needed ?)"); @@ -95,34 +99,38 @@ unsigned int init_rapl(char *none, void **ptr) char _name2[MAX_LEN_NAME + 11]; for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { - for(unsigned int zone=0; zone < nb_zones; zone++) { - int length=powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], - _name, MAX_LEN_NAME); - if (length>0) { + for (unsigned int zone = 0; zone < nb_zones; zone++) { + int length = powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], + _name, MAX_LEN_NAME); + + if (length > 0) { sprintf(_name2, "%s%u", _name, package); rapl->nb++; rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); - rapl->names[rapl->nb-1] = malloc(sizeof(char) * (strlen(_name2)+1)); - rapl->zones = realloc(rapl->zones, sizeof(uint32_t)*rapl->nb); - rapl->packages = realloc(rapl->packages, sizeof(uint32_t)*rapl->nb); + rapl->names[rapl->nb - 1] = malloc(sizeof(char) * (strlen(_name2) + 1)); + rapl->zones = realloc(rapl->zones, sizeof(uint32_t) * rapl->nb); + rapl->packages = realloc(rapl->packages, sizeof(uint32_t) * rapl->nb); - strcpy(rapl->names[rapl->nb-1], _name2); - rapl->zones[rapl->nb-1] = rapl_zones[zone]; - rapl->packages[rapl->nb-1] = package; + strcpy(rapl->names[rapl->nb - 1], _name2); + rapl->zones[rapl->nb - 1] = rapl_zones[zone]; + rapl->packages[rapl->nb - 1] = package; } + #ifdef DEBUG printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); #endif } } + #ifdef DEBUG printf("Result of init\n"); - for (unsigned int i = 0; i < rapl->nb; i++) - { - printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); - } + + for (unsigned int i = 0; i < rapl->nb; i++) { + printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); + } + #endif rapl->values = calloc(sizeof(uint64_t), rapl->nb); @@ -136,14 +144,15 @@ unsigned int init_rapl(char *none, void **ptr) -unsigned int get_rapl(uint64_t *results, void *ptr) +unsigned int +get_rapl(uint64_t *results, void *ptr) { _rapl_t *state = (_rapl_t *) ptr; _get_rapl(state->tmp_values, state); - for (unsigned int i = 0; i < state->nb; i++) - { - results[i] = state->tmp_values[i] - state->values[i]; - } + + for (unsigned int i = 0; i < state->nb; i++) { + results[i] = state->tmp_values[i] - state->values[i]; + } memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); return state->nb; @@ -152,19 +161,20 @@ unsigned int get_rapl(uint64_t *results, void *ptr) -void clean_rapl(void *ptr) +void +clean_rapl(void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; + for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_destroy(&rapl->pkgs[package])) - { - perror("powercap_rapl_destroy"); - } - for (unsigned int elem = 0; elem < rapl->nb; elem++) - { - free(rapl->names[elem]); + if (powercap_rapl_destroy(&rapl->pkgs[package])) { + perror("powercap_rapl_destroy"); } + for (unsigned int elem = 0; elem < rapl->nb; elem++) { + free(rapl->names[elem]); + } + free(rapl->names); free(rapl->pkgs); free(rapl->zones); @@ -174,11 +184,12 @@ void clean_rapl(void *ptr) free(rapl); } -void label_rapl(char **labels, void *ptr) +void +label_rapl(char **labels, void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; i++) - { - labels[i] = rapl->names[i]; - } + + for (unsigned int i = 0; i < rapl->nb; i++) { + labels[i] = rapl->names[i]; + } } diff --git a/src/temperature.c b/src/temperature.c index 6331d20..d0d1e9e 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -33,17 +33,18 @@ struct temperature_t { int nb_elem; }; -int get_string(char *filename, char *buffer, int max_size) +int +get_string(char *filename, char *buffer, int max_size) { int fid = open(filename, O_RDONLY); + //printf("Tries to open : %s : %d\n", filename, fid); - if (fid == -1) - { - return -1; - } + if (fid == -1) { + return -1; + } int nb = read(fid, buffer, max_size); - if(nb == -1) { + if (nb == -1) { close(fid); return -1; } @@ -53,7 +54,8 @@ int get_string(char *filename, char *buffer, int max_size) return 0; } -void add_to_list(char ***list_name, char *source, int nb_elem) +void +add_to_list(char ***list_name, char *source, int nb_elem) { //printf("Adds: %s\n", source); *list_name = realloc(*list_name, (nb_elem + 1) * sizeof(char *)); @@ -62,7 +64,8 @@ void add_to_list(char ***list_name, char *source, int nb_elem) } -void add_temperature_sensor(int id_rep, struct temperature_t *state) +void +add_temperature_sensor(int id_rep, struct temperature_t *state) { static int key = 0; static char buffer_filename[512]; @@ -70,25 +73,35 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) int delta = sprintf(buffer_label, "Temp_%d_", key); - for(int i=1;; i++) { + for (int i = 1;; i++) { sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); - if(get_string(buffer_filename, buffer_label+delta, 100) == -1) + + if (get_string(buffer_filename, buffer_label + delta, 100) == -1) { break; + } + + for (unsigned int pos = 0; pos < strlen(buffer_label); pos++) { + if (buffer_label[pos] == ' ') { + buffer_label[pos] = '_'; + } - for(unsigned int pos = 0; pos < strlen(buffer_label); pos++) { - if (buffer_label[pos] == ' ') buffer_label[pos] = '_'; - if (buffer_label[pos] == '\n') buffer_label[pos] = '\0'; + if (buffer_label[pos] == '\n') { + buffer_label[pos] = '\0'; + } } + add_to_list(&state->label_list, buffer_label, state->nb_elem); sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); - state->fid_list = realloc(state->fid_list, (state->nb_elem+1)*sizeof(int)); + state->fid_list = realloc(state->fid_list, (state->nb_elem + 1) * sizeof(int)); int fd = open(buffer_filename, O_RDONLY); + if (fd < 0) { fprintf(stderr, "%s ", buffer_filename); perror("open"); exit(1); } + state->fid_list[state->nb_elem] = fd; state->nb_elem++; // printf("%s : %s\n", buffer_label, buffer_filename); @@ -97,7 +110,8 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) key++; } -unsigned int init_temperature(char *args, void **ptr) +unsigned int +init_temperature(char *args, void **ptr) { UNUSED(args); struct temperature_t *state = malloc(sizeof(struct temperature_t)); @@ -111,49 +125,58 @@ unsigned int init_temperature(char *args, void **ptr) int i = 0; sprintf(name, base_name, i); - while(get_string(name, buffer, 8) != -1) { - if (strcmp(buffer, "coretemp")==0) + + while (get_string(name, buffer, 8) != -1) { + if (strcmp(buffer, "coretemp") == 0) { add_temperature_sensor(i, state); + } i++; sprintf(name, base_name, i); } + *ptr = (void *) state; return state->nb_elem; } -unsigned int get_temperature(uint64_t *results, void *ptr) +unsigned int +get_temperature(uint64_t *results, void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; static char buffer[512]; - for(int i=0; i<state->nb_elem; i++) { + + for (int i = 0; i < state->nb_elem; i++) { if (pread(state->fid_list[i], buffer, 100, 0) < 0) { perror("pread"); exit(1); } results[i] = strtoull(buffer, NULL, 10); } + return state->nb_elem; } -void clean_temperature(void *ptr) +void +clean_temperature(void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; - for(int i=0; i<state->nb_elem; i++) { + for (int i = 0; i < state->nb_elem; i++) { free(state->label_list[i]); close(state->fid_list[i]); } + free(state->label_list); free(state->fid_list); free(state); } -void label_temperature(char **labels, void *ptr) +void +label_temperature(char **labels, void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; - for (int i = 0; i < state->nb_elem; i++) - { - labels[i] = state->label_list[i]; - } + + for (int i = 0; i < state->nb_elem; i++) { + labels[i] = state->label_list[i]; + } } -- GitLab From 3d630bac4cd8f5e532cd20b30cdcc89b8b908a1a Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 14:29:19 +0100 Subject: [PATCH 025/125] remove deprecated "rapl" counter and replace it with frapl - rename "frapl" to "rapl" - remove no longer used "-R" option --- makefile | 2 +- src/frapl.c | 209 -------------------------------------------------- src/frapl.h | 25 ------ src/mojitos.c | 6 +- src/rapl.c | 178 ++++++++++++++++++++++-------------------- src/rapl.h | 2 +- 6 files changed, 99 insertions(+), 323 deletions(-) delete mode 100644 src/frapl.c delete mode 100644 src/frapl.h diff --git a/makefile b/makefile index ab8c2dc..5198055 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ SRC_DIR = src OBJ_DIR = obj BIN_DIR = bin -OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o frapl.o network.o load.o infiniband.o temperature.o) +OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o infiniband.o temperature.o) OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc diff --git a/src/frapl.c b/src/frapl.c deleted file mode 100644 index 42842cf..0000000 --- a/src/frapl.c +++ /dev/null @@ -1,209 +0,0 @@ -/******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> - - -#define MAX_HEADER 128 -#define UNUSED(expr) do { (void)(expr); } while (0) - - -char * -get_frapl_string(const char *filename) -{ - int fd = open(filename, O_RDONLY); - if (fd == -1) { - return NULL; - } - - char *result = malloc(MAX_HEADER); - int nb = read(fd, result, MAX_HEADER); - close(fd); - result[nb - 1] = 0; - return (result); -} - -void -test_append(char *name, int i) -{ - //char last = name[strlen(name)-1]; - //if (last>='0' && last <= '9') - // return; - sprintf(name + strlen(name), "%d", i); -} - - -struct _frapl_t { - unsigned int nb; - char **names; - int *fids; - uint64_t *values; - uint64_t *tmp_values; - -}; -typedef struct _frapl_t _frapl_t; - - -void -add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) -{ - rapl->nb += 1; - rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); - rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); - - rapl->names[rapl->nb - 1] = malloc(strlen(name) + 1); - strcpy(rapl->names[rapl->nb - 1], name); - //printf("%s\n", energy_uj); - - int fd = open(energy_uj, O_RDONLY); - - if (fd < 0) { - fprintf(stderr, "%s ", energy_uj); - perror("open"); - exit(1); - } - - rapl->fids[rapl->nb - 1] = fd; -} - - -void -_get_frapl(uint64_t *values, _frapl_t *rapl) -{ - static char buffer[512]; - - for (unsigned int i = 0; i < rapl->nb; i++) { - - if (pread(rapl->fids[i], buffer, 100, 0) < 0) { - perror("pread"); - exit(1); - } - - values[i] = strtoull(buffer, NULL, 10); - } -} - - -unsigned int -init_frapl(char *none, void **ptr) -{ - UNUSED(none); - _frapl_t *rapl = malloc(sizeof(_frapl_t)); - rapl->nb = 0; - rapl->names = NULL; - rapl->fids = NULL; - - char buffer[1024]; - char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; - char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - - for (unsigned int i = 0;; i++) { - sprintf(buffer, name_base, i, "name"); - char *tmp = get_frapl_string(buffer); - - if (tmp == NULL) { - break; - } - - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); - add_frapl_source(rapl, tmp, buffer); - free(tmp); - - for (unsigned int j = 0;; j++) { - sprintf(buffer, name_sub, i, i, j, "name"); - char *tmp_sub = get_frapl_string(buffer); - - if (tmp_sub == NULL) { - break; - } - - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - - - sprintf(buffer, name_sub, i, i, j, "energy_uj"); - add_frapl_source(rapl, tmp_sub, buffer); - - free(tmp_sub); - } - } - - rapl->values = calloc(sizeof(uint64_t), rapl->nb); - rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); - - _get_frapl(rapl->values, rapl); - - *ptr = (void *)rapl; - return rapl->nb; -} - - -unsigned int -get_frapl(uint64_t *results, void *ptr) -{ - _frapl_t *state = (_frapl_t *) ptr; - _get_frapl(state->tmp_values, state); - - for (unsigned int i = 0; i < state->nb; i++) { - results[i] = state->tmp_values[i] - state->values[i]; - } - - memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); - return state->nb; -} - -void -clean_frapl(void *ptr) -{ - _frapl_t *rapl = (_frapl_t *) ptr; - - for (unsigned int i = 0; i < rapl->nb; i++) { - free(rapl->names[i]); - close(rapl->fids[i]); - } - - free(rapl->names); - free(rapl->fids); - free(rapl->values); - free(rapl->tmp_values); - free(rapl); -} - - -void -label_frapl(char **labels, void *ptr) -{ - _frapl_t *rapl = (_frapl_t *) ptr; - - for (unsigned int i = 0; i < rapl->nb; i++) { - labels[i] = rapl->names[i]; - } -} diff --git a/src/frapl.h b/src/frapl.h deleted file mode 100644 index 937108e..0000000 --- a/src/frapl.h +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_frapl(char *, void **); -unsigned int get_frapl(uint64_t *results, void *); -void clean_frapl(void *); -void label_frapl(char **labels, void *); - diff --git a/src/mojitos.c b/src/mojitos.c index c0a5655..74e6e9a 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -27,11 +27,10 @@ #include <unistd.h> #include "counters.h" -#include "frapl.h" +#include "rapl.h" #include "infiniband.h" #include "load.h" #include "network.h" -#include "rapl.h" #include "temperature.h" #define UNUSED(expr) do { (void)(expr); } while (0) @@ -188,9 +187,6 @@ main(int argc, char **argv) case 'r': add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); break; - case 'R': - add_source(init_frapl, NULL, label_frapl, get_frapl, clean_frapl); - break; case 'u': add_source(init_load, NULL, label_load, get_load, clean_load); break; diff --git a/src/rapl.c b/src/rapl.c index 0119a4f..90dc838 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. @@ -21,118 +21,141 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> -#include <powercap/powercap-rapl.h> +#define MAX_HEADER 128 #define UNUSED(expr) do { (void)(expr); } while (0) + +char * +get_rapl_string(const char *filename) +{ + int fd = open(filename, O_RDONLY); + if (fd == -1) { + return NULL; + } + + char *result = malloc(MAX_HEADER); + int nb = read(fd, result, MAX_HEADER); + close(fd); + result[nb - 1] = 0; + return (result); +} + +void +test_append(char *name, int i) +{ + //char last = name[strlen(name)-1]; + //if (last>='0' && last <= '9') + // return; + sprintf(name + strlen(name), "%d", i); +} + + struct _rapl_t { - powercap_rapl_pkg *pkgs; - uint32_t nb_pkgs; - uint32_t nb; + unsigned int nb; char **names; - uint32_t *zones; - uint32_t *packages; + int *fids; uint64_t *values; uint64_t *tmp_values; -}; +}; typedef struct _rapl_t _rapl_t; +void +add_rapl_source(_rapl_t *rapl, char *name, char *energy_uj) +{ + rapl->nb += 1; + rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); + rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); + rapl->names[rapl->nb - 1] = malloc(strlen(name) + 1); + strcpy(rapl->names[rapl->nb - 1], name); + //printf("%s\n", energy_uj); + int fd = open(energy_uj, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s ", energy_uj); + perror("open"); + exit(1); + } -const int nb_zones = 3; -const int rapl_zones[3] = { POWERCAP_RAPL_ZONE_PACKAGE, POWERCAP_RAPL_ZONE_CORE, POWERCAP_RAPL_ZONE_DRAM}; - + rapl->fids[rapl->nb - 1] = fd; +} -#define MAX_LEN_NAME 100 -// values [zone + package *nbzones] microjoules void _get_rapl(uint64_t *values, _rapl_t *rapl) { + static char buffer[512]; + for (unsigned int i = 0; i < rapl->nb; i++) { -#ifdef DEBUG - int ret = -#endif - powercap_rapl_get_energy_uj(&rapl->pkgs[rapl->packages[i]], - rapl->zones[i], - &values[i]); -#ifdef DEBUG - printf("GETRAPL: package %d, zone %d, name %s, ret: %d\n", rapl->packages[i], rapl->zones[i], rapl->names[i], ret); -#endif + + if (pread(rapl->fids[i], buffer, 100, 0) < 0) { + perror("pread"); + exit(1); + } + + values[i] = strtoull(buffer, NULL, 10); } } + unsigned int init_rapl(char *none, void **ptr) { UNUSED(none); - // get number of processor sockets - _rapl_t *rapl = malloc(sizeof(struct _rapl_t)); + _rapl_t *rapl = malloc(sizeof(_rapl_t)); rapl->nb = 0; - rapl->packages = NULL; - rapl->zones = NULL; - - rapl->nb_pkgs = powercap_rapl_get_num_instances(); - //rapl->nb_pkgs = powercap_rapl_get_num_packages(); + rapl->names = NULL; + rapl->fids = NULL; - if (rapl->nb_pkgs == 0) { - perror("no packages found (maybe the kernel module isn't loaded?)"); - exit(-1); - } + char buffer[1024]; + char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; + char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - rapl->pkgs = malloc(rapl->nb_pkgs * sizeof(powercap_rapl_pkg)); + for (unsigned int i = 0;; i++) { + sprintf(buffer, name_base, i, "name"); + char *tmp = get_rapl_string(buffer); - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_init(package, &rapl->pkgs[package], 0)) { - perror("powercap_rapl_init, check access (root needed ?)"); - exit(-1); + if (tmp == NULL) { + break; } - rapl->names = NULL; + //printf("%s\n", tmp); + test_append(tmp, i); + //printf("%s -> %s\n", buffer, tmp); - char _name[MAX_LEN_NAME + 1]; - char _name2[MAX_LEN_NAME + 11]; + sprintf(buffer, name_base, i, "energy_uj"); + add_rapl_source(rapl, tmp, buffer); + free(tmp); - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) { - for (unsigned int zone = 0; zone < nb_zones; zone++) { - int length = powercap_rapl_get_name(&rapl->pkgs[package], rapl_zones[zone], - _name, MAX_LEN_NAME); + for (unsigned int j = 0;; j++) { + sprintf(buffer, name_sub, i, i, j, "name"); + char *tmp_sub = get_rapl_string(buffer); - if (length > 0) { + if (tmp_sub == NULL) { + break; + } - sprintf(_name2, "%s%u", _name, package); + //printf("%s\n", tmp_sub); + test_append(tmp_sub, i); + //printf("%s -> %s\n", buffer, tmp_sub); - rapl->nb++; - rapl->names = realloc(rapl->names, sizeof(char *)*rapl->nb); - rapl->names[rapl->nb - 1] = malloc(sizeof(char) * (strlen(_name2) + 1)); - rapl->zones = realloc(rapl->zones, sizeof(uint32_t) * rapl->nb); - rapl->packages = realloc(rapl->packages, sizeof(uint32_t) * rapl->nb); - strcpy(rapl->names[rapl->nb - 1], _name2); - rapl->zones[rapl->nb - 1] = rapl_zones[zone]; - rapl->packages[rapl->nb - 1] = package; - } + sprintf(buffer, name_sub, i, i, j, "energy_uj"); + add_rapl_source(rapl, tmp_sub, buffer); -#ifdef DEBUG - printf("%d %d %d %d %s\n\n", length, package, zone, rapl_zones[zone], _name2); -#endif + free(tmp_sub); } } -#ifdef DEBUG - printf("Result of init\n"); - - for (unsigned int i = 0; i < rapl->nb; i++) { - printf("package %d, zone %d, name %s\n", rapl->packages[i], rapl->zones[i], rapl->names[i]); - } - -#endif - rapl->values = calloc(sizeof(uint64_t), rapl->nb); rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); @@ -143,7 +166,6 @@ init_rapl(char *none, void **ptr) } - unsigned int get_rapl(uint64_t *results, void *ptr) { @@ -158,32 +180,24 @@ get_rapl(uint64_t *results, void *ptr) return state->nb; } - - - void clean_rapl(void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; - for (unsigned int package = 0; package < rapl->nb_pkgs; package++) - if (powercap_rapl_destroy(&rapl->pkgs[package])) { - perror("powercap_rapl_destroy"); - } - - for (unsigned int elem = 0; elem < rapl->nb; elem++) { - free(rapl->names[elem]); + for (unsigned int i = 0; i < rapl->nb; i++) { + free(rapl->names[i]); + close(rapl->fids[i]); } free(rapl->names); - free(rapl->pkgs); - free(rapl->zones); - free(rapl->packages); + free(rapl->fids); free(rapl->values); free(rapl->tmp_values); free(rapl); } + void label_rapl(char **labels, void *ptr) { diff --git a/src/rapl.h b/src/rapl.h index 74cc515..ddce4cc 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. -- GitLab From fdd08d9a4376a284cf06c0a13ed5d422d39125a7 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 15:01:44 +0100 Subject: [PATCH 026/125] properly reformat this time.. --- src/counters.c | 38 +++++++++++++------------------------- src/counters_group.c | 20 +++++++------------- src/infiniband.c | 6 ++---- src/load.c | 15 +++++---------- src/mojitos.c | 20 +++++++------------- src/network.c | 15 +++++---------- src/rapl.c | 24 ++++++++---------------- src/temperature.c | 21 +++++++-------------- 8 files changed, 54 insertions(+), 105 deletions(-) diff --git a/src/counters.c b/src/counters.c index 7441a07..de00d62 100644 --- a/src/counters.c +++ b/src/counters.c @@ -42,16 +42,14 @@ typedef struct _counter_t *counter_t; #include "counters_option.h" -void -show_all_counters() +void show_all_counters() { for (unsigned int i = 0; i < nb_counter_option; i++) { printf("%s\n", perf_static_info[i].name); } } -void -perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) +void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) { *perf_type = malloc(nb * sizeof(__u32)); *perf_key = malloc(nb * sizeof(__u64)); @@ -61,8 +59,7 @@ perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) (*perf_type)[i] = perf_static_info[indexes[i]].perf_type; } } -void -perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) +void perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) { char *token; *nb_perf = 0; @@ -88,9 +85,8 @@ perf_event_list(char *perf_string, int *nb_perf, int **perf_indexes) } } -static long -perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) { long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); @@ -103,8 +99,7 @@ perf_event_open(struct perf_event_attr *hw_event, pid_t pid, return res; } -counter_t -_init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { struct perf_event_attr pe; unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); @@ -130,8 +125,7 @@ _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) return counters; } -void -clean_counters(void *ptr) +void clean_counters(void *ptr) { counter_t counters = (counter_t) ptr; @@ -151,8 +145,7 @@ clean_counters(void *ptr) free(counters); } -void -start_counters(counter_t counters) +void start_counters(counter_t counters) { for (int counter = 0; counter < counters->nbperf; counter++) { for (int core = 0; core < counters->nbcores; core++) { @@ -161,8 +154,7 @@ start_counters(counter_t counters) } } -void -reset_counters(counter_t counters) +void reset_counters(counter_t counters) { for (int counter = 0; counter < counters->nbperf; counter++) { for (int core = 0; core < counters->nbcores; core++) { @@ -171,8 +163,7 @@ reset_counters(counter_t counters) } } -void -_get_counters(counter_t counters, uint64_t *values) +void _get_counters(counter_t counters, uint64_t *values) { for (int i = 0; i < counters->nbperf; i++) { uint64_t accu = 0; @@ -195,8 +186,7 @@ _get_counters(counter_t counters, uint64_t *values) -unsigned int -init_counters(char *args, void **state) +unsigned int init_counters(char *args, void **state) { int nb_perf; int *perf_indexes = NULL; @@ -220,8 +210,7 @@ init_counters(char *args, void **state) return nb_perf; } -unsigned int -get_counters(uint64_t *results, void *ptr) +unsigned int get_counters(uint64_t *results, void *ptr) { counter_t state = (counter_t) ptr; @@ -235,8 +224,7 @@ get_counters(uint64_t *results, void *ptr) return state->nbperf; } -void -label_counters(char **labels, void *ptr) +void label_counters(char **labels, void *ptr) { counter_t state = (counter_t) ptr; diff --git a/src/counters_group.c b/src/counters_group.c index aa441d5..66eba2c 100644 --- a/src/counters_group.c +++ b/src/counters_group.c @@ -35,9 +35,8 @@ struct _counter_t { int *counters; }; -static long -perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) { long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); @@ -50,8 +49,7 @@ perf_event_open(struct perf_event_attr *hw_event, pid_t pid, return res; } -counter_t -init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { struct perf_event_attr pe; struct _counter_t *counters = malloc(sizeof(struct _counter_t)); @@ -83,8 +81,7 @@ init_counters(const int nb_perf, const __u32 *types, const __u64 *names) return counters; } -void -clean_counters(counter_t counters) +void clean_counters(counter_t counters) { for (int core = 0; core < counters->nbcores; core++) { close(counters->counters[core]); @@ -94,15 +91,13 @@ clean_counters(counter_t counters) free(counters); } -void -start_counters(counter_t counters) +void start_counters(counter_t counters) { for (int core = 0; core < counters->nbcores; core++) { ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); } } -void -reset_counters(counter_t counters) +void reset_counters(counter_t counters) { for (int core = 0; core < counters->nbcores; core++) { ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); @@ -116,8 +111,7 @@ struct read_format { } values[]; }; -void -get_counters(counter_t counters, long long *values) +void get_counters(counter_t counters, long long *values) { int nb_perf = counters->nbperf; size_t buffer_size = sizeof(uint64_t) * (1 + nb_perf); diff --git a/src/infiniband.c b/src/infiniband.c index d5da4eb..6f47ab2 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -37,8 +37,7 @@ struct network_t { unsigned int _get_network(uint64_t *results, int *sources); -unsigned int -init_infiniband(char *infi_path, void **ptr) +unsigned int init_infiniband(char *infi_path, void **ptr) { if (infi_path == NULL) { return 0; @@ -78,8 +77,7 @@ init_infiniband(char *infi_path, void **ptr) } char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; -void -label_infiniband(char **labels, void *none) +void label_infiniband(char **labels, void *none) { UNUSED(none); diff --git a/src/load.c b/src/load.c index c0013ab..96d08b8 100644 --- a/src/load.c +++ b/src/load.c @@ -33,8 +33,7 @@ static uint64_t load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static uint64_t tmp_load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static char *stat = "/proc/stat"; -void -_get_load(uint64_t *results) +void _get_load(uint64_t *results) { if (pread(load_fid, buffer, LOAD_BUFFER_SIZE - 1, 0) < 0) { perror("pread"); @@ -60,8 +59,7 @@ _get_load(uint64_t *results) // Public interface -unsigned int -init_load(char *argument, void **state) +unsigned int init_load(char *argument, void **state) { UNUSED(argument); UNUSED(state); @@ -76,8 +74,7 @@ init_load(char *argument, void **state) return 10; } -unsigned int -get_load(uint64_t *results, void *state) +unsigned int get_load(uint64_t *results, void *state) { UNUSED(state); _get_load(tmp_load_values); @@ -90,8 +87,7 @@ get_load(uint64_t *results, void *state) return 10; } -void -clean_load(void *state) +void clean_load(void *state) { UNUSED(state); close(load_fid); @@ -100,8 +96,7 @@ clean_load(void *state) char *_labels[10] = {"user", "nice", "system", "idle", "iowait", "irq", "softirq", "steal", "guest", "guest_nice" }; -void -label_load(char **labels, void *none) +void label_load(char **labels, void *none) { UNUSED(none); diff --git a/src/mojitos.c b/src/mojitos.c index 74e6e9a..b6c057f 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -43,8 +43,7 @@ } while (0) -void -usage(char **argv) +void usage(char **argv) { printf("Usage : %s [-rRluc] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" @@ -64,22 +63,19 @@ usage(char **argv) exit(EXIT_SUCCESS); } -void -sighandler(int none) +void sighandler(int none) { UNUSED(none); } -void -flush(int none) +void flush(int none) { UNUSED(none); exit(0); } FILE *output; -void -flushexit() +void flushexit() { if (output != NULL) { fflush(output); @@ -101,9 +97,8 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void -add_source(initializer_t init, char *arg, labeler_t labeler, - getter_t get, cleaner_t clean) +void add_source(initializer_t init, char *arg, labeler_t labeler, + getter_t get, cleaner_t clean) { nb_sources++; states = realloc(states, nb_sources * sizeof(void *)); @@ -127,8 +122,7 @@ add_source(initializer_t init, char *arg, labeler_t labeler, nb_sensors += nb; } -int -main(int argc, char **argv) +int main(int argc, char **argv) { int total_time = 1; int delta = 0; diff --git a/src/network.c b/src/network.c index 5b94151..f57a383 100644 --- a/src/network.c +++ b/src/network.c @@ -34,8 +34,7 @@ struct network_t { int sources[NB_SENSOR]; }; -unsigned int -_get_network(uint64_t *results, int *sources) +unsigned int _get_network(uint64_t *results, int *sources) { if (sources == NULL) { return 0; @@ -57,8 +56,7 @@ _get_network(uint64_t *results, int *sources) -unsigned int -init_network(char *dev, void **ptr) +unsigned int init_network(char *dev, void **ptr) { if (dev == NULL) { return 0; @@ -108,8 +106,7 @@ init_network(char *dev, void **ptr) return NB_SENSOR; } -unsigned int -get_network(uint64_t *results, void *ptr) +unsigned int get_network(uint64_t *results, void *ptr) { struct network_t *state = (struct network_t *) ptr; _get_network(state->tmp_values, state->sources); @@ -122,8 +119,7 @@ get_network(uint64_t *results, void *ptr) return NB_SENSOR; } -void -clean_network(void *ptr) +void clean_network(void *ptr) { struct network_t *state = (struct network_t *) ptr; @@ -139,8 +135,7 @@ clean_network(void *ptr) } char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; -void -label_network(char **labels, void *none) +void label_network(char **labels, void *none) { UNUSED(none); diff --git a/src/rapl.c b/src/rapl.c index 90dc838..cd558d2 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -31,8 +31,7 @@ #define UNUSED(expr) do { (void)(expr); } while (0) -char * -get_rapl_string(const char *filename) +char *get_rapl_string(const char *filename) { int fd = open(filename, O_RDONLY); if (fd == -1) { @@ -46,8 +45,7 @@ get_rapl_string(const char *filename) return (result); } -void -test_append(char *name, int i) +void test_append(char *name, int i) { //char last = name[strlen(name)-1]; //if (last>='0' && last <= '9') @@ -67,8 +65,7 @@ struct _rapl_t { typedef struct _rapl_t _rapl_t; -void -add_rapl_source(_rapl_t *rapl, char *name, char *energy_uj) +void add_rapl_source(_rapl_t *rapl, char *name, char *energy_uj) { rapl->nb += 1; rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); @@ -90,8 +87,7 @@ add_rapl_source(_rapl_t *rapl, char *name, char *energy_uj) } -void -_get_rapl(uint64_t *values, _rapl_t *rapl) +void _get_rapl(uint64_t *values, _rapl_t *rapl) { static char buffer[512]; @@ -107,8 +103,7 @@ _get_rapl(uint64_t *values, _rapl_t *rapl) } -unsigned int -init_rapl(char *none, void **ptr) +unsigned int init_rapl(char *none, void **ptr) { UNUSED(none); _rapl_t *rapl = malloc(sizeof(_rapl_t)); @@ -166,8 +161,7 @@ init_rapl(char *none, void **ptr) } -unsigned int -get_rapl(uint64_t *results, void *ptr) +unsigned int get_rapl(uint64_t *results, void *ptr) { _rapl_t *state = (_rapl_t *) ptr; _get_rapl(state->tmp_values, state); @@ -180,8 +174,7 @@ get_rapl(uint64_t *results, void *ptr) return state->nb; } -void -clean_rapl(void *ptr) +void clean_rapl(void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; @@ -198,8 +191,7 @@ clean_rapl(void *ptr) } -void -label_rapl(char **labels, void *ptr) +void label_rapl(char **labels, void *ptr) { _rapl_t *rapl = (_rapl_t *) ptr; diff --git a/src/temperature.c b/src/temperature.c index d0d1e9e..049ade7 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -33,8 +33,7 @@ struct temperature_t { int nb_elem; }; -int -get_string(char *filename, char *buffer, int max_size) +int get_string(char *filename, char *buffer, int max_size) { int fid = open(filename, O_RDONLY); @@ -54,8 +53,7 @@ get_string(char *filename, char *buffer, int max_size) return 0; } -void -add_to_list(char ***list_name, char *source, int nb_elem) +void add_to_list(char ***list_name, char *source, int nb_elem) { //printf("Adds: %s\n", source); *list_name = realloc(*list_name, (nb_elem + 1) * sizeof(char *)); @@ -64,8 +62,7 @@ add_to_list(char ***list_name, char *source, int nb_elem) } -void -add_temperature_sensor(int id_rep, struct temperature_t *state) +void add_temperature_sensor(int id_rep, struct temperature_t *state) { static int key = 0; static char buffer_filename[512]; @@ -110,8 +107,7 @@ add_temperature_sensor(int id_rep, struct temperature_t *state) key++; } -unsigned int -init_temperature(char *args, void **ptr) +unsigned int init_temperature(char *args, void **ptr) { UNUSED(args); struct temperature_t *state = malloc(sizeof(struct temperature_t)); @@ -139,8 +135,7 @@ init_temperature(char *args, void **ptr) return state->nb_elem; } -unsigned int -get_temperature(uint64_t *results, void *ptr) +unsigned int get_temperature(uint64_t *results, void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; static char buffer[512]; @@ -156,8 +151,7 @@ get_temperature(uint64_t *results, void *ptr) return state->nb_elem; } -void -clean_temperature(void *ptr) +void clean_temperature(void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; @@ -171,8 +165,7 @@ clean_temperature(void *ptr) free(state); } -void -label_temperature(char **labels, void *ptr) +void label_temperature(char **labels, void *ptr) { struct temperature_t *state = (struct temperature_t *)ptr; -- GitLab From d2075487da6b1e50e265c4f1d2761b0ae1315fea Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 15:32:04 +0100 Subject: [PATCH 027/125] cleanup, corrections --- makefile | 4 +- src/counters_group.c | 138 ------------------------------- src/frapl.c | 192 ------------------------------------------- 3 files changed, 2 insertions(+), 332 deletions(-) delete mode 100644 src/counters_group.c delete mode 100644 src/frapl.c diff --git a/makefile b/makefile index bc3dd53..66a376c 100644 --- a/makefile +++ b/makefile @@ -19,10 +19,10 @@ all: mojitos mojitos: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS) $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos $(OBJECTS) -lpowercap -$(OBJ_DIR)/counters_%.o: $(SRC_DIR)/counters_%.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h +$(OBJ_DIR)/counters.o: $(SRC_DIR)/counters.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h $(CC) $(CFLAGS) -c $< -o $@ -$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.py +$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh sh ./$(SRC_DIR)/counters_option.sh > $(SRC_DIR)/counters_option.h $(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h diff --git a/src/counters_group.c b/src/counters_group.c deleted file mode 100644 index 66eba2c..0000000 --- a/src/counters_group.c +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <linux/perf_event.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/ioctl.h> -#include <stdio.h> -#include <stdint.h> -#include <asm/unistd.h> - -#include "counters.h" - -struct _counter_t { - int nbcores; - int nbperf; - int *counters; -}; - -static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, - int cpu, int group_fd, unsigned long flags) -{ - long res = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - - if (res == -1) { - perror("perf_event_open"); - fprintf(stderr, "Error opening leader %llx\n", hw_event->config); - exit(EXIT_FAILURE); - } - - return res; -} - -counter_t init_counters(const int nb_perf, const __u32 *types, const __u64 *names) -{ - struct perf_event_attr pe; - struct _counter_t *counters = malloc(sizeof(struct _counter_t)); - - unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); - counters->nbcores = nbcores; - counters->nbperf = nb_perf; - memset(&pe, 0, sizeof(struct perf_event_attr)); - pe.size = sizeof(struct perf_event_attr); - pe.disabled = 1; - - pe.read_format = PERF_FORMAT_GROUP; - counters->counters = malloc((nbcores + 1) * sizeof(int)); - - for (int core = 0; core < nbcores; core++) { - counters->counters[core] = -1; - - for (int idperf = 0; idperf < nb_perf; idperf ++) { - pe.type = types[idperf]; - pe.config = names[idperf]; - int res = perf_event_open(&pe, -1, core, counters->counters[core], PERF_FLAG_FD_CLOEXEC); - - if (counters->counters[core] == -1) { - counters->counters[core] = res; - } - } - } - - return counters; -} - -void clean_counters(counter_t counters) -{ - for (int core = 0; core < counters->nbcores; core++) { - close(counters->counters[core]); - } - - free(counters->counters); - free(counters); -} - -void start_counters(counter_t counters) -{ - for (int core = 0; core < counters->nbcores; core++) { - ioctl(counters->counters[core], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); - } -} -void reset_counters(counter_t counters) -{ - for (int core = 0; core < counters->nbcores; core++) { - ioctl(counters->counters[core], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); - } -} - -struct read_format { - uint64_t nr; - struct { - uint64_t value; - } values[]; -}; - -void get_counters(counter_t counters, long long *values) -{ - int nb_perf = counters->nbperf; - size_t buffer_size = sizeof(uint64_t) * (1 + nb_perf); - struct read_format *buffer = NULL; - - if (buffer == NULL) { - buffer = malloc(buffer_size); - } - - memset(values, 0, nb_perf * sizeof(long long)); - - for (int core = 0; core < counters->nbcores; core++) { - if (-1 == read(counters->counters[core], buffer, buffer_size)) { - perror("PB Lecture resultat"); - exit(EXIT_FAILURE); - } - - for (int idperf = 0; idperf <= nb_perf; idperf++) { - values[idperf] += buffer->values[idperf].value; - } - } - - reset_counters(counters); -} diff --git a/src/frapl.c b/src/frapl.c deleted file mode 100644 index 6048e1d..0000000 --- a/src/frapl.c +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> - - -#define MAX_HEADER 128 -#define UNUSED(expr) do { (void)(expr); } while (0) - - -char *get_frapl_string(const char *filename) -{ - int fd = open(filename, O_RDONLY); - if( fd == -1) - { - return NULL; - } - char *result = malloc(MAX_HEADER); - int nb = read(fd, result, MAX_HEADER); - close(fd); - result[nb-1] = 0; - return (result); -} - -void test_append(char *name, int i) -{ - //char last = name[strlen(name)-1]; - //if (last>='0' && last <= '9') - // return; - sprintf(name+strlen(name), "%d", i); -} - - -struct _frapl_t -{ - unsigned int nb; - char **names; - int *fids; - uint64_t *values; - uint64_t *tmp_values; - -}; -typedef struct _frapl_t _frapl_t; - - -void add_frapl_source(_frapl_t *rapl, char *name, char *energy_uj) -{ - rapl->nb += 1; - rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); - rapl->fids = realloc(rapl->fids, sizeof(int *)*rapl->nb); - - rapl->names[rapl->nb-1] = malloc(strlen(name)+1); - strcpy(rapl->names[rapl->nb-1], name); - //printf("%s\n", energy_uj); - - int fd = open(energy_uj, O_RDONLY); - - if (fd < 0) - { - fprintf(stderr, "%s ", energy_uj); - perror("open"); - exit(1); - } - rapl->fids[rapl->nb-1] = fd; -} - - -void _get_frapl(uint64_t *values, _frapl_t *rapl) -{ - static char buffer[512]; - - for (unsigned int i = 0; i < rapl->nb; i++) - { - - if (pread(rapl->fids[i], buffer, 100, 0) < 0) - { - perror("pread"); - exit(1); - } - values[i] = strtoull(buffer, NULL, 10); - } -} - - -unsigned int init_frapl(char *none, void **ptr) -{ - UNUSED(none); - _frapl_t *rapl = malloc(sizeof(_frapl_t)); - rapl->nb = 0; - rapl->names = NULL; - rapl->fids = NULL; - - char buffer[1024]; - char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; - char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; - - for (unsigned int i=0;; i++) - { - sprintf(buffer, name_base, i, "name"); - char *tmp = get_frapl_string(buffer); - if (tmp == NULL) break; - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); - add_frapl_source(rapl, tmp, buffer); - free(tmp); - - for (unsigned int j=0;; j++) - { - sprintf(buffer, name_sub, i, i, j, "name"); - char *tmp_sub = get_frapl_string(buffer); - if (tmp_sub == NULL) break; - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - - - sprintf(buffer, name_sub, i, i, j, "energy_uj"); - add_frapl_source(rapl, tmp_sub, buffer); - - free(tmp_sub); - } - } - - rapl->values = calloc(sizeof(uint64_t), rapl->nb); - rapl->tmp_values = calloc(sizeof(uint64_t), rapl->nb); - - _get_frapl(rapl->values, rapl); - - *ptr = (void *)rapl; - return rapl->nb; -} - - -unsigned int get_frapl(uint64_t *results, void *ptr) -{ - _frapl_t *state = (_frapl_t *) ptr; - _get_frapl(state->tmp_values, state); - for(unsigned int i=0; i<state->nb; i++) - results[i] = state->tmp_values[i] - state->values[i]; - - memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); - return state->nb; -} - -void clean_frapl(void *ptr) -{ - _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) - { - free(rapl->names[i]); - close(rapl->fids[i]); - } - free(rapl->names); - free(rapl->fids); - free(rapl->values); - free(rapl->tmp_values); - free(rapl); -} - - -void label_frapl(char **labels, void *ptr) -{ - _frapl_t *rapl = (_frapl_t *) ptr; - for(unsigned int i=0; i<rapl->nb; i++) - labels[i] = rapl->names[i]; -} -- GitLab From 8ff09885f804be8bfd04b4d7c7510d91c7ee4bd9 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 17:56:00 +0100 Subject: [PATCH 028/125] small changes on makefile - .POSIX rule - BIN macro - add LDFLAGS - some other changes.. --- makefile | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/makefile b/makefile index 66a376c..4d3fa12 100644 --- a/makefile +++ b/makefile @@ -1,36 +1,44 @@ -.PHONY: all clean mojitos mojitos_group debug format +.POSIX: SRC_DIR = src OBJ_DIR = obj BIN_DIR = bin -OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o infiniband.o temperature.o) -OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) +BIN = mojitos + +OBJ = $(addprefix $(OBJ_DIR)/, \ + counters.o \ + rapl.o \ + network.o \ + load.o \ + infiniband.o \ + temperature.o \ +) CC = gcc CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic +LDFLAGS = -lpowercap ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -# depending on the context it may need to be changed to all: mojitos mojitos_group -all: mojitos - -mojitos: $(OBJ_DIR) $(BIN_DIR) $(OBJECTS) - $(CC) $(CFLAGS) -o $(BIN_DIR)/mojitos $(OBJECTS) -lpowercap +all: $(BIN) -$(OBJ_DIR)/counters.o: $(SRC_DIR)/counters.c $(SRC_DIR)/counters.h $(SRC_DIR)/counters_option.h - $(CC) $(CFLAGS) -c $< -o $@ +$(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o + $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o -$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh - sh ./$(SRC_DIR)/counters_option.sh > $(SRC_DIR)/counters_option.h +$(OBJ): $(OBJ_DIR) +$(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h -$(OBJ_DIR)/mojitos.o: $(SRC_DIR)/mojitos.c $(SRC_DIR)/counters_option.h +$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(SRC_DIR)/counters_option.h $(CC) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(SRC_DIR)/%.h +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h $(CC) $(CFLAGS) -c $< -o $@ +$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh + sh ./$(SRC_DIR)/counters_option.sh > $(SRC_DIR)/counters_option.h + $(OBJ_DIR): mkdir -p $(OBJ_DIR) @@ -46,3 +54,5 @@ format: clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \rm -f $(SRC_DIR)/counters_option.h + +.PHONY: all clean mojitos debug format -- GitLab From 471ccfd974c5b8d1f2316d57fade66fc24dc06fc Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 19:52:23 +0100 Subject: [PATCH 029/125] replace getop with "optparse" plus usage fix and makefile fix add long options --- makefile | 2 +- src/mojitos.c | 55 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/makefile b/makefile index 4d3fa12..488f39c 100644 --- a/makefile +++ b/makefile @@ -16,7 +16,7 @@ OBJ = $(addprefix $(OBJ_DIR)/, \ ) CC = gcc -CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic +CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function LDFLAGS = -lpowercap ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q diff --git a/src/mojitos.c b/src/mojitos.c index b6c057f..cd8fcad 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -33,6 +33,10 @@ #include "network.h" #include "temperature.h" +#define OPTPARSE_IMPLEMENTATION +#define OPTPARSE_API static +#include "optparse.h" + #define UNUSED(expr) do { (void)(expr); } while (0) #define PANIC(code, fmt, ...) \ do { \ @@ -45,12 +49,11 @@ void usage(char **argv) { - printf("Usage : %s [-rRluc] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" + printf("Usage : %s [-rlucs] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" "if time==0 then loops infinitively\n" "if -e is present, time and freq are not used\n" "-r activates RAPL\n" - "-R activates the file version of RAPL\n" "-p activates performance counters\n" " perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n" "-l lists the possible performance counters and quits\n" @@ -60,7 +63,7 @@ void usage(char **argv) "-u activates report of system load\n" "-c activates report of processor temperature\n" , argv[0]); - exit(EXIT_SUCCESS); + exit(EXIT_FAILURE); } void sighandler(int none) @@ -140,17 +143,32 @@ int main(int argc, char **argv) atexit(flushexit); signal(15, flush); - int c; - - while ((c = getopt (argc, argv, "ilhcftdeoprRsu")) != -1 && application == NULL) { - switch (c) { + int opt; + struct optparse options; + options.permute = 0; + struct optparse_long longopts[] = { + {"monitor-infiniband", 'i', OPTPARSE_REQUIRED}, + {"freq", 'f', OPTPARSE_REQUIRED}, + {"time", 't', OPTPARSE_REQUIRED}, + {"net-dev", 'd', OPTPARSE_REQUIRED}, + {"exec", 'e', OPTPARSE_REQUIRED}, + {"logfile", 'o', OPTPARSE_REQUIRED}, + {"perf-list", 'p', OPTPARSE_REQUIRED}, + {"cpu-temp", 'c', OPTPARSE_NONE}, + {"rapl", 'r', OPTPARSE_NONE}, + {"overhead-stats", 's', OPTPARSE_NONE}, + {"sysload", 'u', OPTPARSE_NONE}, + {"list", 'l', OPTPARSE_NONE}, + }; + + optparse_init(&options, argv); + while ((opt = optparse_long(&options, longopts, NULL)) != -1 && application == NULL) { + switch (opt) { case 'f': - if (optind >= argc) PANIC(1,"-f, no frequency provided"); - frequency = atoi(argv[optind]); + frequency = atoi(options.optarg); break; case 't': - if (optind >= argc) PANIC(1,"-t, no time provided"); - total_time = atoi(argv[optind]); + total_time = atoi(options.optarg); delta = 1; if (total_time == 0) { total_time = 1; @@ -158,25 +176,23 @@ int main(int argc, char **argv) } break; case 'd': - add_source(init_network, argv[optind], label_network, get_network, clean_network); + add_source(init_network, options.optarg, label_network, get_network, clean_network); break; case 'i': - add_source(init_infiniband, argv[optind], label_infiniband, get_network, clean_network); + add_source(init_infiniband, options.optarg, label_infiniband, get_network, clean_network); break; case 'o': - if (optind >= argc) PANIC(1,"-o, no logfile provided"); - if ((output = fopen(argv[optind], "wb")) == NULL) { + if ((output = fopen(options.optarg, "wb")) == NULL) { perror("fopen"); - PANIC(1, "-o %s", argv[optind]); + PANIC(1, "-o %s", options.optarg); } break; case 'e': - application = &argv[optind]; + application = options.argv; signal(17, sighandler); break; case 'p': - if (optind >= argc) PANIC(1,"-p, no counter provided"); - add_source(init_counters, argv[optind], label_counters, get_counters, clean_counters); + add_source(init_counters, options.optarg, label_counters, get_counters, clean_counters); break; case 'r': add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); @@ -194,6 +210,7 @@ int main(int argc, char **argv) show_all_counters(); exit(EXIT_SUCCESS); default: + fprintf(stderr, "%s: %s\n", argv[0], options.errmsg); usage(argv); } } -- GitLab From f38c9908a426c73f06dfb37d05fd2951064256cb Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 16 Jan 2023 19:54:47 +0100 Subject: [PATCH 030/125] add -Wno-unused-function to CFLAGS in makefile --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 5198055..6a709b2 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc -CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic +CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -- GitLab From 0fc68415b1b1a773e227cf5406f02629b88d3a6f Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Tue, 17 Jan 2023 19:54:15 +0100 Subject: [PATCH 031/125] utils file --- .gitignore | 8 +- LICENSE | 1348 ++++++++++++++++++++-------------------- makefile | 2 +- src/counters.h | 52 +- src/counters_option.py | 124 ++-- src/infiniband.h | 44 +- src/load.h | 48 +- src/network.h | 50 +- src/temperature.h | 48 +- src/util.c | 6 + src/util.h | 5 + 11 files changed, 873 insertions(+), 862 deletions(-) create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/.gitignore b/.gitignore index f5893ce..5a8f74f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -*.o -src/counters_option.h -bin -obj +*.o +src/counters_option.h +bin +obj diff --git a/LICENSE b/LICENSE index f288702..3877ae0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,674 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<https://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<https://www.gnu.org/licenses/why-not-lgpl.html>. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>. diff --git a/makefile b/makefile index 6a709b2..9988f8a 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ SRC_DIR = src OBJ_DIR = obj BIN_DIR = bin -OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o infiniband.o temperature.o) +OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o infiniband.o temperature.o util.o) OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc diff --git a/src/counters.h b/src/counters.h index af20717..bd2d0a5 100644 --- a/src/counters.h +++ b/src/counters.h @@ -1,26 +1,26 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_counters(char *, void **); -unsigned int get_counters(uint64_t *results, void *); -void clean_counters(void *); -void label_counters(char **labels, void *); - -void show_all_counters(); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_counters(char *, void **); +unsigned int get_counters(uint64_t *results, void *); +void clean_counters(void *); +void label_counters(char **labels, void *); + +void show_all_counters(); diff --git a/src/counters_option.py b/src/counters_option.py index 877a33a..d853e41 100755 --- a/src/counters_option.py +++ b/src/counters_option.py @@ -1,62 +1,62 @@ -#! /usr/bin/python3 - -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - -linux_include = '/usr/include/linux/perf_event.h' - -string = """#include <linux/perf_event.h> - -typedef struct counter_option { - char *name; - __u32 perf_type; - __u64 perf_key; -} counter_option; - -static counter_option perf_static_info[] = {""" -print(string) - -nb = 0 - -black_list = ['stalled_cycles_frontend','stalled_cycles_backend', - 'cache_l1i', 'cache_op_write', 'cache_result_miss'] - -with open(linux_include, 'r') as infile: - mode = '' - for line in infile: - if 'perf_hw_id' in line: - mode = 'PERF_TYPE_HARDWARE' - elif 'perf_hw_cache_' in line: - mode = 'PERF_TYPE_HW_CACHE' - elif 'perf_sw_id' in line: - mode = 'PERF_TYPE_SOFTWARE' - elif 'PERF_COUNT_' in line and '=' in line: - perf_name = line.split()[0] - short_perf = perf_name[14:].lower() - if short_perf in black_list: - continue - if mode == 'PERF_TYPE_HW_CACHE': - for op_id, op_id_str in enumerate(['r', 'w', 'p']): - op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] - for result_id, result_id_str in enumerate(['a', 'm']): - result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] - - res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( - short_perf, op_id_str, result_id_str, - mode, - perf_name, - op_id_names[op_id], - result_id_names[result_id]) - - print(res) - nb += 1 - - else: - res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' - print(res) - nb += 1 - - -print('};') - -print('static unsigned int nb_counter_option =',nb,';') +#! /usr/bin/python3 + +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + +linux_include = '/usr/include/linux/perf_event.h' + +string = """#include <linux/perf_event.h> + +typedef struct counter_option { + char *name; + __u32 perf_type; + __u64 perf_key; +} counter_option; + +static counter_option perf_static_info[] = {""" +print(string) + +nb = 0 + +black_list = ['stalled_cycles_frontend','stalled_cycles_backend', + 'cache_l1i', 'cache_op_write', 'cache_result_miss'] + +with open(linux_include, 'r') as infile: + mode = '' + for line in infile: + if 'perf_hw_id' in line: + mode = 'PERF_TYPE_HARDWARE' + elif 'perf_hw_cache_' in line: + mode = 'PERF_TYPE_HW_CACHE' + elif 'perf_sw_id' in line: + mode = 'PERF_TYPE_SOFTWARE' + elif 'PERF_COUNT_' in line and '=' in line: + perf_name = line.split()[0] + short_perf = perf_name[14:].lower() + if short_perf in black_list: + continue + if mode == 'PERF_TYPE_HW_CACHE': + for op_id, op_id_str in enumerate(['r', 'w', 'p']): + op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] + for result_id, result_id_str in enumerate(['a', 'm']): + result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] + + res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( + short_perf, op_id_str, result_id_str, + mode, + perf_name, + op_id_names[op_id], + result_id_names[result_id]) + + print(res) + nb += 1 + + else: + res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' + print(res) + nb += 1 + + +print('};') + +print('static unsigned int nb_counter_option =',nb,';') diff --git a/src/infiniband.h b/src/infiniband.h index 1f6aaf9..4234964 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -1,22 +1,22 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_infiniband(char *infi_path, void **ptr); -void label_infiniband(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_infiniband(char *infi_path, void **ptr); +void label_infiniband(char **labels, void *); diff --git a/src/load.h b/src/load.h index 299fa3e..78c1b40 100644 --- a/src/load.h +++ b/src/load.h @@ -1,24 +1,24 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_load(char *, void **); -unsigned int get_load(uint64_t *results, void *); -void clean_load(void *); -void label_load(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_load(char *, void **); +unsigned int get_load(uint64_t *results, void *); +void clean_load(void *); +void label_load(char **labels, void *); diff --git a/src/network.h b/src/network.h index 3ba9ae5..b770560 100644 --- a/src/network.h +++ b/src/network.h @@ -1,25 +1,25 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_network(char *, void **); -unsigned int get_network(uint64_t *results, void *); -void clean_network(void *); -void label_network(char **labels, void *); - +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_network(char *, void **); +unsigned int get_network(uint64_t *results, void *); +void clean_network(void *); +void label_network(char **labels, void *); + diff --git a/src/temperature.h b/src/temperature.h index e49e416..ac8e34b 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -1,24 +1,24 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_temperature(char *, void **); -unsigned int get_temperature(uint64_t *results, void *); -void clean_temperature(void *); -void label_temperature(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_temperature(char *, void **); +unsigned int get_temperature(uint64_t *results, void *); +void clean_temperature(void *); +void label_temperature(char **labels, void *); diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..5ff3acd --- /dev/null +++ b/src/util.c @@ -0,0 +1,6 @@ +#include "util.h" + +inline uint64_t substractAcc(const uint64_t l, const uint64_t r) +{ + return (l < r) ? UINT64_MAX + (l - r) : l - r; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..83129d8 --- /dev/null +++ b/src/util.h @@ -0,0 +1,5 @@ +#pragma once + +#include <stdint.h> + +inline uint64_t substractAcc(const uint64_t l, const uint64_t r); \ No newline at end of file -- GitLab From a5bf8b3f3599f47005acb29b467ff050813b44c6 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 17 Jan 2023 21:25:18 +0100 Subject: [PATCH 032/125] build system (v0), add long options - mojitos now supports long options, via "optparse.h", written by wellons@nullprogram.com and released into the public domain - one can choose which captor to include or exclude in the final binary with `configure.sh`. - makefile is now POSIX compliant (or at least, should be). - one now have to fill in the "struct optparse_long" and "struct captor" structs when adding a new captor. - defined a hard limit to the numbers of fixed options (10), and to the amount of captors (20). These can be changed by modifying NB_MAX_OPTS and NB_MAX_CAPTORS, respectively. - mojitos now includes "captors.h", generated by the `configure.sh` script - changed the signature of `add_source()` to: void add_source(struct captor*, char*) - `main()` now must call the `init_captors()` function. --- .gitignore | 1 + configure.sh | 65 ++++++++ makefile | 22 +-- src/counters.h | 12 ++ src/infiniband.h | 10 ++ src/load.h | 10 ++ src/mojitos.c | 143 +++++++++-------- src/network.h | 10 ++ src/optparse.h | 389 ++++++++++++++++++++++++++++++++++++++++++++++ src/rapl.h | 10 ++ src/temperature.h | 10 ++ 11 files changed, 606 insertions(+), 76 deletions(-) create mode 100755 configure.sh create mode 100644 src/optparse.h diff --git a/.gitignore b/.gitignore index f5893ce..16bccfb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o src/counters_option.h +src/captors.h bin obj diff --git a/configure.sh b/configure.sh new file mode 100755 index 0000000..746f129 --- /dev/null +++ b/configure.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +try() { "$@" || die "cannot $*"; } +die() { yell "$*"; exit 111; } +yell() { echo "$0: $*" >&2; } +echo() { printf '%s\n' "$*"; } + +target=src/captors.h +hdr_blacklist='counters_option|optparse|captors' + +usage() { + printf -- 'Usage: %s [-l] [-e <captor>] [-i <captor>]\n' "$(basename "$0")" >&2 + printf -- '-e | --exclude : exclude captor, can be called multiple times\n' >&2 + printf -- '-i | --include : include captor, can be called multiple times\n' >&2 + printf -- '-l | --list-captors : list all captors and exit\n' >&2 + exit 1 +} + +ls_captors() { + try cd src + ls *.h | grep -vE "($hdr_blacklist)" | sed 's/\.h$//' +} + +gen_captors_h() { + captors=$(ls_captors) + + [ -n "$captors" ] || return + + # gen includes + for captor in $captors; do + printf '#include "%s.h"\n' "$captor" + done + printf '\n' + + # gen `init_captors()` + printf 'void init_captors()\n{\n' + for captor in $captors; do + printf ' longopts[NB_MAX_OPTS + nb_defined_captors] = %s_opt;\n' "$captor" + printf ' captors[nb_defined_captors++] = %s;\n' "$captor" + done + printf '}\n' +} + +while [ "$1" ]; do + case $1 in + --include|-i) + # no-op for now + : + ;; + --exclude|-e) + shift; [ "$1" ] || usage + hdr_blacklist="${hdr_blacklist}|${1}" + ;; + --list-captors|-l) + ls_captors + exit 0 + ;; + --help|-h) + usage + ;; + esac + shift +done + +gen_captors_h > "$target" diff --git a/makefile b/makefile index 488f39c..fe9035a 100644 --- a/makefile +++ b/makefile @@ -6,17 +6,17 @@ BIN_DIR = bin BIN = mojitos -OBJ = $(addprefix $(OBJ_DIR)/, \ - counters.o \ - rapl.o \ - network.o \ - load.o \ - infiniband.o \ - temperature.o \ -) +OBJ = \ + $(OBJ_DIR)/counters.o \ + $(OBJ_DIR)/rapl.o \ + $(OBJ_DIR)/network.o \ + $(OBJ_DIR)/load.o \ + $(OBJ_DIR)/infiniband.o \ + $(OBJ_DIR)/temperature.o CC = gcc -CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function +CPPFLAGS = -std=gnu99 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function +CFLAGS = $(CPPFLAGS) -O3 LDFLAGS = -lpowercap ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q @@ -45,11 +45,11 @@ $(OBJ_DIR): $(BIN_DIR): mkdir -p $(BIN_DIR) -debug: CFLAGS += -DDEBUG -g +debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og debug: all format: - $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h + $(ASTYLE) $(SRC_DIR)/*.[ch] clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* diff --git a/src/counters.h b/src/counters.h index af20717..313feeb 100644 --- a/src/counters.h +++ b/src/counters.h @@ -23,4 +23,16 @@ unsigned int get_counters(uint64_t *results, void *); void clean_counters(void *); void label_counters(char **labels, void *); +struct optparse_long counters_opt = {"perf-list", 'p', OPTPARSE_REQUIRED}; +struct captor counters = { + .usage_arg = "<perf_list>", + .usage_msg = "performance counters\n" + "\tperf_list is a coma separated list of performance counters.\n" + "\tEx: instructions,cache_misses", + .init = init_counters, + .get = get_counters, + .clean = clean_counters, + .label = label_counters, +}; + void show_all_counters(); diff --git a/src/infiniband.h b/src/infiniband.h index 1f6aaf9..0f1ad11 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -20,3 +20,13 @@ unsigned int init_infiniband(char *infi_path, void **ptr); void label_infiniband(char **labels, void *); + +struct optparse_long infiniband_opt = {"monitor-infiniband", 'i', OPTPARSE_REQUIRED}; +struct captor infiniband = { + .usage_arg = "<infiniband_path>", + .usage_msg = "infiniband monitoring (if infiniband_path is X, tries to detect it automatically)", + .init = init_infiniband, + .get = NULL, + .clean = NULL, + .label = label_infiniband, +}; diff --git a/src/load.h b/src/load.h index 299fa3e..366e448 100644 --- a/src/load.h +++ b/src/load.h @@ -22,3 +22,13 @@ unsigned int init_load(char *, void **); unsigned int get_load(uint64_t *results, void *); void clean_load(void *); void label_load(char **labels, void *); + +struct optparse_long load_opt = {"sysload", 'u', OPTPARSE_NONE}; +struct captor load = { + .usage_arg = NULL, + .usage_msg = "system load", + .init = init_load, + .get = get_load, + .clean = clean_load, + .label = label_load, +}; diff --git a/src/mojitos.c b/src/mojitos.c index cd8fcad..55af9f5 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -26,12 +26,8 @@ #include <time.h> #include <unistd.h> -#include "counters.h" -#include "rapl.h" -#include "infiniband.h" -#include "load.h" -#include "network.h" -#include "temperature.h" +#define NB_MAX_OPTS 10 +#define NB_MAX_CAPTORS 20 #define OPTPARSE_IMPLEMENTATION #define OPTPARSE_API static @@ -46,23 +42,62 @@ exit(code); \ } while (0) +typedef unsigned int (*initializer_t)(char *, void **); +typedef void (*labeler_t)(char **, void *); +typedef unsigned int (*getter_t)(uint64_t *, void *); +typedef void (*cleaner_t)(void *); + +struct captor { + char *usage_arg; + char *usage_msg; + initializer_t init; + getter_t get; + cleaner_t clean; + labeler_t label; +}; + +struct captor captors[NB_MAX_CAPTORS]; + +struct optparse_long longopts[NB_MAX_OPTS + NB_MAX_CAPTORS] = { + {"overhead-stats", 's', OPTPARSE_NONE}, + {"list", 'l', OPTPARSE_NONE}, + {"freq", 'f', OPTPARSE_REQUIRED}, + {"time", 't', OPTPARSE_REQUIRED}, + {"exec", 'e', OPTPARSE_REQUIRED}, + {"logfile", 'o', OPTPARSE_REQUIRED}, +}; + +int nb_defined_captors = 0; + +#include "captors.h" void usage(char **argv) { - printf("Usage : %s [-rlucs] [-t time] [-f freq] [-p perf_list] [-d network_device]\n" - " [-i infiniband_path] [-o logfile] [-e command arguments...]\n" + printf("Usage : %s [OPTIONS] [CAPTOR ...] [-o logfile] [-e cmd ...]\n" + "\nOPTIONS:\n" + "-t <time>\n" + "-f <freq>\n" + "-l\t\tlist the possible performance counters and quit\n" + "-s\t\tenable overhead statistics in nanoseconds\n" "if time==0 then loops infinitively\n" "if -e is present, time and freq are not used\n" - "-r activates RAPL\n" - "-p activates performance counters\n" - " perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n" - "-l lists the possible performance counters and quits\n" - "-d activates network monitoring (if network_device is X, tries to detect it automatically)\n" - "-i activates infiniband monitoring (if infiniband_path is X, tries to detect it automatically)\n" - "-s activates statistics of overhead in nanoseconds\n" - "-u activates report of system load\n" - "-c activates report of processor temperature\n" , argv[0]); + + if (nb_defined_captors == 0) { + // no captor to show + exit(EXIT_FAILURE); + } + + printf("\nCAPTORS:\n"); + + for (int i = 0; i < nb_defined_captors; i++) { + printf("-%c", longopts[NB_MAX_OPTS + i].shortname); + if (captors[i].usage_arg != NULL) { + printf(" %s", captors[i].usage_arg); + } + printf("\n\t%s\n", captors[i].usage_msg); + } + exit(EXIT_FAILURE); } @@ -86,11 +121,6 @@ void flushexit() } } -typedef unsigned int (initializer_t)(char *, void **); -typedef void (labeler_t)(char **, void *); -typedef unsigned int (*getter_t)(uint64_t *, void *); -typedef void (*cleaner_t)(void *); - unsigned int nb_sources = 0; void **states = NULL; getter_t *getter = NULL; @@ -100,10 +130,14 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void add_source(initializer_t init, char *arg, labeler_t labeler, - getter_t get, cleaner_t clean) +void add_source(struct captor *cpt, char *arg) { nb_sources++; + initializer_t init = cpt->init; + labeler_t labeler = cpt->label; + getter_t get = cpt->get; + cleaner_t clean = cpt->clean; + states = realloc(states, nb_sources * sizeof(void *)); int nb = init(arg, &states[nb_sources - 1]); @@ -131,9 +165,10 @@ int main(int argc, char **argv) int delta = 0; int frequency = 1; char **application = NULL; - int stat_mode = -1; + init_captors(); + if (argc == 1) { usage(argv); } @@ -146,20 +181,6 @@ int main(int argc, char **argv) int opt; struct optparse options; options.permute = 0; - struct optparse_long longopts[] = { - {"monitor-infiniband", 'i', OPTPARSE_REQUIRED}, - {"freq", 'f', OPTPARSE_REQUIRED}, - {"time", 't', OPTPARSE_REQUIRED}, - {"net-dev", 'd', OPTPARSE_REQUIRED}, - {"exec", 'e', OPTPARSE_REQUIRED}, - {"logfile", 'o', OPTPARSE_REQUIRED}, - {"perf-list", 'p', OPTPARSE_REQUIRED}, - {"cpu-temp", 'c', OPTPARSE_NONE}, - {"rapl", 'r', OPTPARSE_NONE}, - {"overhead-stats", 's', OPTPARSE_NONE}, - {"sysload", 'u', OPTPARSE_NONE}, - {"list", 'l', OPTPARSE_NONE}, - }; optparse_init(&options, argv); while ((opt = optparse_long(&options, longopts, NULL)) != -1 && application == NULL) { @@ -175,12 +196,12 @@ int main(int argc, char **argv) delta = 0; } break; - case 'd': - add_source(init_network, options.optarg, label_network, get_network, clean_network); - break; - case 'i': - add_source(init_infiniband, options.optarg, label_infiniband, get_network, clean_network); + case 's': + stat_mode = 0; break; + case 'l': + show_all_counters(); + exit(EXIT_SUCCESS); case 'o': if ((output = fopen(options.optarg, "wb")) == NULL) { perror("fopen"); @@ -191,27 +212,19 @@ int main(int argc, char **argv) application = options.argv; signal(17, sighandler); break; - case 'p': - add_source(init_counters, options.optarg, label_counters, get_counters, clean_counters); - break; - case 'r': - add_source(init_rapl, NULL, label_rapl, get_rapl, clean_rapl); - break; - case 'u': - add_source(init_load, NULL, label_load, get_load, clean_load); - break; - case 'c': - add_source(init_temperature, NULL, label_temperature, get_temperature, clean_temperature); - break; - case 's': - stat_mode = 0; - break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); - default: - fprintf(stderr, "%s: %s\n", argv[0], options.errmsg); - usage(argv); + default: { + int ismatch = 0; + for (int i = 0; i < nb_defined_captors && !ismatch; i++) { + if (opt == longopts[NB_MAX_OPTS + i].shortname) { + ismatch = 1; + add_source(&captors[i], options.optarg); + } + } + if (!ismatch) { + fprintf(stderr, "%s: %s\n", argv[0], options.errmsg); + usage(argv); + } + } } } diff --git a/src/network.h b/src/network.h index 3ba9ae5..3182587 100644 --- a/src/network.h +++ b/src/network.h @@ -23,3 +23,13 @@ unsigned int get_network(uint64_t *results, void *); void clean_network(void *); void label_network(char **labels, void *); +struct optparse_long network_opt = {"net-dev", 'd', OPTPARSE_REQUIRED}; +struct captor network = { + .usage_arg = "<net_dev>", + .usage_msg = "network monitoring (if network_device is X, tries to detect it automatically)", + .init = init_network, + .get = get_network, + .clean = clean_network, + .label = label_network, +}; + diff --git a/src/optparse.h b/src/optparse.h new file mode 100644 index 0000000..04e60f6 --- /dev/null +++ b/src/optparse.h @@ -0,0 +1,389 @@ +/* Optparse --- portable, reentrant, embeddable, getopt-like option parser + * + * This is free and unencumbered software released into the public domain. + * + * To get the implementation, define OPTPARSE_IMPLEMENTATION. + * Optionally define OPTPARSE_API to control the API's visibility + * and/or linkage (static, __attribute__, __declspec). + * + * The POSIX getopt() option parser has three fatal flaws. These flaws + * are solved by Optparse. + * + * 1) Parser state is stored entirely in global variables, some of + * which are static and inaccessible. This means only one thread can + * use getopt(). It also means it's not possible to recursively parse + * nested sub-arguments while in the middle of argument parsing. + * Optparse fixes this by storing all state on a local struct. + * + * 2) The POSIX standard provides no way to properly reset the parser. + * This means for portable code that getopt() is only good for one + * run, over one argv with one option string. It also means subcommand + * options cannot be processed with getopt(). Most implementations + * provide a method to reset the parser, but it's not portable. + * Optparse provides an optparse_arg() function for stepping over + * subcommands and continuing parsing of options with another option + * string. The Optparse struct itself can be passed around to + * subcommand handlers for additional subcommand option parsing. A + * full reset can be achieved by with an additional optparse_init(). + * + * 3) Error messages are printed to stderr. This can be disabled with + * opterr, but the messages themselves are still inaccessible. + * Optparse solves this by writing an error message in its errmsg + * field. The downside to Optparse is that this error message will + * always be in English rather than the current locale. + * + * Optparse should be familiar with anyone accustomed to getopt(), and + * it could be a nearly drop-in replacement. The option string is the + * same and the fields have the same names as the getopt() global + * variables (optarg, optind, optopt). + * + * Optparse also supports GNU-style long options with optparse_long(). + * The interface is slightly different and simpler than getopt_long(). + * + * By default, argv is permuted as it is parsed, moving non-option + * arguments to the end. This can be disabled by setting the `permute` + * field to 0 after initialization. + */ +#ifndef OPTPARSE_H +#define OPTPARSE_H + +#ifndef OPTPARSE_API +# define OPTPARSE_API +#endif + +struct optparse { + char **argv; + int permute; + int optind; + int optopt; + char *optarg; + char errmsg[64]; + int subopt; +}; + +enum optparse_argtype { + OPTPARSE_NONE, + OPTPARSE_REQUIRED, + OPTPARSE_OPTIONAL +}; + +struct optparse_long { + const char *longname; + int shortname; + enum optparse_argtype argtype; +}; + +/** + * Initializes the parser state. + */ +OPTPARSE_API +void optparse_init(struct optparse *options, char **argv); + +/** + * Read the next option in the argv array. + * @param optstring a getopt()-formatted option string. + * @return the next option character, -1 for done, or '?' for error + * + * Just like getopt(), a character followed by no colons means no + * argument. One colon means the option has a required argument. Two + * colons means the option takes an optional argument. + */ +OPTPARSE_API +int optparse(struct optparse *options, const char *optstring); + +/** + * Handles GNU-style long options in addition to getopt() options. + * This works a lot like GNU's getopt_long(). The last option in + * longopts must be all zeros, marking the end of the array. The + * longindex argument may be NULL. + */ +OPTPARSE_API +int optparse_long(struct optparse *options, + const struct optparse_long *longopts, + int *longindex); + +/** + * Used for stepping over non-option arguments. + * @return the next non-option argument, or NULL for no more arguments + * + * Argument parsing can continue with optparse() after using this + * function. That would be used to parse the options for the + * subcommand returned by optparse_arg(). This function allows you to + * ignore the value of optind. + */ +OPTPARSE_API +char *optparse_arg(struct optparse *options); + +/* Implementation */ +#ifdef OPTPARSE_IMPLEMENTATION + +#define OPTPARSE_MSG_INVALID "invalid option" +#define OPTPARSE_MSG_MISSING "option requires an argument" +#define OPTPARSE_MSG_TOOMANY "option takes no arguments" + +static int optparse_error(struct optparse *options, const char *msg, const char *data) +{ + unsigned p = 0; + const char *sep = " -- '"; + while (*msg) + options->errmsg[p++] = *msg++; + while (*sep) + options->errmsg[p++] = *sep++; + while (p < sizeof(options->errmsg) - 2 && *data) + options->errmsg[p++] = *data++; + options->errmsg[p++] = '\''; + options->errmsg[p++] = '\0'; + return '?'; +} + +OPTPARSE_API +void optparse_init(struct optparse *options, char **argv) +{ + options->argv = argv; + options->permute = 1; + options->optind = argv[0] != 0; + options->subopt = 0; + options->optarg = 0; + options->errmsg[0] = '\0'; +} + +static int optparse_is_dashdash(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0'; +} + +static int optparse_is_shortopt(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0'; +} + +static int optparse_is_longopt(const char *arg) +{ + return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0'; +} + +static void optparse_permute(struct optparse *options, int index) +{ + char *nonoption = options->argv[index]; + int i; + for (i = index; i < options->optind - 1; i++) + options->argv[i] = options->argv[i + 1]; + options->argv[options->optind - 1] = nonoption; +} + +static int optparse_argtype(const char *optstring, char c) +{ + int count = OPTPARSE_NONE; + if (c == ':') + return -1; + for (; *optstring && c != *optstring; optstring++); + if (!*optstring) + return -1; + if (optstring[1] == ':') + count += optstring[2] == ':' ? 2 : 1; + return count; +} + +OPTPARSE_API +int optparse(struct optparse *options, const char *optstring) +{ + int type; + char *next; + char *option = options->argv[options->optind]; + options->errmsg[0] = '\0'; + options->optopt = 0; + options->optarg = 0; + if (option == 0) { + return -1; + } else if (optparse_is_dashdash(option)) { + options->optind++; /* consume "--" */ + return -1; + } else if (!optparse_is_shortopt(option)) { + if (options->permute) { + int index = options->optind++; + int r = optparse(options, optstring); + optparse_permute(options, index); + options->optind--; + return r; + } else { + return -1; + } + } + option += options->subopt + 1; + options->optopt = option[0]; + type = optparse_argtype(optstring, option[0]); + next = options->argv[options->optind + 1]; + switch (type) { + case -1: { + char str[2] = {0, 0}; + str[0] = option[0]; + options->optind++; + return optparse_error(options, OPTPARSE_MSG_INVALID, str); + } + case OPTPARSE_NONE: + if (option[1]) { + options->subopt++; + } else { + options->subopt = 0; + options->optind++; + } + return option[0]; + case OPTPARSE_REQUIRED: + options->subopt = 0; + options->optind++; + if (option[1]) { + options->optarg = option + 1; + } else if (next != 0) { + options->optarg = next; + options->optind++; + } else { + char str[2] = {0, 0}; + str[0] = option[0]; + options->optarg = 0; + return optparse_error(options, OPTPARSE_MSG_MISSING, str); + } + return option[0]; + case OPTPARSE_OPTIONAL: + options->subopt = 0; + options->optind++; + if (option[1]) + options->optarg = option + 1; + else + options->optarg = 0; + return option[0]; + } + return 0; +} + +OPTPARSE_API +char *optparse_arg(struct optparse *options) +{ + char *option = options->argv[options->optind]; + options->subopt = 0; + if (option != 0) + options->optind++; + return option; +} + +static int optparse_longopts_end(const struct optparse_long *longopts, int i) +{ + return !longopts[i].longname && !longopts[i].shortname; +} + +static void optparse_from_long(const struct optparse_long *longopts, char *optstring) +{ + char *p = optstring; + int i; + for (i = 0; !optparse_longopts_end(longopts, i); i++) { + if (longopts[i].shortname && longopts[i].shortname < 127) { + int a; + *p++ = longopts[i].shortname; + for (a = 0; a < (int)longopts[i].argtype; a++) + *p++ = ':'; + } + } + *p = '\0'; +} + +/* Unlike strcmp(), handles options containing "=". */ +static int optparse_longopts_match(const char *longname, const char *option) +{ + const char *a = option, *n = longname; + if (longname == 0) + return 0; + for (; *a && *n && *a != '='; a++, n++) + if (*a != *n) + return 0; + return *n == '\0' && (*a == '\0' || *a == '='); +} + +/* Return the part after "=", or NULL. */ +static char *optparse_longopts_arg(char *option) +{ + for (; *option && *option != '='; option++); + if (*option == '=') + return option + 1; + else + return 0; +} + +static int optparse_long_fallback(struct optparse *options, + const struct optparse_long *longopts, + int *longindex) +{ + int result; + char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */ + optparse_from_long(longopts, optstring); + result = optparse(options, optstring); + if (longindex != 0) { + *longindex = -1; + if (result != -1) { + int i; + for (i = 0; !optparse_longopts_end(longopts, i); i++) + if (longopts[i].shortname == options->optopt) + *longindex = i; + } + } + return result; +} + +OPTPARSE_API +int optparse_long(struct optparse *options, + const struct optparse_long *longopts, + int *longindex) +{ + int i; + char *option = options->argv[options->optind]; + if (option == 0) { + return -1; + } else if (optparse_is_dashdash(option)) { + options->optind++; /* consume "--" */ + return -1; + } else if (optparse_is_shortopt(option)) { + return optparse_long_fallback(options, longopts, longindex); + } else if (!optparse_is_longopt(option)) { + if (options->permute) { + int index = options->optind++; + int r = optparse_long(options, longopts, longindex); + optparse_permute(options, index); + options->optind--; + return r; + } else { + return -1; + } + } + + /* Parse as long option. */ + options->errmsg[0] = '\0'; + options->optopt = 0; + options->optarg = 0; + option += 2; /* skip "--" */ + options->optind++; + for (i = 0; !optparse_longopts_end(longopts, i); i++) { + const char *name = longopts[i].longname; + if (optparse_longopts_match(name, option)) { + char *arg; + if (longindex) + *longindex = i; + options->optopt = longopts[i].shortname; + arg = optparse_longopts_arg(option); + if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) { + return optparse_error(options, OPTPARSE_MSG_TOOMANY, name); + } + if (arg != 0) { + options->optarg = arg; + } else if (longopts[i].argtype == OPTPARSE_REQUIRED) { + options->optarg = options->argv[options->optind]; + if (options->optarg == 0) + return optparse_error(options, OPTPARSE_MSG_MISSING, name); + else + options->optind++; + } + return options->optopt; + } + } + return optparse_error(options, OPTPARSE_MSG_INVALID, option); +} + +#endif /* OPTPARSE_IMPLEMENTATION */ +#endif /* OPTPARSE_H */ diff --git a/src/rapl.h b/src/rapl.h index ddce4cc..b8dc9a2 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -23,3 +23,13 @@ unsigned int get_rapl(uint64_t *results, void *); void clean_rapl(void *); void label_rapl(char **labels, void *); +struct optparse_long rapl_opt = {"rapl", 'r', OPTPARSE_NONE}; +struct captor rapl = { + .usage_arg = NULL, + .usage_msg = "RAPL", + .init = init_rapl, + .get = get_rapl, + .clean = clean_rapl, + .label = label_rapl, +}; + diff --git a/src/temperature.h b/src/temperature.h index e49e416..5e8046e 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -22,3 +22,13 @@ unsigned int init_temperature(char *, void **); unsigned int get_temperature(uint64_t *results, void *); void clean_temperature(void *); void label_temperature(char **labels, void *); + +struct optparse_long temperature_opt = {"cpu-temp", 'c', OPTPARSE_NONE}; +struct captor temperature = { + .usage_arg = NULL, + .usage_msg = "processor temperature", + .init = init_temperature, + .get = get_temperature, + .clean = clean_temperature, + .label = label_temperature, +}; -- GitLab From e46c8918d197e361cb02453280eb5dbaf33d0e64 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 18 Jan 2023 09:57:04 +0000 Subject: [PATCH 033/125] remove Werror in debug mode --- makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index fe9035a..7024207 100644 --- a/makefile +++ b/makefile @@ -15,8 +15,8 @@ OBJ = \ $(OBJ_DIR)/temperature.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function -CFLAGS = $(CPPFLAGS) -O3 +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function +CFLAGS = $(CPPFLAGS) -O3 -Werror LDFLAGS = -lpowercap ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -- GitLab From bd90c66a14e041843d0ebdd8d265b48a994f69b1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 21 Jan 2023 12:53:44 +0000 Subject: [PATCH 034/125] fix: dos2unix --- src/counters.h | 52 ++++++++--------- src/counters_option.py | 124 ++++++++++++++++++++--------------------- src/infiniband.h | 44 +++++++-------- src/load.h | 48 ++++++++-------- src/network.h | 50 ++++++++--------- src/temperature.h | 48 ++++++++-------- src/util.h | 8 +-- 7 files changed, 187 insertions(+), 187 deletions(-) diff --git a/src/counters.h b/src/counters.h index bd2d0a5..af20717 100644 --- a/src/counters.h +++ b/src/counters.h @@ -1,26 +1,26 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_counters(char *, void **); -unsigned int get_counters(uint64_t *results, void *); -void clean_counters(void *); -void label_counters(char **labels, void *); - -void show_all_counters(); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_counters(char *, void **); +unsigned int get_counters(uint64_t *results, void *); +void clean_counters(void *); +void label_counters(char **labels, void *); + +void show_all_counters(); diff --git a/src/counters_option.py b/src/counters_option.py index d853e41..877a33a 100755 --- a/src/counters_option.py +++ b/src/counters_option.py @@ -1,62 +1,62 @@ -#! /usr/bin/python3 - -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - -linux_include = '/usr/include/linux/perf_event.h' - -string = """#include <linux/perf_event.h> - -typedef struct counter_option { - char *name; - __u32 perf_type; - __u64 perf_key; -} counter_option; - -static counter_option perf_static_info[] = {""" -print(string) - -nb = 0 - -black_list = ['stalled_cycles_frontend','stalled_cycles_backend', - 'cache_l1i', 'cache_op_write', 'cache_result_miss'] - -with open(linux_include, 'r') as infile: - mode = '' - for line in infile: - if 'perf_hw_id' in line: - mode = 'PERF_TYPE_HARDWARE' - elif 'perf_hw_cache_' in line: - mode = 'PERF_TYPE_HW_CACHE' - elif 'perf_sw_id' in line: - mode = 'PERF_TYPE_SOFTWARE' - elif 'PERF_COUNT_' in line and '=' in line: - perf_name = line.split()[0] - short_perf = perf_name[14:].lower() - if short_perf in black_list: - continue - if mode == 'PERF_TYPE_HW_CACHE': - for op_id, op_id_str in enumerate(['r', 'w', 'p']): - op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] - for result_id, result_id_str in enumerate(['a', 'm']): - result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] - - res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( - short_perf, op_id_str, result_id_str, - mode, - perf_name, - op_id_names[op_id], - result_id_names[result_id]) - - print(res) - nb += 1 - - else: - res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' - print(res) - nb += 1 - - -print('};') - -print('static unsigned int nb_counter_option =',nb,';') +#! /usr/bin/python3 + +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + +linux_include = '/usr/include/linux/perf_event.h' + +string = """#include <linux/perf_event.h> + +typedef struct counter_option { + char *name; + __u32 perf_type; + __u64 perf_key; +} counter_option; + +static counter_option perf_static_info[] = {""" +print(string) + +nb = 0 + +black_list = ['stalled_cycles_frontend','stalled_cycles_backend', + 'cache_l1i', 'cache_op_write', 'cache_result_miss'] + +with open(linux_include, 'r') as infile: + mode = '' + for line in infile: + if 'perf_hw_id' in line: + mode = 'PERF_TYPE_HARDWARE' + elif 'perf_hw_cache_' in line: + mode = 'PERF_TYPE_HW_CACHE' + elif 'perf_sw_id' in line: + mode = 'PERF_TYPE_SOFTWARE' + elif 'PERF_COUNT_' in line and '=' in line: + perf_name = line.split()[0] + short_perf = perf_name[14:].lower() + if short_perf in black_list: + continue + if mode == 'PERF_TYPE_HW_CACHE': + for op_id, op_id_str in enumerate(['r', 'w', 'p']): + op_id_names = ['PERF_COUNT_HW_CACHE_OP_READ', 'PERF_COUNT_HW_CACHE_OP_WRITE', 'PERF_COUNT_HW_CACHE_OP_PREFETCH'] + for result_id, result_id_str in enumerate(['a', 'm']): + result_id_names = ['PERF_COUNT_HW_CACHE_RESULT_ACCESS', 'PERF_COUNT_HW_CACHE_RESULT_MISS'] + + res = '{ .name = "%s_%s_%s", .perf_type = %s, .perf_key = %s | (%s >> 8) | (%s >> 16) },' % ( + short_perf, op_id_str, result_id_str, + mode, + perf_name, + op_id_names[op_id], + result_id_names[result_id]) + + print(res) + nb += 1 + + else: + res = '{ .name = "'+short_perf+'", .perf_type = '+mode+', .perf_key = '+perf_name+'},' + print(res) + nb += 1 + + +print('};') + +print('static unsigned int nb_counter_option =',nb,';') diff --git a/src/infiniband.h b/src/infiniband.h index 4234964..1f6aaf9 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -1,22 +1,22 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_infiniband(char *infi_path, void **ptr); -void label_infiniband(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_infiniband(char *infi_path, void **ptr); +void label_infiniband(char **labels, void *); diff --git a/src/load.h b/src/load.h index 78c1b40..299fa3e 100644 --- a/src/load.h +++ b/src/load.h @@ -1,24 +1,24 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_load(char *, void **); -unsigned int get_load(uint64_t *results, void *); -void clean_load(void *); -void label_load(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_load(char *, void **); +unsigned int get_load(uint64_t *results, void *); +void clean_load(void *); +void label_load(char **labels, void *); diff --git a/src/network.h b/src/network.h index b770560..3ba9ae5 100644 --- a/src/network.h +++ b/src/network.h @@ -1,25 +1,25 @@ -/******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_network(char *, void **); -unsigned int get_network(uint64_t *results, void *); -void clean_network(void *); -void label_network(char **labels, void *); - +/******************************************************* + Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_network(char *, void **); +unsigned int get_network(uint64_t *results, void *); +void clean_network(void *); +void label_network(char **labels, void *); + diff --git a/src/temperature.h b/src/temperature.h index ac8e34b..e49e416 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -1,24 +1,24 @@ -/******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_temperature(char *, void **); -unsigned int get_temperature(uint64_t *results, void *); -void clean_temperature(void *); -void label_temperature(char **labels, void *); +/******************************************************* + Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_temperature(char *, void **); +unsigned int get_temperature(uint64_t *results, void *); +void clean_temperature(void *); +void label_temperature(char **labels, void *); diff --git a/src/util.h b/src/util.h index 83129d8..9a4067d 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,5 @@ -#pragma once - -#include <stdint.h> - +#pragma once + +#include <stdint.h> + inline uint64_t substractAcc(const uint64_t l, const uint64_t r); \ No newline at end of file -- GitLab From 652c34e2124544136be39c1bcc2f0940ef37cc41 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 21 Jan 2023 13:02:50 +0000 Subject: [PATCH 035/125] fix: std once style --- src/util.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/util.h b/src/util.h index 9a4067d..1fff9af 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,10 @@ -#pragma once +#ifndef _UTIL_H +#define _UTIL_H + +//#warning "TODO: Add licence" #include <stdint.h> -inline uint64_t substractAcc(const uint64_t l, const uint64_t r); \ No newline at end of file +inline uint64_t substractAcc(const uint64_t l, const uint64_t r); + +#endif -- GitLab From ac422f8cf06164f6ad861863e153ddfd13975597 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 21 Jan 2023 13:11:28 +0000 Subject: [PATCH 036/125] fix: Usage mojitos.c -R was deleted. --- src/mojitos.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mojitos.c b/src/mojitos.c index b6c057f..ccde606 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -50,7 +50,6 @@ void usage(char **argv) "if time==0 then loops infinitively\n" "if -e is present, time and freq are not used\n" "-r activates RAPL\n" - "-R activates the file version of RAPL\n" "-p activates performance counters\n" " perf_list is coma separated list of performance counters without space. Ex: instructions,cache_misses\n" "-l lists the possible performance counters and quits\n" -- GitLab From 6e6aa01c6a4af52722905c6e7237f96027981114 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 21 Jan 2023 16:26:44 +0000 Subject: [PATCH 037/125] test reader --- src/info_reader.c | 73 +++++++++++++++++++++++++++++ src/info_reader.h | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 src/info_reader.c create mode 100644 src/info_reader.h diff --git a/src/info_reader.c b/src/info_reader.c new file mode 100644 index 0000000..d33654b --- /dev/null +++ b/src/info_reader.c @@ -0,0 +1,73 @@ +#include "info_reader.h" + +#define MAX_PROCS 128 + +typedef struct { + int processor; + char *vendor_id; + int family; + int core_id; + int physical_id; + char *model_name; +} Cpu; + +int int_allocator(char *s) { + int value = atoi(s); + return value; +} + +char *string_allocator(char *s) { + char *value = malloc(strlen(s) + 1); + strcpy(value, s); + return value; +} + +void set_processor(Cpu *cpu, int data) { cpu->processor = (int)data; } + +void set_vendor_id(Cpu *cpu, char *data) { cpu->vendor_id = data; } + +void set_family(Cpu *cpu, int data) { cpu->family = (int)data; } + +void set_core_id(Cpu *cpu, int data) { cpu->core_id = (int)data; } + +void set_physical_id(Cpu *cpu, int data) { cpu->physical_id = (int)data; } + +void set_model_name(Cpu *cpu, char *data) { cpu->model_name = data; } + +int main(int argc, char const *argv[]) { + Cpu cpus[MAX_PROCS]; + + KeyFinder keys[] = { + {"processor", (CopyAllocator *)int_allocator, (Setter *)set_processor}, + {"vendor_id", (CopyAllocator *)string_allocator, (Setter *)set_vendor_id}, + {"cpu family", (CopyAllocator *)int_allocator, (Setter *)set_family}, + {"core id", (CopyAllocator *)int_allocator, (Setter *)set_core_id}, + {"physical id", (CopyAllocator *)int_allocator, + (Setter *)set_physical_id}, + {"model name", (CopyAllocator *)string_allocator, + (Setter *)set_model_name}}; + + Parser parser = {.storage = (void **)cpus, + .capacity = MAX_PROCS, + .storage_struct_size = sizeof(Cpu), + .keys = keys, + .nb_keys = 6, + .file = fopen("/proc/cpuinfo", "r")}; + + parse(&parser); + + for (unsigned int i = 0; i < parser.nb_stored; ++i) { + printf("========== PROC[%d] ==========\n", i); + printf("Processor: %d\n", cpus[i].processor); + printf("Vendor ID: %s\n", cpus[i].vendor_id); + printf("Family: %d\n", cpus[i].family); + printf("Core ID: %d\n", cpus[i].core_id); + printf("Physical ID: %d\n", cpus[i].physical_id); + printf("Model Name: %s\n", cpus[i].model_name); + printf("==============================\n"); + free(cpus[i].vendor_id); + free(cpus[i].model_name); + } + return 0; +} + diff --git a/src/info_reader.h b/src/info_reader.h new file mode 100644 index 0000000..e0f230b --- /dev/null +++ b/src/info_reader.h @@ -0,0 +1,114 @@ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef _INFO_READER_H +#define _INFO_READER_H + +typedef struct Parser Parser; +typedef struct KeyFinder KeyFinder; + +// Transforme the string in the expected format +typedef void *(CopyAllocator)(char *string); +// Set the value into the memory +typedef void(Setter)(void *storage, void *value); + +struct KeyFinder { + char *key; + // Functions + CopyAllocator *copy; + Setter *set; +}; + +struct Parser { + void *storage; + unsigned int nb_stored; + unsigned int capacity; + size_t storage_struct_size; + + KeyFinder *keys; + unsigned int nb_keys; + + FILE *file; +}; + +char *get_string_value(char *line) { + char *start = line; + while (*start != '\0') { + if (*start == ':' && *(start + 1) == ' ') { + return (start + 2); + } + ++start; + } + return NULL; +} + +void replace_first(char *string, char find, char replace) { + char *found = strchr(string, find); + if (found) { + *found = replace; + } +} + +unsigned int start_with(const char *prefix, const char *string) { + size_t prefix_len = strlen(prefix); + size_t string_len = strlen(string); + return string_len < prefix_len ? false + : memcmp(prefix, string, prefix_len) == 0; +} + +int match(Parser *parser, char *line) { + for (size_t i = 0; i < parser->nb_keys; i++) { + KeyFinder *key_finder = &parser->keys[i]; + + if (start_with(key_finder->key, line)) { + char *string_value = get_string_value(line); + if (get_string_value == NULL) { + fprintf(stderr, "Error : invalid format for line : %s\n", line); + exit(EXIT_FAILURE); + } + replace_first(string_value, '\n', '\0'); + void *value = key_finder->copy(string_value); + + key_finder->set( + (parser->storage + (parser->storage_struct_size * parser->nb_stored)), + value); + + return 1; + } + } + return 0; +} + +void parse(Parser *parser) { + char *line = NULL; + size_t len = 0; + ssize_t read; + + unsigned int key_assigned = 0; + + while ((read = getline(&line, &len, parser->file)) != -1) { + if (key_assigned == parser->nb_keys && read > 1) { + continue; + } + if (read == 1) { + parser->nb_stored++; + if (parser->nb_stored == parser->capacity) { + fprintf(stderr, "Error : too much cpus to read.\n"); + exit(EXIT_FAILURE); + } + + key_assigned = 0; + } + key_assigned += match(parser, line); + } + + if (key_assigned > 0) { + parser->nb_stored++; + } + + free(line); +} + +#endif -- GitLab From 597829bb05779d7153fe1a102b2c1a5a055529f8 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 08:24:24 +0000 Subject: [PATCH 038/125] working library --- src/info_reader.c | 88 ++++---- src/info_reader.h | 536 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 518 insertions(+), 106 deletions(-) diff --git a/src/info_reader.c b/src/info_reader.c index d33654b..110d060 100644 --- a/src/info_reader.c +++ b/src/info_reader.c @@ -1,53 +1,68 @@ #include "info_reader.h" -#define MAX_PROCS 128 +#ifdef DEBUG + #warning "PTR_TO_TPTR hide a cast warning"aa +#endif +#define MAX_PROCS 128 typedef struct { - int processor; + size_t processor; char *vendor_id; - int family; - int core_id; - int physical_id; + size_t family; + size_t core_id; + size_t physical_id; char *model_name; } Cpu; -int int_allocator(char *s) { - int value = atoi(s); - return value; +GenericPointer int_allocator(char *s) { + size_t value = atoi(s); + return (GenericPointer) value; } -char *string_allocator(char *s) { +GenericPointer string_allocator(char *s) { char *value = malloc(strlen(s) + 1); strcpy(value, s); - return value; + return (GenericPointer) value; } -void set_processor(Cpu *cpu, int data) { cpu->processor = (int)data; } - -void set_vendor_id(Cpu *cpu, char *data) { cpu->vendor_id = data; } - -void set_family(Cpu *cpu, int data) { cpu->family = (int)data; } - -void set_core_id(Cpu *cpu, int data) { cpu->core_id = (int)data; } - -void set_physical_id(Cpu *cpu, int data) { cpu->physical_id = (int)data; } - -void set_model_name(Cpu *cpu, char *data) { cpu->model_name = data; } +void set_processor(GenericPointer storage, GenericPointer data) { + Cpu* cpu = (Cpu*) storage; + cpu->processor = data; +} +void set_vendor_id(GenericPointer storage, GenericPointer data) { + Cpu* cpu = (Cpu*) storage; + cpu->vendor_id = (char*) data; +} +void set_family(GenericPointer storage, GenericPointer data) { + Cpu* cpu = (Cpu*) storage; + cpu->family = data; +} +void set_core_id(GenericPointer storage, GenericPointer data) { + Cpu* cpu = (Cpu*) storage; + cpu->core_id = data; +} +void set_physical_id(GenericPointer storage, GenericPointer data) { + Cpu* cpu = (Cpu*) storage; + cpu->physical_id = data; +} +void set_model_name(GenericPointer storage, GenericPointer data) { + Cpu* cpu = (Cpu*) storage; + cpu->model_name = (char*) data; +} int main(int argc, char const *argv[]) { Cpu cpus[MAX_PROCS]; - KeyFinder keys[] = { - {"processor", (CopyAllocator *)int_allocator, (Setter *)set_processor}, - {"vendor_id", (CopyAllocator *)string_allocator, (Setter *)set_vendor_id}, - {"cpu family", (CopyAllocator *)int_allocator, (Setter *)set_family}, - {"core id", (CopyAllocator *)int_allocator, (Setter *)set_core_id}, - {"physical id", (CopyAllocator *)int_allocator, - (Setter *)set_physical_id}, - {"model name", (CopyAllocator *)string_allocator, - (Setter *)set_model_name}}; - - Parser parser = {.storage = (void **)cpus, + {"processor", ": ", (CopyAllocator *) int_allocator, (Setter *)set_processor}, + {"vendor_id", ": ", (CopyAllocator *) string_allocator, (Setter *)set_vendor_id}, + {"cpu family", ": ", (CopyAllocator *) int_allocator, (Setter *)set_family}, + {"core id", ": ", (CopyAllocator *) int_allocator, (Setter *)set_core_id}, + {"physical id", ": ", (CopyAllocator *) int_allocator,(Setter *)set_physical_id}, + {"model name", ": ", (CopyAllocator *) string_allocator, + (Setter *)set_model_name} + }; + + Parser parser = {.storage = (GenericPointer) cpus, .capacity = MAX_PROCS, .storage_struct_size = sizeof(Cpu), .keys = keys, @@ -58,16 +73,17 @@ int main(int argc, char const *argv[]) { for (unsigned int i = 0; i < parser.nb_stored; ++i) { printf("========== PROC[%d] ==========\n", i); - printf("Processor: %d\n", cpus[i].processor); + printf("Processor: %ld\n", cpus[i].processor); printf("Vendor ID: %s\n", cpus[i].vendor_id); - printf("Family: %d\n", cpus[i].family); - printf("Core ID: %d\n", cpus[i].core_id); - printf("Physical ID: %d\n", cpus[i].physical_id); + printf("Family: %ld\n", cpus[i].family); + printf("Core ID: %ld\n", cpus[i].core_id); + printf("Physical ID: %ld\n", cpus[i].physical_id); printf("Model Name: %s\n", cpus[i].model_name); printf("==============================\n"); free(cpus[i].vendor_id); free(cpus[i].model_name); } + return 0; } diff --git a/src/info_reader.h b/src/info_reader.h index e0f230b..030ea52 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -1,28 +1,104 @@ +#include <string.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> - -#ifndef _INFO_READER_H -#define _INFO_READER_H +/** + * @struct Parser + * @brief The parser struct + * The struct containing all the necessary informations and functions to parse a file + * + * @var storage : void* : pointer to the storage where the parsed data will be stored + * @var nb_stored : unsigned int : the number of struct stored + * @var capacity : unsigned int : the maximum number of struct that can be stored + * @var storage_struct_size : size_t : the size of the struct stored in the storage + * @var keys : KeyFinder* : pointer to an array of KeyFinder containing the possible keys + * @var nb_keys : unsigned int : number of key finders + * @var file : FILE* : pointer to the file that will be parsed +*/ typedef struct Parser Parser; + +/** + * @struct KeyFinder + * @brief The key finder struct + * The struct containing all the necessary informations and functions to find a key in a line of text + * + * @var key : char* : the key to be found + * @var delimiter : char* : the delimiter between the key and the value + * @var copy : CopyAllocator*: the function to use to make a copy of the value + * @var set : Setter*: the function to use to store the value in the storage +*/ typedef struct KeyFinder KeyFinder; -// Transforme the string in the expected format -typedef void *(CopyAllocator)(char *string); -// Set the value into the memory -typedef void(Setter)(void *storage, void *value); +/** + * @brief Split a string into a key and value based on a specified delimiter. + * + * The function takes a string and splits it into two parts: a key and a value. + * The parts are determined by a specified delimiter. + * The key and value are returned through output parameters. + * If the delimiter is not found in the input string, the key and value pointers + * will be set to NULL. + * + * @param[in] string The input string to be split, the string is modified. + * @param[in] delimiter The delimiter string. + * @param[out] key A pointer to a char pointer where the key will be stored. + * @param[out] value A pointer to a char pointer where the value will be stored. + * @return None. + */ +static void split_on_delimiter(char *string, const char *delimiter, char **key, char **value); + +/** + * @brief Replace the first occurrence of a character in a string with another character. + * + * The function takes a string and two characters as input, and replaces the first + * occurrence of the first character in the string with the second character. + * + * @param[in,out] string The input string where the replacement should take place. + * @param[in] from The character to be replaced. + * @param[in] to The character to replace with. + * @return None. + */ +static void replace_first(char* string, char from, char to); + +/** + * @brief Check if a string starts with a prefix. + * + * @param[in] prefix The prefix to check. + * @param[in] string The string to check. + * @return true The string starts with the prefix. + * @return false The string does not start with the prefix or one of the input pointers is NULL. + */ +static bool start_with(const char* prefix, const char* string); + +/** + * @brief Matches a line of text to a key in the parser's list of keys. + * + * @param parser Pointer to the Parser struct. + * @param line Line of text to match. + * @param key_finder Pointer to a KeyFinder pointer where the matched key will be stored. + * @param raw_value Pointer to a char pointer where the value associated with the matched key will be stored. + * + * @return Returns 1 if a key is matched, 0 otherwise. + */ +static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value); + + + + +typedef size_t GenericPointer; +typedef GenericPointer (CopyAllocator) (char *string); +typedef void (Setter) (GenericPointer storage, GenericPointer value); struct KeyFinder { char *key; - // Functions + char *delimiter; + CopyAllocator *copy; Setter *set; }; struct Parser { - void *storage; + GenericPointer storage; unsigned int nb_stored; unsigned int capacity; size_t storage_struct_size; @@ -33,82 +109,402 @@ struct Parser { FILE *file; }; -char *get_string_value(char *line) { - char *start = line; - while (*start != '\0') { - if (*start == ':' && *(start + 1) == ' ') { - return (start + 2); +static void set_value(Parser *parser, KeyFinder *key_finder, char* raw_value) { + GenericPointer address = parser->storage + (parser->storage_struct_size * parser->nb_stored); + GenericPointer value = key_finder->copy(raw_value); + key_finder->set(address, value); +} + +// static void storage_zero(Parser *parser) { +// static const int zero = 0; +// GenericPointer storage = parser->storage; +// size_t capacity = parser->capacity; +// size_t struct_size = parser->storage_struct_size; +// memset(storage, zero, struct_size * capacity); +// } + +static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value) { + for (unsigned int i = 0; i < parser->nb_keys; i++) { + KeyFinder *finder = &parser->keys[i]; + + if (start_with(finder->key, line)) { + char* value = NULL; + char* key = NULL; + + split_on_delimiter(line, finder->delimiter, &key, &value); + if ( key == NULL || value == NULL) { + return 0; + } + *key_finder = finder; + *raw_value = value; + return 1; + } + } + return 0; +} + +static unsigned int move_to_next(Parser *parser) { + parser->nb_stored += 1; + if (parser->nb_stored >= parser->capacity) { + return 0; + } + return 1; +} + +static unsigned int parse(Parser *parser) { + char *line = NULL; + size_t len = 0; + ssize_t read; + unsigned int key_assigned = 0; + + while ((read = getline(&line, &len, parser->file)) != -1) { + if (key_assigned == parser->nb_keys && read > 1) { + continue; + } else if (read == 1) { + if (!move_to_next(parser)) { + return 0; + } + key_assigned = 0; + } else { + KeyFinder *key_finder = NULL; + char *raw_value = NULL; + replace_first(line, '\n', '\0'); + if (match(parser, line, &key_finder, &raw_value)) { + set_value(parser, key_finder, raw_value); + ++key_assigned; + } + } + } + if (key_assigned > 0) { + parser->nb_stored++; + } + free(line); + return 1; +} + + + +static void replace_first(char* string, char from, char to) { + for (int i = 0; string[i] != '\0'; i++) { + if (string[i] == from) { + string[i] = to; + break; + } } - ++start; - } - return NULL; } -void replace_first(char *string, char find, char replace) { - char *found = strchr(string, find); - if (found) { - *found = replace; - } +static void split_on_delimiter(char *string, const char* delimiter, char **key, char **value) { + *key = NULL; + *value = NULL; + size_t delimiter_len = strlen(delimiter); + char* start_delimiter = strstr(string, delimiter); + if (start_delimiter != NULL) { + *start_delimiter = '\0'; + *key = string; + *value = start_delimiter + delimiter_len; + } } -unsigned int start_with(const char *prefix, const char *string) { - size_t prefix_len = strlen(prefix); - size_t string_len = strlen(string); - return string_len < prefix_len ? false - : memcmp(prefix, string, prefix_len) == 0; +static bool start_with(const char *prefix, const char *string) { + if (prefix == NULL || string == NULL) { + return false; + } + + size_t prefix_len = strlen(prefix); + size_t string_len = strlen(string); + + if (string_len < prefix_len) { + return false; + } else { + return memcmp(prefix, string, prefix_len) == 0; + } } -int match(Parser *parser, char *line) { - for (size_t i = 0; i < parser->nb_keys; i++) { - KeyFinder *key_finder = &parser->keys[i]; - if (start_with(key_finder->key, line)) { - char *string_value = get_string_value(line); - if (get_string_value == NULL) { - fprintf(stderr, "Error : invalid format for line : %s\n", line); - exit(EXIT_FAILURE); - } - replace_first(string_value, '\n', '\0'); - void *value = key_finder->copy(string_value); +#ifdef __TESTING__ - key_finder->set( - (parser->storage + (parser->storage_struct_size * parser->nb_stored)), - value); +#define FMT_NULL(string) \ + string = string ? string : "NULL" - return 1; - } - } - return 0; +#define TEST_STR(result, expected) \ + test_str(__FILE__, __LINE__, result, expected) + +#define TEST_BOOLEAN(result, expected) \ + test_boolean(__FILE__, __LINE__, result, expected) + +#define TEST_PTR(result, expected) \ + test_ptr(__FILE__, __LINE__, result, expected) + +typedef int (Comparator) (void*, void*); +typedef char* (Formatter) (char*, void*); + +int string_compare(char* string1, char* string2) { + if (string1 == NULL && string2 == NULL) { + return 1; + } else if (string1 == NULL || string2 == NULL) { + return 0; + } else { + return (strcmp(string1, string2) == 0); + } } -void parse(Parser *parser) { - char *line = NULL; - size_t len = 0; - ssize_t read; +char* string_format(__attribute__((unused)) char* buffer, char* string) { + return FMT_NULL(string); +} - unsigned int key_assigned = 0; - while ((read = getline(&line, &len, parser->file)) != -1) { - if (key_assigned == parser->nb_keys && read > 1) { - continue; - } - if (read == 1) { - parser->nb_stored++; - if (parser->nb_stored == parser->capacity) { - fprintf(stderr, "Error : too much cpus to read.\n"); - exit(EXIT_FAILURE); - } - - key_assigned = 0; - } - key_assigned += match(parser, line); - } +int boolean_compare(bool* boolean1, bool* boolean2) { + return *boolean1 == *boolean2; +} + +char* boolean_format(__attribute__((unused)) char* buffer, bool* boolean) { + return *boolean ? "True" : "False"; +} + +int ptr_compare(void* ptr1, void* ptr2) { + return ptr1 == ptr2; +} - if (key_assigned > 0) { - parser->nb_stored++; - } +char* ptr_format(char* buffer, void* ptr) { + sprintf(buffer, "%p", ptr); + return buffer; +} + +void test(char* file, int line, void* result, void* expected, Comparator* compare, Formatter* format){ + static char buffer_result[1000]; + static char buffer_expected[1000]; + if (compare(result, expected) == 0){ + printf("Test %s:%d failed: expected %s, got %s\n", + file, + line, + format(buffer_result, expected), + format(buffer_expected, result) + ); + } else { + printf("Test %s:%d passed\n", file, line); + } +} + +void test_str(char* file, int line, char* result, char* expected) { + Comparator* compare = (Comparator*) string_compare; + Formatter* format = (Formatter*) string_format; + + test(file, line, result, expected, compare, format); +} + +void test_boolean(char* file, int line, bool* result, bool* expected) { + Comparator* compare = (Comparator*) boolean_compare; + Formatter* format = (Formatter*) boolean_format; + + test(file, line, (void*) result, (void*) expected, compare, format); +} + +void test_ptr(char* file, int line, void* result, void* expected) { + Comparator* compare = (Comparator*) ptr_compare; + Formatter* format = (Formatter*) ptr_format; + + test(file, line, result, expected, compare, format); +} + +void test_replace_first() { + printf("==== TEST replace_first() ====\n"); + char test1[] = "This is my string"; + replace_first(test1, 'i', 'I'); + TEST_STR(test1, "ThIs is my string"); + + char test2[] = "This is my string"; + replace_first(test2, 'x', 'X'); + TEST_STR(test2, "This is my string"); + + + char test3[] = "This is my string"; + replace_first(test3, ' ', '_'); + TEST_STR(test3, "This_is my string"); +} + +void test_split_on_delimiter() { + printf("==== TEST split_on_delimite() ====\n"); + char test4[] = "key:value"; + char* key; + char* value; + split_on_delimiter(test4, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, "value"); + + char test5[] = "key: value"; + split_on_delimiter(test5, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, " value"); + + char test6[] = "key:value"; + replace_first(test6, ':', ' '); + split_on_delimiter(test6, " ", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, "value"); + + char test7[] = ""; + split_on_delimiter(test7, ":", &key, &value); + TEST_STR(key, NULL); + TEST_STR(value, NULL); + + char test9[] = "key:value:extra"; + split_on_delimiter(test9, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, "value:extra"); + + char test10[] = "key: value :extra"; + split_on_delimiter(test10, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, " value :extra"); +} + +void test_start_with() { + printf("==== TEST start_with() ====\n"); + char* prefix = NULL; + char* string = NULL; + bool result = false; + bool _true = true; + bool _false = false; + + prefix = "Hello"; + string = "Hello World"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_true); + + prefix = "Goodbye"; + string = "Hello World"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_false); + + prefix = "Hello World"; + string = "Hello"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_false); + + prefix = "Hello"; + string = "Hello"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_true); + + prefix = NULL; + string = "Hello World"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_false); +} + +#define DUMB_KEYFINDER(key_finder, key, delimiter) \ + do { \ + key_finder = (KeyFinder) { \ + key, \ + delimiter, \ + NULL, \ + NULL \ + }; \ + } while (0); + +#define DUMB_PARSER(parser, keys, nb_keys) \ + do { \ + parser = (Parser) { \ + NULL, \ + 0, \ + 0, \ + 0, \ + keys, \ + nb_keys, \ + NULL \ + }; \ + } while (0); + + +void test_match() { + printf("==== TEST match() ====\n"); + // usefull variable : + bool _true = true; + bool _false = false; + KeyFinder keys[10]; + char line[100]; + Parser parser; + bool result; + KeyFinder* found_key_finder = NULL; + char* raw_value = NULL; + + // Test 1: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, "key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_true); + TEST_PTR(found_key_finder, &keys[0]); + TEST_STR(raw_value, "value"); + + // Test 2: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1) + strcpy(line, "not a key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); + + // Test 3: + // -- Setup + DUMB_KEYFINDER(keys[0],"key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, "key:value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); + + // Test 4: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_KEYFINDER(keys[1], "second_key", ": "); + DUMB_PARSER(parser, keys, 2); + strcpy(line, "second_key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_true); + TEST_PTR(found_key_finder, &keys[1]); + TEST_STR(raw_value, "value"); + + // Test 5: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, ""); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); +} - free(line); +int main() { + test_replace_first(); + test_split_on_delimiter(); + test_start_with(); + test_match(); + return 0; } #endif -- GitLab From ad8b9217a2d9a275e9373a5cdf0ca65e4bb698b0 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 08:38:51 +0000 Subject: [PATCH 039/125] format: dos2linux LICENSE --- LICENSE | 1348 +++++++++++++++++++++++++++---------------------------- 1 file changed, 674 insertions(+), 674 deletions(-) diff --git a/LICENSE b/LICENSE index 3877ae0..f288702 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,674 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<https://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<https://www.gnu.org/licenses/why-not-lgpl.html>. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>. -- GitLab From 6ee1d02f90e9bde8d158493685b9a79f17316361 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 08:40:38 +0000 Subject: [PATCH 040/125] format: doc --- doc/counter_ex.c | 9 +++------ makefile | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/counter_ex.c b/doc/counter_ex.c index 5067003..188f4dd 100644 --- a/doc/counter_ex.c +++ b/doc/counter_ex.c @@ -2,21 +2,18 @@ static int acc; -unsigned int -init_acc(char *a, void **b) +unsigned int init_acc(char *a, void **b) { acc = 0; } -unsigned int -get_acc(uint64_t *results, void *none) +unsigned int get_acc(uint64_t *results, void *none) { UNUSED(none); return a++; } -void -label_acc(char **labels, void *none) +void label_acc(char **labels, void *none) { UNUSED(none); labels[0] = "acc"; diff --git a/makefile b/makefile index 9988f8a..c43c867 100644 --- a/makefile +++ b/makefile @@ -1,9 +1,11 @@ .PHONY: all clean mojitos mojitos_group debug format SRC_DIR = src +DOC_DIR = doc OBJ_DIR = obj BIN_DIR = bin + OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o infiniband.o temperature.o util.o) OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) @@ -42,6 +44,7 @@ debug: all format: $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h + $(ASTYLE) $(DOC_DIR)/*.c $(DOC_DIR)/*.h clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* -- GitLab From b1d79f008e5fd55f39f60d06e5991c5b2c292db0 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 23 Jan 2023 15:00:56 +0100 Subject: [PATCH 041/125] update doc (formatting, and new header) --- doc/counter_ex.c | 15 +++++++++------ doc/counter_ex.h | 13 ++++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/doc/counter_ex.c b/doc/counter_ex.c index 5067003..73696ad 100644 --- a/doc/counter_ex.c +++ b/doc/counter_ex.c @@ -2,22 +2,25 @@ static int acc; -unsigned int -init_acc(char *a, void **b) +unsigned int init_acc(char *a, void **b) { acc = 0; } -unsigned int -get_acc(uint64_t *results, void *none) +unsigned int get_acc(uint64_t *results, void *none) { UNUSED(none); return a++; } -void -label_acc(char **labels, void *none) +void label_acc(char **labels, void *none) { UNUSED(none); labels[0] = "acc"; } + +void clean_acc(void *none) +{ + /* That's a no-op for this example */ + UNUSED(none); +} diff --git a/doc/counter_ex.h b/doc/counter_ex.h index 49e185c..beeef91 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -4,4 +4,15 @@ unsigned int init_acc(char *, void **); unsigned int get_acc(uint64_t *results, void *); -void label_counter(char **labels, void *); +void clean_acc(void*); +void label_acc(char **labels, void *); + +struct optparse_long counters_opt = {"accumulator", 'a', OPTPARSE_NONE}; +struct captor counters = { + .usage_arg = NULL, + .usage_msg = "dumb accumulator\n" + .init = init_acc, + .get = get_acc, + .clean = clean_acc, + .label = label_acc, +}; -- GitLab From 0112f0fb7c8ba9420bb62323973590be0389264d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 14:24:10 +0000 Subject: [PATCH 042/125] add macros --- src/util.c | 27 ++++++++++++++++++++++++--- src/util.h | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/util.c b/src/util.c index 5ff3acd..186434b 100644 --- a/src/util.c +++ b/src/util.c @@ -1,6 +1,27 @@ +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #include "util.h" -inline uint64_t substractAcc(const uint64_t l, const uint64_t r) +uint64_t modulo_substraction(uint64_t previous, u_int64_t new) { - return (l < r) ? UINT64_MAX + (l - r) : l - r; -} \ No newline at end of file + return new > previous ? (previous - new) + : (UINT64_MAX - new) + previous; +} diff --git a/src/util.h b/src/util.h index 1fff9af..6d4a644 100644 --- a/src/util.h +++ b/src/util.h @@ -1,10 +1,43 @@ +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #ifndef _UTIL_H #define _UTIL_H -//#warning "TODO: Add licence" - #include <stdint.h> -inline uint64_t substractAcc(const uint64_t l, const uint64_t r); +#define CASSERT(predicate, file) _impl_CASSERT_LINE(predicate,__LINE__,file) + +#define _impl_PASTE(a,b) a##b +#define _impl_CASSERT_LINE(predicate, line, file) \ + typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; + +#define UNUSED(expr) do { (void)(expr); } while (0) +#define PANIC(code, fmt, ...) \ + do { \ + fprintf(stderr, "Exit on error: "); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + exit(code); \ + } while (0) + +uint64_t modulo_substraction(const uint64_t l, const uint64_t r); #endif -- GitLab From 89508f4d9e097464af8f64467f919f60185e4be8 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 14:25:34 +0000 Subject: [PATCH 043/125] working progress --- src/amd_rapl.c | 323 +++++++++++++++++++++++ src/amd_rapl.h | 24 ++ src/info_reader.c | 158 +++++++----- src/info_reader.h | 639 ++++++++++++++++++++++++---------------------- 4 files changed, 768 insertions(+), 376 deletions(-) create mode 100644 src/amd_rapl.c create mode 100644 src/amd_rapl.h diff --git a/src/amd_rapl.c b/src/amd_rapl.c new file mode 100644 index 0000000..b83ded9 --- /dev/null +++ b/src/amd_rapl.c @@ -0,0 +1,323 @@ +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + +#include <stdio.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +#include "info_reader.h" +#include "util.h" +#include "amd_rapl.h" + +#warning "Must be modified before release" +#define BUFFER_SIZE 64 +#define MAX_CPUS 64 +#define NB_KEYS 2 + +// ---------------------------MSR_REGISTERS +static const uint64_t amd_energy_mask = 0xFFFFFFFF; +static const uint64_t amd_energy_unit_mask = 0x01F00; +static const uint64_t msr_rapl_power_unit = 0xC0010299; +static const uint64_t energy_core_msr = 0xC001029A; +static const uint64_t energy_pkg_msr = 0xC001029B; + +// ------------------------------FILE_PATHS +static const char *base_str = "/dev/cpu/%d/msr"; +static const char *cpuinfo = "/proc/cpuinfo"; + +struct cpu_sensor_t { + //TODO: check the reset of the msr registers +#warning "Check the reset of the msr registers" + size_t cpu_id; + size_t package_id; + char *name; + + int *fd; + uint64_t energy_units; + uint64_t core_energy; + uint64_t pkg_energy; +}; +typedef struct cpu_sensor_t cpu_sensor_t; + +struct _amd_rapl_t { + cpu_sensor_t *sensors; + unsigned int nb; +}; +typedef struct _amd_rapl_t _amd_rapl_t; + +// -----------------------------INFO_READER + +static GenericPointer _size_t_allocator(char *s) +{ + size_t value = atoi(s); + return (GenericPointer) value; +} + +static void _set_cpu_id(GenericPointer storage, GenericPointer data) +{ + cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + cpu->cpu_id = (size_t) data; +} + +static void _set_package_id(GenericPointer storage, GenericPointer data) +{ + cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + cpu->package_id = (size_t) data; +} + +static KeyFinder keys[NB_KEYS] = { + {"processor", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_cpu_id}, + {"physical id", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_package_id} +}; + +// --------------------------------READ_MSR + +uint64_t read_msr(int fd, uint64_t msr) +{ + uint64_t data; + if (pread(fd, &data, sizeof data, msr) != sizeof data) { + fprintf(stderr, "msr(%ld):", msr); + perror("pread"); + exit(127); + } + return data; +} + +uint64_t read_unit(int fd) +{ + u_int64_t unit = read_msr(fd, msr_rapl_power_unit); + return (unit & amd_energy_unit_mask) >> 8; +} + +uint64_t read_raw_core_energy(int fd) +{ + u_int64_t energy = read_msr(fd, energy_core_msr); + return energy & amd_energy_mask; +} + +uint64_t read_raw_pkg_energy(int fd) +{ + u_int64_t energy = read_msr(fd, energy_pkg_msr); + return energy & amd_energy_mask; +} + +// ---------------------------------ENERGY + +uint64_t raw_to_microjoule(uint64_t raw, uint64_t unit) +{ + // raw * (1 / (unit^2)) -> Joule + // Joule * 1000000 -> microjoule + return (raw * 1000000UL) / (1ul << unit); +} +uint64_t raw_to_joule(uint64_t raw, uint64_t unit) +{ + // raw * (1 / (unit^2)) -> Joule + return raw / (1ul << unit); +} + +// -----------------------------------DEBUG + +#ifdef DEBUG +void debug_print_sensor(cpu_sensor_t *sensor) +{ + CASSERT(sizeof(cpu_sensor_t) == 40, amd_rapl_c); + printf("cpu_id : %ld, package_id : %ld, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", + sensor->cpu_id, + sensor->package_id, + sensor->energy_units, + sensor->core_energy, + sensor->pkg_energy + ); +} + +void debug_print_amd_rapl(_amd_rapl_t *rapl) +{ + for (unsigned int i = 0; i < rapl->nb; i++) { + debug_print_sensor(rapl->sensors[i]); + } +} +#endif + + + +// ---------------------------AMD_RAPL_UTIL + +uint64_t modulo_substraction(uint64_t previous, u_int64_t new) +{ + return new > previous ? (previous - new) + : (UINT64_MAX - new) + previous; +} + +unsigned int get_nb_cpu() +{ + char filename[BUFFER_SIZE]; + + unsigned int n_cpu = 0; + for (;; n_cpu++) { + sprintf(filename, base_str, n_cpu); + + int fd = open(filename, O_RDONLY); + if (fd < 0) { + break; + } + close(fd); + } + return n_cpu; +} + +void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) +{ + static const char *base_name = "core%ld"; + static char filename[BUFFER_SIZE]; + sprintf(filename, base_str, cpu_id); + + int fd = open(filename, O_RDONLY); + if (fd < 0) { + perror("rdmsr:open"); + exit(127); + } + + u_int64_t raw_core_energy = read_raw_core_energy(fd); + u_int64_t raw_pkg_energy = read_raw_pkg_energy(fd); + + sensor->cpu_id = cpu_id; + asprintf(sensor->name, base_name, sensor->cpu_id); + sensor->energy_units = read_unit(fd); + sensor->core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); + sensor->pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); +} + +u_int64_t get_core_energy(cpu_sensor_t *sensor) +{ + u_int64_t raw_core_energy = read_raw_core_energy(sensor->fd); + u_int64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units) + + u_int64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); + sensor->core_energy = core_energy; + return energy_consumed; +} + +u_int64_t get_pkg_energy(cpu_sensor_t *sensor) +{ + u_int64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); + u_int64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units) + + u_int64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); + sensor->pkg_energy = pkg_energy; + return energy_consumed; +} + +// ----------------------AMD_RAPL_INTERFACE + + +void free_amd_rapl(_amd_rapl_t *rapl) +{ + free(rapl->sensors); + free(rapl); +} + + +unsigned int init_amd_rapl(char *none, void **ptr) +{ +// FILE *fcpuinfo = fopen(cpuinfo, "r"); +// if (fcpuinfo == NULL) { +// perror("fopen"); +// exit(1); +// } +// Parser parser = { +// (GenericPointer) cpus, +// 0, +// MAX_CPUS, +// sizeof(cpu_sensor_t), +// keys, +// NB_KEYS, +// fcpuinfo +// }; +// parse(&parser); +// fclose(fcpuinfo); + +// #ifdef DEBUG +// printf("nb_cpus: %d\n", parser.nb_stored); +// for (unsigned int nb_cpu = 0; nb_cpu < parser.nb_stored; ++nb_cpu) { +// debug_print_sensor(&cpus[nb_cpu]); +// } +// #endif + + UNUSED(none); + _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); + + unsigned int nb_cpu = get_nb_cpu(); + if (nb_cpu == 0) { + perror("get_nb_cpu"); + exit(127); + } + + cpu_sensor_tr *cpus = (cpu_sensor_t *) calloc(nb_cpu, sizeof(cpu_sensor_t)); + + rapl->nb = nb_cpu; + rapl->sensors = cpus; + + for (unsigned int i = 0; i < nb_cpu; i++) { + init_cpu_sensor(&rapl->sensors[i], i); + } + return rapl->nb; +} + + +unsigned int get_amd_rapl(uint64_t results, void *ptr) +{ + _amd_rapl_t *rapl = (_amd_rapl_t) ptr; + for (unsigned int i = 0; i < rapl->nb; i++) { + // TODO: check if unit is the same +#warning "check if unit is the same" + results[i] = get_core_energy(rapl->sensors[i]); + } + return rapl->nb; +} + + + + +int main() +{ + _amd_rapl_t *rapl = (_amd_rapl_t *)malloc(sizeof(_amd_rapl_t)); + init_amd_rapl(rapl); + print_amd_rapl(rapl); + sleep(1); + print_amd_rapl(rapl); + sleep(1); + print_amd_rapl(rapl); + sleep(1); + print_amd_rapl(rapl); + sleep(1); + print_amd_rapl(rapl); + sleep(1); + print_amd_rapl(rapl); + sleep(1); + print_amd_rapl(rapl); + + free_amd_rapl(rapl); + return 0; +} + diff --git a/src/amd_rapl.h b/src/amd_rapl.h new file mode 100644 index 0000000..459c136 --- /dev/null +++ b/src/amd_rapl.h @@ -0,0 +1,24 @@ +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_amd_rapl(char *, void **); +unsigned int get_amd_rapl(uint64_t *results, void *); +void clean_amd_rapl(void *); +void label_amd_rapl(char **labels, void *); diff --git a/src/info_reader.c b/src/info_reader.c index 110d060..e2563c6 100644 --- a/src/info_reader.c +++ b/src/info_reader.c @@ -1,89 +1,115 @@ #include "info_reader.h" +#include <stdint.h> -#ifdef DEBUG - #warning "PTR_TO_TPTR hide a cast warning"aa -#endif +#ifdef DEBUG +#warning "PTR_TO_TPTR hide a cast warning"aa +#endif -#define MAX_PROCS 128 +#define MAX_PROCS 2 typedef struct { - size_t processor; - char *vendor_id; - size_t family; - size_t core_id; - size_t physical_id; - char *model_name; + size_t processor; + char *vendor_id; + size_t family; + size_t core_id; + size_t physical_id; + char *model_name; } Cpu; -GenericPointer int_allocator(char *s) { - size_t value = atoi(s); - return (GenericPointer) value; +GenericPointer int_allocator(char *s) +{ + size_t value = atoi(s); + return (GenericPointer) value; } -GenericPointer string_allocator(char *s) { - char *value = malloc(strlen(s) + 1); - strcpy(value, s); - return (GenericPointer) value; +GenericPointer string_allocator(char *s) +{ + char *value = malloc(strlen(s) + 1); + strcpy(value, s); + return (GenericPointer) value; } -void set_processor(GenericPointer storage, GenericPointer data) { - Cpu* cpu = (Cpu*) storage; - cpu->processor = data; +void set_processor(GenericPointer storage, GenericPointer data) +{ + Cpu *cpu = (Cpu *) storage; + cpu->processor = data; } -void set_vendor_id(GenericPointer storage, GenericPointer data) { - Cpu* cpu = (Cpu*) storage; - cpu->vendor_id = (char*) data; +void set_vendor_id(GenericPointer storage, GenericPointer data) +{ + Cpu *cpu = (Cpu *) storage; + cpu->vendor_id = (char *) data; } -void set_family(GenericPointer storage, GenericPointer data) { - Cpu* cpu = (Cpu*) storage; - cpu->family = data; +void set_family(GenericPointer storage, GenericPointer data) +{ + Cpu *cpu = (Cpu *) storage; + cpu->family = data; } -void set_core_id(GenericPointer storage, GenericPointer data) { - Cpu* cpu = (Cpu*) storage; - cpu->core_id = data; +void set_core_id(GenericPointer storage, GenericPointer data) +{ + Cpu *cpu = (Cpu *) storage; + cpu->core_id = data; } -void set_physical_id(GenericPointer storage, GenericPointer data) { - Cpu* cpu = (Cpu*) storage; - cpu->physical_id = data; +void set_physical_id(GenericPointer storage, GenericPointer data) +{ + Cpu *cpu = (Cpu *) storage; + cpu->physical_id = data; } -void set_model_name(GenericPointer storage, GenericPointer data) { - Cpu* cpu = (Cpu*) storage; - cpu->model_name = (char*) data; +void set_model_name(GenericPointer storage, GenericPointer data) +{ + Cpu *cpu = (Cpu *) storage; + cpu->model_name = (char *) data; } -int main(int argc, char const *argv[]) { - Cpu cpus[MAX_PROCS]; - KeyFinder keys[] = { - {"processor", ": ", (CopyAllocator *) int_allocator, (Setter *)set_processor}, - {"vendor_id", ": ", (CopyAllocator *) string_allocator, (Setter *)set_vendor_id}, - {"cpu family", ": ", (CopyAllocator *) int_allocator, (Setter *)set_family}, - {"core id", ": ", (CopyAllocator *) int_allocator, (Setter *)set_core_id}, - {"physical id", ": ", (CopyAllocator *) int_allocator,(Setter *)set_physical_id}, - {"model name", ": ", (CopyAllocator *) string_allocator, - (Setter *)set_model_name} - }; +struct cpu_sensor_t { + //TODO: check the reset of the msr registers +#warning "Check the reset of the msr registers" + size_t cpu_id; + size_t package_id; - Parser parser = {.storage = (GenericPointer) cpus, - .capacity = MAX_PROCS, - .storage_struct_size = sizeof(Cpu), - .keys = keys, - .nb_keys = 6, - .file = fopen("/proc/cpuinfo", "r")}; + uint64_t energy_units; + uint64_t core_energy_status; + uint64_t pkg_energy_status; +}; - parse(&parser); +int main(int argc, char const *argv[]) +{ + Cpu cpus[MAX_PROCS]; + KeyFinder keys[] = { + {"processor", ": ", (CopyAllocator *) int_allocator, (Setter *)set_processor}, + {"vendor_id", ": ", (CopyAllocator *) string_allocator, (Setter *)set_vendor_id}, + {"cpu family", ": ", (CopyAllocator *) int_allocator, (Setter *)set_family}, + {"core id", ": ", (CopyAllocator *) int_allocator, (Setter *)set_core_id}, + {"physical id", ": ", (CopyAllocator *) int_allocator,(Setter *)set_physical_id}, + { + "model name", ": ", (CopyAllocator *) string_allocator, + (Setter *)set_model_name + } + }; - for (unsigned int i = 0; i < parser.nb_stored; ++i) { - printf("========== PROC[%d] ==========\n", i); - printf("Processor: %ld\n", cpus[i].processor); - printf("Vendor ID: %s\n", cpus[i].vendor_id); - printf("Family: %ld\n", cpus[i].family); - printf("Core ID: %ld\n", cpus[i].core_id); - printf("Physical ID: %ld\n", cpus[i].physical_id); - printf("Model Name: %s\n", cpus[i].model_name); - printf("==============================\n"); - free(cpus[i].vendor_id); - free(cpus[i].model_name); - } + Parser parser = {.storage = (GenericPointer) cpus, + .capacity = MAX_PROCS, + .storage_struct_size = sizeof(Cpu), + .keys = keys, + .nb_keys = 6, + .file = fopen("/proc/cpuinfo", "r") + }; - return 0; + parse(&parser); + + for (unsigned int i = 0; i < parser.nb_stored; ++i) { + printf("========== PROC[%d] ==========\n", i); + printf("Processor: %ld\n", cpus[i].processor); + printf("Vendor ID: %s\n", cpus[i].vendor_id); + printf("Family: %ld\n", cpus[i].family); + printf("Core ID: %ld\n", cpus[i].core_id); + printf("Physical ID: %ld\n", cpus[i].physical_id); + printf("Model Name: %s\n", cpus[i].model_name); + printf("==============================\n"); + free(cpus[i].vendor_id); + free(cpus[i].model_name); + } + + printf("size = %ld\n", sizeof (struct cpu_sensor_t)); + + return 0; } diff --git a/src/info_reader.h b/src/info_reader.h index 030ea52..4717841 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -8,7 +8,7 @@ * @brief The parser struct * The struct containing all the necessary informations and functions to parse a file * - * @var storage : void* : pointer to the storage where the parsed data will be stored + * @var storage : GenericPointer : pointer to the storage where the parsed data will be stored * @var nb_stored : unsigned int : the number of struct stored * @var capacity : unsigned int : the maximum number of struct that can be stored * @var storage_struct_size : size_t : the size of the struct stored in the storage @@ -22,7 +22,7 @@ typedef struct Parser Parser; * @struct KeyFinder * @brief The key finder struct * The struct containing all the necessary informations and functions to find a key in a line of text - * + * * @var key : char* : the key to be found * @var delimiter : char* : the delimiter between the key and the value * @var copy : CopyAllocator*: the function to use to make a copy of the value @@ -58,17 +58,17 @@ static void split_on_delimiter(char *string, const char *delimiter, char **key, * @param[in] to The character to replace with. * @return None. */ -static void replace_first(char* string, char from, char to); +static void replace_first(char *string, char from, char to); /** * @brief Check if a string starts with a prefix. - * + * * @param[in] prefix The prefix to check. * @param[in] string The string to check. * @return true The string starts with the prefix. * @return false The string does not start with the prefix or one of the input pointers is NULL. */ -static bool start_with(const char* prefix, const char* string); +static bool start_with(const char *prefix, const char *string); /** * @brief Matches a line of text to a key in the parser's list of keys. @@ -82,38 +82,36 @@ static bool start_with(const char* prefix, const char* string); */ static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value); - - - typedef size_t GenericPointer; typedef GenericPointer (CopyAllocator) (char *string); typedef void (Setter) (GenericPointer storage, GenericPointer value); struct KeyFinder { - char *key; - char *delimiter; + char *key; + char *delimiter; - CopyAllocator *copy; - Setter *set; + CopyAllocator *copy; + Setter *set; }; struct Parser { - GenericPointer storage; - unsigned int nb_stored; - unsigned int capacity; - size_t storage_struct_size; + GenericPointer storage; + unsigned int nb_stored; + unsigned int capacity; + size_t storage_struct_size; - KeyFinder *keys; - unsigned int nb_keys; + KeyFinder *keys; + unsigned int nb_keys; - FILE *file; + FILE *file; }; -static void set_value(Parser *parser, KeyFinder *key_finder, char* raw_value) { - GenericPointer address = parser->storage + (parser->storage_struct_size * parser->nb_stored); - GenericPointer value = key_finder->copy(raw_value); - key_finder->set(address, value); -} +static void set_value(Parser *parser, KeyFinder *key_finder, char *raw_value) +{ + GenericPointer address = parser->storage + (parser->storage_struct_size * parser->nb_stored); + GenericPointer value = key_finder->copy(raw_value); + key_finder->set(address, value); +} // static void storage_zero(Parser *parser) { // static const int zero = 0; @@ -123,68 +121,72 @@ static void set_value(Parser *parser, KeyFinder *key_finder, char* raw_value) { // memset(storage, zero, struct_size * capacity); // } -static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value) { - for (unsigned int i = 0; i < parser->nb_keys; i++) { - KeyFinder *finder = &parser->keys[i]; - - if (start_with(finder->key, line)) { - char* value = NULL; - char* key = NULL; - - split_on_delimiter(line, finder->delimiter, &key, &value); - if ( key == NULL || value == NULL) { - return 0; - } - *key_finder = finder; - *raw_value = value; - return 1; - } - } - return 0; +static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value) +{ + for (unsigned int i = 0; i < parser->nb_keys; i++) { + KeyFinder *finder = &parser->keys[i]; + + if (start_with(finder->key, line)) { + char *value = NULL; + char *key = NULL; + + split_on_delimiter(line, finder->delimiter, &key, &value); + if ( key == NULL || value == NULL) { + return 0; + } + *key_finder = finder; + *raw_value = value; + return 1; + } + } + return 0; } -static unsigned int move_to_next(Parser *parser) { - parser->nb_stored += 1; - if (parser->nb_stored >= parser->capacity) { - return 0; - } - return 1; +static unsigned int move_to_next(Parser *parser) +{ + parser->nb_stored += 1; + if (parser->nb_stored >= parser->capacity) { + return 0; + } + return 1; } -static unsigned int parse(Parser *parser) { - char *line = NULL; - size_t len = 0; - ssize_t read; - unsigned int key_assigned = 0; - - while ((read = getline(&line, &len, parser->file)) != -1) { - if (key_assigned == parser->nb_keys && read > 1) { - continue; - } else if (read == 1) { - if (!move_to_next(parser)) { - return 0; - } - key_assigned = 0; - } else { - KeyFinder *key_finder = NULL; - char *raw_value = NULL; - replace_first(line, '\n', '\0'); - if (match(parser, line, &key_finder, &raw_value)) { - set_value(parser, key_finder, raw_value); - ++key_assigned; - } - } - } - if (key_assigned > 0) { - parser->nb_stored++; - } - free(line); - return 1; +static unsigned int parse(Parser *parser) +{ + char *line = NULL; + size_t len = 0; + ssize_t read; + unsigned int key_assigned = 0; + + while ((read = getline(&line, &len, parser->file)) != -1) { + if (key_assigned == parser->nb_keys && read > 1) { + continue; + } else if (read == 1) { + if (!move_to_next(parser)) { + return 0; + } + key_assigned = 0; + } else { + KeyFinder *key_finder = NULL; + char *raw_value = NULL; + replace_first(line, '\n', '\0'); + if (match(parser, line, &key_finder, &raw_value)) { + set_value(parser, key_finder, raw_value); + ++key_assigned; + } + } + } + if (key_assigned > 0) { + parser->nb_stored++; + } + free(line); + return 1; } -static void replace_first(char* string, char from, char to) { +static void replace_first(char *string, char from, char to) +{ for (int i = 0; string[i] != '\0'; i++) { if (string[i] == from) { string[i] = to; @@ -193,31 +195,33 @@ static void replace_first(char* string, char from, char to) { } } -static void split_on_delimiter(char *string, const char* delimiter, char **key, char **value) { - *key = NULL; - *value = NULL; - size_t delimiter_len = strlen(delimiter); - char* start_delimiter = strstr(string, delimiter); - if (start_delimiter != NULL) { - *start_delimiter = '\0'; - *key = string; - *value = start_delimiter + delimiter_len; - } +static void split_on_delimiter(char *string, const char *delimiter, char **key, char **value) +{ + *key = NULL; + *value = NULL; + size_t delimiter_len = strlen(delimiter); + char *start_delimiter = strstr(string, delimiter); + if (start_delimiter != NULL) { + *start_delimiter = '\0'; + *key = string; + *value = start_delimiter + delimiter_len; + } } -static bool start_with(const char *prefix, const char *string) { - if (prefix == NULL || string == NULL) { - return false; - } +static bool start_with(const char *prefix, const char *string) +{ + if (prefix == NULL || string == NULL) { + return false; + } - size_t prefix_len = strlen(prefix); - size_t string_len = strlen(string); + size_t prefix_len = strlen(prefix); + size_t string_len = strlen(string); - if (string_len < prefix_len) { - return false; - } else { - return memcmp(prefix, string, prefix_len) == 0; - } + if (string_len < prefix_len) { + return false; + } else { + return memcmp(prefix, string, prefix_len) == 0; + } } @@ -235,161 +239,174 @@ static bool start_with(const char *prefix, const char *string) { #define TEST_PTR(result, expected) \ test_ptr(__FILE__, __LINE__, result, expected) -typedef int (Comparator) (void*, void*); -typedef char* (Formatter) (char*, void*); - -int string_compare(char* string1, char* string2) { - if (string1 == NULL && string2 == NULL) { - return 1; - } else if (string1 == NULL || string2 == NULL) { - return 0; - } else { - return (strcmp(string1, string2) == 0); - } +typedef int (Comparator) (void *, void *); +typedef char *(Formatter) (char *, void *); + +int string_compare(char *string1, char *string2) +{ + if (string1 == NULL && string2 == NULL) { + return 1; + } else if (string1 == NULL || string2 == NULL) { + return 0; + } else { + return (strcmp(string1, string2) == 0); + } } -char* string_format(__attribute__((unused)) char* buffer, char* string) { - return FMT_NULL(string); +char *string_format(__attribute__((unused)) char *buffer, char *string) +{ + return FMT_NULL(string); } -int boolean_compare(bool* boolean1, bool* boolean2) { - return *boolean1 == *boolean2; +int boolean_compare(bool *boolean1, bool *boolean2) +{ + return *boolean1 == *boolean2; } -char* boolean_format(__attribute__((unused)) char* buffer, bool* boolean) { - return *boolean ? "True" : "False"; +char *boolean_format(__attribute__((unused)) char *buffer, bool *boolean) +{ + return *boolean ? "True" : "False"; } -int ptr_compare(void* ptr1, void* ptr2) { - return ptr1 == ptr2; +int ptr_compare(void *ptr1, void *ptr2) +{ + return ptr1 == ptr2; } -char* ptr_format(char* buffer, void* ptr) { - sprintf(buffer, "%p", ptr); - return buffer; +char *ptr_format(char *buffer, void *ptr) +{ + sprintf(buffer, "%p", ptr); + return buffer; } -void test(char* file, int line, void* result, void* expected, Comparator* compare, Formatter* format){ - static char buffer_result[1000]; - static char buffer_expected[1000]; - if (compare(result, expected) == 0){ - printf("Test %s:%d failed: expected %s, got %s\n", - file, - line, - format(buffer_result, expected), - format(buffer_expected, result) - ); - } else { - printf("Test %s:%d passed\n", file, line); - } +void test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) +{ + static char buffer_result[1000]; + static char buffer_expected[1000]; + if (compare(result, expected) == 0) { + printf("Test %s:%d failed: expected %s, got %s\n", + file, + line, + format(buffer_result, expected), + format(buffer_expected, result) + ); + } else { + printf("Test %s:%d passed\n", file, line); + } } -void test_str(char* file, int line, char* result, char* expected) { - Comparator* compare = (Comparator*) string_compare; - Formatter* format = (Formatter*) string_format; +void test_str(char *file, int line, char *result, char *expected) +{ + Comparator *compare = (Comparator *) string_compare; + Formatter *format = (Formatter *) string_format; - test(file, line, result, expected, compare, format); + test(file, line, result, expected, compare, format); } -void test_boolean(char* file, int line, bool* result, bool* expected) { - Comparator* compare = (Comparator*) boolean_compare; - Formatter* format = (Formatter*) boolean_format; +void test_boolean(char *file, int line, bool *result, bool *expected) +{ + Comparator *compare = (Comparator *) boolean_compare; + Formatter *format = (Formatter *) boolean_format; - test(file, line, (void*) result, (void*) expected, compare, format); + test(file, line, (void *) result, (void *) expected, compare, format); } -void test_ptr(char* file, int line, void* result, void* expected) { - Comparator* compare = (Comparator*) ptr_compare; - Formatter* format = (Formatter*) ptr_format; +void test_ptr(char *file, int line, void *result, void *expected) +{ + Comparator *compare = (Comparator *) ptr_compare; + Formatter *format = (Formatter *) ptr_format; - test(file, line, result, expected, compare, format); + test(file, line, result, expected, compare, format); } -void test_replace_first() { - printf("==== TEST replace_first() ====\n"); - char test1[] = "This is my string"; - replace_first(test1, 'i', 'I'); - TEST_STR(test1, "ThIs is my string"); +void test_replace_first() +{ + printf("==== TEST replace_first() ====\n"); + char test1[] = "This is my string"; + replace_first(test1, 'i', 'I'); + TEST_STR(test1, "ThIs is my string"); - char test2[] = "This is my string"; - replace_first(test2, 'x', 'X'); - TEST_STR(test2, "This is my string"); + char test2[] = "This is my string"; + replace_first(test2, 'x', 'X'); + TEST_STR(test2, "This is my string"); - char test3[] = "This is my string"; - replace_first(test3, ' ', '_'); - TEST_STR(test3, "This_is my string"); + char test3[] = "This is my string"; + replace_first(test3, ' ', '_'); + TEST_STR(test3, "This_is my string"); } -void test_split_on_delimiter() { - printf("==== TEST split_on_delimite() ====\n"); - char test4[] = "key:value"; - char* key; - char* value; - split_on_delimiter(test4, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test5[] = "key: value"; - split_on_delimiter(test5, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value"); - - char test6[] = "key:value"; - replace_first(test6, ':', ' '); - split_on_delimiter(test6, " ", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test7[] = ""; - split_on_delimiter(test7, ":", &key, &value); - TEST_STR(key, NULL); - TEST_STR(value, NULL); - - char test9[] = "key:value:extra"; - split_on_delimiter(test9, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value:extra"); - - char test10[] = "key: value :extra"; - split_on_delimiter(test10, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value :extra"); +void test_split_on_delimiter() +{ + printf("==== TEST split_on_delimite() ====\n"); + char test4[] = "key:value"; + char *key; + char *value; + split_on_delimiter(test4, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, "value"); + + char test5[] = "key: value"; + split_on_delimiter(test5, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, " value"); + + char test6[] = "key:value"; + replace_first(test6, ':', ' '); + split_on_delimiter(test6, " ", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, "value"); + + char test7[] = ""; + split_on_delimiter(test7, ":", &key, &value); + TEST_STR(key, NULL); + TEST_STR(value, NULL); + + char test9[] = "key:value:extra"; + split_on_delimiter(test9, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, "value:extra"); + + char test10[] = "key: value :extra"; + split_on_delimiter(test10, ":", &key, &value); + TEST_STR(key, "key"); + TEST_STR(value, " value :extra"); } -void test_start_with() { - printf("==== TEST start_with() ====\n"); - char* prefix = NULL; - char* string = NULL; - bool result = false; - bool _true = true; - bool _false = false; - - prefix = "Hello"; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); - - prefix = "Goodbye"; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); - - prefix = "Hello World"; - string = "Hello"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); - - prefix = "Hello"; - string = "Hello"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); - - prefix = NULL; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); +void test_start_with() +{ + printf("==== TEST start_with() ====\n"); + char *prefix = NULL; + char *string = NULL; + bool result = false; + bool _true = true; + bool _false = false; + + prefix = "Hello"; + string = "Hello World"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_true); + + prefix = "Goodbye"; + string = "Hello World"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_false); + + prefix = "Hello World"; + string = "Hello"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_false); + + prefix = "Hello"; + string = "Hello"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_true); + + prefix = NULL; + string = "Hello World"; + result = start_with(prefix, string); + TEST_BOOLEAN(&result, &_false); } #define DUMB_KEYFINDER(key_finder, key, delimiter) \ @@ -416,95 +433,97 @@ void test_start_with() { } while (0); -void test_match() { - printf("==== TEST match() ====\n"); - // usefull variable : - bool _true = true; - bool _false = false; - KeyFinder keys[10]; - char line[100]; - Parser parser; - bool result; - KeyFinder* found_key_finder = NULL; - char* raw_value = NULL; - - // Test 1: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); - strcpy(line, "key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_true); - TEST_PTR(found_key_finder, &keys[0]); - TEST_STR(raw_value, "value"); - - // Test 2: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1) - strcpy(line, "not a key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); - - // Test 3: - // -- Setup - DUMB_KEYFINDER(keys[0],"key", ": "); - DUMB_PARSER(parser, keys, 1); - strcpy(line, "key:value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); - - // Test 4: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_KEYFINDER(keys[1], "second_key", ": "); - DUMB_PARSER(parser, keys, 2); - strcpy(line, "second_key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_true); - TEST_PTR(found_key_finder, &keys[1]); - TEST_STR(raw_value, "value"); - - // Test 5: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); - strcpy(line, ""); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - TEST_BOOLEAN(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); +void test_match() +{ + printf("==== TEST match() ====\n"); + // usefull variable : + bool _true = true; + bool _false = false; + KeyFinder keys[10]; + char line[100]; + Parser parser; + bool result; + KeyFinder *found_key_finder = NULL; + char *raw_value = NULL; + + // Test 1: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, "key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_true); + TEST_PTR(found_key_finder, &keys[0]); + TEST_STR(raw_value, "value"); + + // Test 2: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1) + strcpy(line, "not a key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); + + // Test 3: + // -- Setup + DUMB_KEYFINDER(keys[0],"key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, "key:value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); + + // Test 4: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_KEYFINDER(keys[1], "second_key", ": "); + DUMB_PARSER(parser, keys, 2); + strcpy(line, "second_key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + TEST_BOOLEAN(&result, &_true); + TEST_PTR(found_key_finder, &keys[1]); + TEST_STR(raw_value, "value"); + + // Test 5: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, ""); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); } -int main() { - test_replace_first(); - test_split_on_delimiter(); - test_start_with(); - test_match(); - return 0; +int main() +{ + test_replace_first(); + test_split_on_delimiter(); + test_start_with(); + test_match(); + return 0; } #endif -- GitLab From 70ab4642ad532768f79a24f02059652c99d38fc5 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 14:27:26 +0000 Subject: [PATCH 044/125] add macros and fix --- src/util.c | 27 ++++++++++++++++++++++++--- src/util.h | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/util.c b/src/util.c index 5ff3acd..93db7f1 100644 --- a/src/util.c +++ b/src/util.c @@ -1,6 +1,27 @@ +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #include "util.h" -inline uint64_t substractAcc(const uint64_t l, const uint64_t r) +uint64_t modulo_substraction(uint64_t previous, uint64_t new) { - return (l < r) ? UINT64_MAX + (l - r) : l - r; -} \ No newline at end of file + return new > previous ? (previous - new) + : (UINT64_MAX - new) + previous; +} diff --git a/src/util.h b/src/util.h index 1fff9af..6d4a644 100644 --- a/src/util.h +++ b/src/util.h @@ -1,10 +1,43 @@ +/******************************************************* + Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #ifndef _UTIL_H #define _UTIL_H -//#warning "TODO: Add licence" - #include <stdint.h> -inline uint64_t substractAcc(const uint64_t l, const uint64_t r); +#define CASSERT(predicate, file) _impl_CASSERT_LINE(predicate,__LINE__,file) + +#define _impl_PASTE(a,b) a##b +#define _impl_CASSERT_LINE(predicate, line, file) \ + typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; + +#define UNUSED(expr) do { (void)(expr); } while (0) +#define PANIC(code, fmt, ...) \ + do { \ + fprintf(stderr, "Exit on error: "); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + exit(code); \ + } while (0) + +uint64_t modulo_substraction(const uint64_t l, const uint64_t r); #endif -- GitLab From a6968e0e1db4392913c4a9313fd1ce3acacc0f33 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 23 Jan 2023 16:25:46 +0100 Subject: [PATCH 045/125] remove useless include generated by src/counters_option.sh (<linux/perf_event.h> is already included in src/counters.c) plus make it so that it generates a correctly formated code --- src/counters_option.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/counters_option.sh b/src/counters_option.sh index 5d1e577..7c99eba 100644 --- a/src/counters_option.sh +++ b/src/counters_option.sh @@ -5,12 +5,11 @@ linux_include=/usr/include/linux/perf_event.h -echo '#include <linux/perf_event.h> - +echo ' typedef struct counter_option { - char *name; - __u32 perf_type; - __u64 perf_key; + char *name; + __u32 perf_type; + __u64 perf_key; } counter_option; static counter_option perf_static_info[] = {' @@ -39,7 +38,7 @@ while IFS= read line; do esac if [ "$mode" != 'PERF_TYPE_HW_CACHE' ]; then - printf '{ .name = "%s", .perf_type = %s, .perf_key = %s},\n' \ + printf ' { .name = "%s", .perf_type = %s, .perf_key = %s},\n' \ "$short_perf" \ "$mode" \ "$perf_name" @@ -64,7 +63,7 @@ while IFS= read line; do result_id_str=${result_id% *} result_id_name=${result_id#* } - printf '{' + printf ' {' printf ' .name = "%s_%s_%s",' \ "$short_perf" \ "$op_id_str" \ @@ -85,5 +84,5 @@ done < "$linux_include" echo '};' -printf 'static unsigned int nb_counter_option = %d;\n' "$nb" +printf '\nstatic unsigned int nb_counter_option = %d;\n' "$nb" -- GitLab From 202d36be49dd1fbc16352460bbd6e43287a2eeea Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 23 Jan 2023 16:28:50 +0100 Subject: [PATCH 046/125] add basic system detection in configure.sh --- configure.sh | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/configure.sh b/configure.sh index 746f129..6a957ff 100755 --- a/configure.sh +++ b/configure.sh @@ -4,9 +4,19 @@ try() { "$@" || die "cannot $*"; } die() { yell "$*"; exit 111; } yell() { echo "$0: $*" >&2; } echo() { printf '%s\n' "$*"; } +isnum() { + case "${1#[+-]}" in + *[!0-9]*|'') return 1 ;; + *) return 0 ;; + esac +} target=src/captors.h -hdr_blacklist='counters_option|optparse|captors' + +noncaptor='counters_option|optparse|captors' + +hdr_blacklist=$noncaptor +hdr_whitelist='' usage() { printf -- 'Usage: %s [-l] [-e <captor>] [-i <captor>]\n' "$(basename "$0")" >&2 @@ -18,7 +28,12 @@ usage() { ls_captors() { try cd src - ls *.h | grep -vE "($hdr_blacklist)" | sed 's/\.h$//' + printf -- 'captors:\n' >&2 + ls -1 *.h | + grep -vE "^($hdr_blacklist)\.h$" | + grep -E "^($hdr_whitelist)\.h$" | + sed 's/\.h$//' | + tee /dev/stderr } gen_captors_h() { @@ -44,8 +59,8 @@ gen_captors_h() { while [ "$1" ]; do case $1 in --include|-i) - # no-op for now - : + shift; [ "$1" ] || usage + hdr_whitelist="${hdr_whitelist}|${1}" ;; --exclude|-e) shift; [ "$1" ] || usage @@ -62,4 +77,32 @@ while [ "$1" ]; do shift done +[ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters +[ -d /sys/class/infiniband ] && hdr_whitelist=${hdr_whitelist}|infiniband +[ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load" + +if [ -r /proc/net/route ]; then + dev=$(awk 'NR == 2 { print $1 }' /proc/net/route) + [ -e "/sys/class/net/$dev" ] && hdr_whitelist="${hdr_whitelist}|network" +fi + +vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) +vendor_lc=$(echo "$vendor" | tr 'A-Z' 'a-z') +case $vendor_lc in +*intel*) + hdr_whitelist="${hdr_whitelist}|rapl" + ;; +*amd*) + family=$(awk '/cpu[ \t]*family/ {print $3; exit}' /proc/cpuinfo) + if isnum "$family"; then + [ $family -ge 17 ] && hdr_whitelist="${hdr_whitelist}|amd_rapl" + fi + ;; +*) + yell "unsupported processor vendor id: $vendor" + ;; +esac + +[ $(ls -1 /sys/class/hwmon | wc -l) -gt 0 ] && hdr_whitelist="${hdr_whitelist}|temperature" + gen_captors_h > "$target" -- GitLab From 72f4dc47c84f28f93748969be20d8d819c13afd9 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 17:39:34 +0000 Subject: [PATCH 047/125] on test --- makefile | 2 +- src/amd_rapl.c | 114 ++++++++++++++++++++++++++++++---------------- src/info_reader.c | 6 ++- src/util.c | 6 +-- 4 files changed, 82 insertions(+), 46 deletions(-) diff --git a/makefile b/makefile index c43c867..6e47e9e 100644 --- a/makefile +++ b/makefile @@ -10,7 +10,7 @@ OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o OBJECTS_GRP = $(subst _individual,_group, $(OBJECTS)) CC = gcc -CFLAGS = -std=gnu99 -O3 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function +CFLAGS = -std=gnu99 -Wall -Wextra -Werror -Wpedantic -Wno-unused-function ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q diff --git a/src/amd_rapl.c b/src/amd_rapl.c index b83ded9..cb06472 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -53,7 +53,7 @@ struct cpu_sensor_t { size_t package_id; char *name; - int *fd; + int fd; uint64_t energy_units; uint64_t core_energy; uint64_t pkg_energy; @@ -141,10 +141,12 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) #ifdef DEBUG void debug_print_sensor(cpu_sensor_t *sensor) { - CASSERT(sizeof(cpu_sensor_t) == 40, amd_rapl_c); - printf("cpu_id : %ld, package_id : %ld, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", + CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); + printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", sensor->cpu_id, sensor->package_id, + sensor->name, + sensor->fd, sensor->energy_units, sensor->core_energy, sensor->pkg_energy @@ -154,21 +156,13 @@ void debug_print_sensor(cpu_sensor_t *sensor) void debug_print_amd_rapl(_amd_rapl_t *rapl) { for (unsigned int i = 0; i < rapl->nb; i++) { - debug_print_sensor(rapl->sensors[i]); + debug_print_sensor(&rapl->sensors[i]); } } #endif - - // ---------------------------AMD_RAPL_UTIL -uint64_t modulo_substraction(uint64_t previous, u_int64_t new) -{ - return new > previous ? (previous - new) - : (UINT64_MAX - new) + previous; -} - unsigned int get_nb_cpu() { char filename[BUFFER_SIZE]; @@ -186,9 +180,16 @@ unsigned int get_nb_cpu() return n_cpu; } +char* get_name(size_t cpu_id) { + static const char *base_name = "core%ld"; + size_t memory_needed = snprintf(NULL, 0, base_name, cpu_id); + char* name = (char *)calloc(memory_needed, sizeof(char)); + snprintf(name, memory_needed, base_name, cpu_id); + return name; +} + void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) { - static const char *base_name = "core%ld"; static char filename[BUFFER_SIZE]; sprintf(filename, base_str, cpu_id); @@ -202,7 +203,8 @@ void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) u_int64_t raw_pkg_energy = read_raw_pkg_energy(fd); sensor->cpu_id = cpu_id; - asprintf(sensor->name, base_name, sensor->cpu_id); + sensor->name = get_name(cpu_id); + sensor->fd = fd; sensor->energy_units = read_unit(fd); sensor->core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); sensor->pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); @@ -211,9 +213,9 @@ void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) u_int64_t get_core_energy(cpu_sensor_t *sensor) { u_int64_t raw_core_energy = read_raw_core_energy(sensor->fd); - u_int64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units) + u_int64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - u_int64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); + u_int64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); sensor->core_energy = core_energy; return energy_consumed; } @@ -221,13 +223,18 @@ u_int64_t get_core_energy(cpu_sensor_t *sensor) u_int64_t get_pkg_energy(cpu_sensor_t *sensor) { u_int64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); - u_int64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units) - - u_int64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); + u_int64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); + + u_int64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); sensor->pkg_energy = pkg_energy; return energy_consumed; } +void clean_cpu_sensor(cpu_sensor_t* sensor) { + close(sensor->fd); + free(sensor->name); +} + // ----------------------AMD_RAPL_INTERFACE @@ -273,7 +280,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) exit(127); } - cpu_sensor_tr *cpus = (cpu_sensor_t *) calloc(nb_cpu, sizeof(cpu_sensor_t)); + cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(nb_cpu, sizeof(cpu_sensor_t)); rapl->nb = nb_cpu; rapl->sensors = cpus; @@ -281,43 +288,70 @@ unsigned int init_amd_rapl(char *none, void **ptr) for (unsigned int i = 0; i < nb_cpu; i++) { init_cpu_sensor(&rapl->sensors[i], i); } + + *ptr = (void*) rapl; return rapl->nb; } -unsigned int get_amd_rapl(uint64_t results, void *ptr) +unsigned int get_amd_rapl(uint64_t *results, void *ptr) { - _amd_rapl_t *rapl = (_amd_rapl_t) ptr; + _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { // TODO: check if unit is the same #warning "check if unit is the same" - results[i] = get_core_energy(rapl->sensors[i]); + results[i] = get_core_energy(&rapl->sensors[i]); } return rapl->nb; } +void label_amd_rapl(char **labels, void* ptr) { + _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; + for (unsigned int i = 0; i < rapl->nb; i++) { + labels[i] = rapl->sensors[i].name; + } +} + +void clean_amd_rapl(void *ptr) { + _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; + + for (unsigned int i = 0; i < rapl->nb; ++i) { + clean_cpu_sensor(&rapl->sensors[i]); + } + free(rapl->sensors); + free(rapl); +} int main() { - _amd_rapl_t *rapl = (_amd_rapl_t *)malloc(sizeof(_amd_rapl_t)); - init_amd_rapl(rapl); - print_amd_rapl(rapl); - sleep(1); - print_amd_rapl(rapl); - sleep(1); - print_amd_rapl(rapl); - sleep(1); - print_amd_rapl(rapl); - sleep(1); - print_amd_rapl(rapl); - sleep(1); - print_amd_rapl(rapl); - sleep(1); - print_amd_rapl(rapl); - - free_amd_rapl(rapl); + static const unsigned int time = 10; + _amd_rapl_t *rapl = NULL; + unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); + uint64_t results[nb_cpu]; + char* labels[nb_cpu]; + + label_amd_rapl(labels, (void *) rapl); + + for (unsigned int i = 0; i < rapl->nb; ++i) { + printf("%s ", labels[i]); + } + printf("\n"); + + // -- Run + + for (unsigned int i = 0; i < time; ++i) { + sleep(1); + get_amd_rapl(results, (void*)rapl); + + for (unsigned int j = 0; j < rapl->nb; ++j) { + printf("%ln ", results); + } + printf("\n"); + } + + clean_amd_rapl(rapl); return 0; } diff --git a/src/info_reader.c b/src/info_reader.c index e2563c6..19d84de 100644 --- a/src/info_reader.c +++ b/src/info_reader.c @@ -64,10 +64,12 @@ struct cpu_sensor_t { #warning "Check the reset of the msr registers" size_t cpu_id; size_t package_id; + char *name; + int *fd; uint64_t energy_units; - uint64_t core_energy_status; - uint64_t pkg_energy_status; + uint64_t core_energy; + uint64_t pkg_energy; }; int main(int argc, char const *argv[]) diff --git a/src/util.c b/src/util.c index 186434b..fe3efa1 100644 --- a/src/util.c +++ b/src/util.c @@ -20,8 +20,8 @@ #include "util.h" -uint64_t modulo_substraction(uint64_t previous, u_int64_t new) +uint64_t modulo_substraction(uint64_t previous, uint64_t new) { - return new > previous ? (previous - new) - : (UINT64_MAX - new) + previous; + return new > previous ? (new - previous) + : (UINT64_MAX - previous) + new; } -- GitLab From 0e4a69d26e8f33cc9caf44fe52405b27353208d5 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 23 Jan 2023 17:40:59 +0000 Subject: [PATCH 048/125] fix: util.c --- src/util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util.c b/src/util.c index 93db7f1..fe3efa1 100644 --- a/src/util.c +++ b/src/util.c @@ -22,6 +22,6 @@ uint64_t modulo_substraction(uint64_t previous, uint64_t new) { - return new > previous ? (previous - new) - : (UINT64_MAX - new) + previous; + return new > previous ? (new - previous) + : (UINT64_MAX - previous) + new; } -- GitLab From 28b96095c1c5aa814fcb89ac261c68eee5f103e0 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 09:56:37 +0000 Subject: [PATCH 049/125] separate test lib --- src/info_reader.h | 102 ++------------------------------------- src/small_test.h | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 97 deletions(-) create mode 100644 src/small_test.h diff --git a/src/info_reader.h b/src/info_reader.h index 4717841..40948bd 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -226,99 +226,7 @@ static bool start_with(const char *prefix, const char *string) #ifdef __TESTING__ - -#define FMT_NULL(string) \ - string = string ? string : "NULL" - -#define TEST_STR(result, expected) \ - test_str(__FILE__, __LINE__, result, expected) - -#define TEST_BOOLEAN(result, expected) \ - test_boolean(__FILE__, __LINE__, result, expected) - -#define TEST_PTR(result, expected) \ - test_ptr(__FILE__, __LINE__, result, expected) - -typedef int (Comparator) (void *, void *); -typedef char *(Formatter) (char *, void *); - -int string_compare(char *string1, char *string2) -{ - if (string1 == NULL && string2 == NULL) { - return 1; - } else if (string1 == NULL || string2 == NULL) { - return 0; - } else { - return (strcmp(string1, string2) == 0); - } -} - -char *string_format(__attribute__((unused)) char *buffer, char *string) -{ - return FMT_NULL(string); -} - - -int boolean_compare(bool *boolean1, bool *boolean2) -{ - return *boolean1 == *boolean2; -} - -char *boolean_format(__attribute__((unused)) char *buffer, bool *boolean) -{ - return *boolean ? "True" : "False"; -} - -int ptr_compare(void *ptr1, void *ptr2) -{ - return ptr1 == ptr2; -} - -char *ptr_format(char *buffer, void *ptr) -{ - sprintf(buffer, "%p", ptr); - return buffer; -} - -void test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) -{ - static char buffer_result[1000]; - static char buffer_expected[1000]; - if (compare(result, expected) == 0) { - printf("Test %s:%d failed: expected %s, got %s\n", - file, - line, - format(buffer_result, expected), - format(buffer_expected, result) - ); - } else { - printf("Test %s:%d passed\n", file, line); - } -} - -void test_str(char *file, int line, char *result, char *expected) -{ - Comparator *compare = (Comparator *) string_compare; - Formatter *format = (Formatter *) string_format; - - test(file, line, result, expected, compare, format); -} - -void test_boolean(char *file, int line, bool *result, bool *expected) -{ - Comparator *compare = (Comparator *) boolean_compare; - Formatter *format = (Formatter *) boolean_format; - - test(file, line, (void *) result, (void *) expected, compare, format); -} - -void test_ptr(char *file, int line, void *result, void *expected) -{ - Comparator *compare = (Comparator *) ptr_compare; - Formatter *format = (Formatter *) ptr_format; - - test(file, line, result, expected, compare, format); -} +#include "small_test.h" void test_replace_first() { @@ -414,21 +322,21 @@ void test_start_with() key_finder = (KeyFinder) { \ key, \ delimiter, \ - NULL, \ - NULL \ + 0, \ + 0 \ }; \ } while (0); #define DUMB_PARSER(parser, keys, nb_keys) \ do { \ parser = (Parser) { \ - NULL, \ + 0, \ 0, \ 0, \ 0, \ keys, \ nb_keys, \ - NULL \ + 0 \ }; \ } while (0); diff --git a/src/small_test.h b/src/small_test.h new file mode 100644 index 0000000..a63cca8 --- /dev/null +++ b/src/small_test.h @@ -0,0 +1,119 @@ +#ifndef __SMALL_TEST_H +#define __SMALL_TEST_H + +#define FMT_NULL(string) \ + string = string ? string : "NULL" + +#define TEST_STR(result, expected) \ + test_str(__FILE__, __LINE__, result, expected) + +#define TEST_BOOLEAN(result, expected) \ + test_boolean(__FILE__, __LINE__, result, expected) + +#define TEST_PTR(result, expected) \ + test_ptr(__FILE__, __LINE__, result, expected) + +#define TEST_UINT64_T(result, expected) \ + test_uint64_t(__FILE__, __LINE__, result, expected) + +typedef int (Comparator) (void *, void *); +typedef char *(Formatter) (char *, void *); + +int string_compare(char *string1, char *string2) +{ + if (string1 == NULL && string2 == NULL) { + return 1; + } else if (string1 == NULL || string2 == NULL) { + return 0; + } else { + return (strcmp(string1, string2) == 0); + } +} + +char *string_format(__attribute__((unused)) char *buffer, char *string) +{ + return FMT_NULL(string); +} + + +int boolean_compare(bool *boolean1, bool *boolean2) +{ + return *boolean1 == *boolean2; +} + +char *boolean_format(__attribute__((unused)) char *buffer, bool *boolean) +{ + return *boolean ? "True" : "False"; +} + +int ptr_compare(void *ptr1, void *ptr2) +{ + return ptr1 == ptr2; +} + +char *ptr_format(char *buffer, void *ptr) +{ + sprintf(buffer, "%p", ptr); + return buffer; +} + + +int uint64_t_compare(uint64_t *value1, uint64_t *value2) +{ + return *value1 == *value2; +} + +char *uint64_t_format(char *buffer, uint64_t *value) +{ + sprintf(buffer, "%ld", *value); + return buffer; +} + +void test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) +{ + static char buffer_result[1000]; + static char buffer_expected[1000]; + if (compare(result, expected) == 0) { + printf("Test %s:%d failed: expected %s, got %s\n", + file, + line, + format(buffer_result, expected), + format(buffer_expected, result) + ); + } else { + printf("Test %s:%d passed\n", file, line); + } +} + +void test_str(char *file, int line, char *result, char *expected) +{ + Comparator *compare = (Comparator *) string_compare; + Formatter *format = (Formatter *) string_format; + + test(file, line, result, expected, compare, format); +} + +void test_boolean(char *file, int line, bool *result, bool *expected) +{ + Comparator *compare = (Comparator *) boolean_compare; + Formatter *format = (Formatter *) boolean_format; + + test(file, line, (void *) result, (void *) expected, compare, format); +} + +void test_ptr(char *file, int line, void *result, void *expected) +{ + Comparator *compare = (Comparator *) ptr_compare; + Formatter *format = (Formatter *) ptr_format; + + test(file, line, result, expected, compare, format); +} + +void test_uint64_t(char *file, int line, void *result, void *expected) +{ + Comparator *compare = (Comparator *) uint64_t_compare; + Formatter *format = (Formatter *) uint64_t_format; + + test(file, line, (uint64_t *)result, (uint64_t *)expected, compare, format); +} +#endif -- GitLab From 56d5175173c643446298bb199b6bb2f1e8315056 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 09:56:57 +0000 Subject: [PATCH 050/125] building tests --- src/amd_rapl.c | 192 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 139 insertions(+), 53 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index cb06472..9bdfbed 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -44,7 +44,6 @@ static const uint64_t energy_pkg_msr = 0xC001029B; // ------------------------------FILE_PATHS static const char *base_str = "/dev/cpu/%d/msr"; -static const char *cpuinfo = "/proc/cpuinfo"; struct cpu_sensor_t { //TODO: check the reset of the msr registers @@ -68,6 +67,8 @@ typedef struct _amd_rapl_t _amd_rapl_t; // -----------------------------INFO_READER +#ifdef __READ_CPUINFO__ +static const char *cpuinfo = "/proc/cpuinfo"; static GenericPointer _size_t_allocator(char *s) { size_t value = atoi(s); @@ -90,6 +91,7 @@ static KeyFinder keys[NB_KEYS] = { {"processor", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_cpu_id}, {"physical id", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_package_id} }; +#endif // --------------------------------READ_MSR @@ -107,7 +109,7 @@ uint64_t read_msr(int fd, uint64_t msr) uint64_t read_unit(int fd) { u_int64_t unit = read_msr(fd, msr_rapl_power_unit); - return (unit & amd_energy_unit_mask) >> 8; + return ((unit & amd_energy_unit_mask) >> 8); } uint64_t read_raw_core_energy(int fd) @@ -126,14 +128,17 @@ uint64_t read_raw_pkg_energy(int fd) uint64_t raw_to_microjoule(uint64_t raw, uint64_t unit) { + static const uint64_t to_microjoule = 1000000UL; // raw * (1 / (unit^2)) -> Joule - // Joule * 1000000 -> microjoule - return (raw * 1000000UL) / (1ul << unit); + // Joule * 1000000 -> uJoule + uint64_t microjoule = (raw * to_microjoule) / (1UL << unit); + return microjoule; } uint64_t raw_to_joule(uint64_t raw, uint64_t unit) { - // raw * (1 / (unit^2)) -> Joule - return raw / (1ul << unit); + // raw * (1 / (unit^2)) -> Joule + int64_t joule = raw / (1UL << unit); + return joule; } // -----------------------------------DEBUG @@ -141,12 +146,12 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) #ifdef DEBUG void debug_print_sensor(cpu_sensor_t *sensor) { - CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", + //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); + printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", sensor->cpu_id, sensor->package_id, - sensor->name, - sensor->fd, + sensor->name, + sensor->fd, sensor->energy_units, sensor->core_energy, sensor->pkg_energy @@ -159,6 +164,21 @@ void debug_print_amd_rapl(_amd_rapl_t *rapl) debug_print_sensor(&rapl->sensors[i]); } } + +// typedef struct { +// size_t cpu_id; +// uint64_t *results; +// size_t capacity; +// } CpuLogger; +// +// CpuLogger init_logger(size_t cpu_id, size_t capacity) +// { +// +// } +// +// void log_value(); + + #endif // ---------------------------AMD_RAPL_UTIL @@ -180,12 +200,13 @@ unsigned int get_nb_cpu() return n_cpu; } -char* get_name(size_t cpu_id) { +char *get_name(size_t cpu_id) +{ static const char *base_name = "core%ld"; - size_t memory_needed = snprintf(NULL, 0, base_name, cpu_id); - char* name = (char *)calloc(memory_needed, sizeof(char)); - snprintf(name, memory_needed, base_name, cpu_id); - return name; + static const size_t max_lenght = 20; + char *name = (char *)calloc(max_lenght, sizeof(char)); + snprintf(name, max_lenght, base_name, cpu_id); + return name; } void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) @@ -203,8 +224,8 @@ void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) u_int64_t raw_pkg_energy = read_raw_pkg_energy(fd); sensor->cpu_id = cpu_id; - sensor->name = get_name(cpu_id); - sensor->fd = fd; + sensor->name = get_name(cpu_id); + sensor->fd = fd; sensor->energy_units = read_unit(fd); sensor->core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); sensor->pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); @@ -215,7 +236,7 @@ u_int64_t get_core_energy(cpu_sensor_t *sensor) u_int64_t raw_core_energy = read_raw_core_energy(sensor->fd); u_int64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - u_int64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); + u_int64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); sensor->core_energy = core_energy; return energy_consumed; } @@ -224,15 +245,16 @@ u_int64_t get_pkg_energy(cpu_sensor_t *sensor) { u_int64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); u_int64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); - - u_int64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); + + u_int64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); sensor->pkg_energy = pkg_energy; return energy_consumed; } -void clean_cpu_sensor(cpu_sensor_t* sensor) { - close(sensor->fd); - free(sensor->name); +void clean_cpu_sensor(cpu_sensor_t *sensor) +{ + close(sensor->fd); + free(sensor->name); } // ----------------------AMD_RAPL_INTERFACE @@ -289,7 +311,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) init_cpu_sensor(&rapl->sensors[i], i); } - *ptr = (void*) rapl; + *ptr = (void *) rapl; return rapl->nb; } @@ -305,53 +327,117 @@ unsigned int get_amd_rapl(uint64_t *results, void *ptr) return rapl->nb; } -void label_amd_rapl(char **labels, void* ptr) { - _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; +void label_amd_rapl(char **labels, void *ptr) +{ + _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { - labels[i] = rapl->sensors[i].name; + labels[i] = rapl->sensors[i].name; } } -void clean_amd_rapl(void *ptr) { - _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; +void clean_amd_rapl(void *ptr) +{ + _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; ++i) { - clean_cpu_sensor(&rapl->sensors[i]); - } - free(rapl->sensors); - free(rapl); + for (unsigned int i = 0; i < rapl->nb; ++i) { + clean_cpu_sensor(&rapl->sensors[i]); + } + free(rapl->sensors); + free(rapl); } +#ifdef __TESTING_AMD__ +#include "small_test.h" + +void test_raw_to_microjoule() { + printf("==== TEST raw_to_microjoule() ====\n"); + uint64_t raw = 0; + uint64_t unit = 0; + uint64_t result = 0; + uint64_t expected = 0; + + // Test 1: + // -- Setup + raw = 100; + unit = 0; + expected = 100000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 2: + // -- Setup + raw = 200; + unit = 1; + expected = 100000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 3: + // -- Setup + raw = 500; + unit = 2; + expected = 125000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 4: + // -- Setup + raw = 1000; + unit = 3; + expected = 125000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 5: + // -- Setup + raw = 10000; + unit = 4; + expected = 625000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); +} int main() { - static const unsigned int time = 10; - _amd_rapl_t *rapl = NULL; + test_raw_to_microjoule(); + static const unsigned int time = 10; + _amd_rapl_t *rapl = NULL; unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); - uint64_t results[nb_cpu]; - char* labels[nb_cpu]; + uint64_t results[nb_cpu]; + char *labels[nb_cpu]; - label_amd_rapl(labels, (void *) rapl); + label_amd_rapl(labels, (void *) rapl); - for (unsigned int i = 0; i < rapl->nb; ++i) { - printf("%s ", labels[i]); - } - printf("\n"); + for (unsigned int i = 0; i < rapl->nb; ++i) { + printf("%s ", labels[i]); + } + printf("\n"); - // -- Run + // -- Run - for (unsigned int i = 0; i < time; ++i) { - sleep(1); - get_amd_rapl(results, (void*)rapl); + for (unsigned int i = 0; i < time; ++i) { + sleep(1); + get_amd_rapl(results, (void *)rapl); - for (unsigned int j = 0; j < rapl->nb; ++j) { - printf("%ln ", results); - } - printf("\n"); - } + for (unsigned int j = 0; j < rapl->nb; ++j) { + printf("%ld ", results[j]); + } + printf("\n"); + } - clean_amd_rapl(rapl); + clean_amd_rapl(rapl); return 0; } +#endif -- GitLab From 6f7fa2eab376fe5625bf43906822bb5ba9543a29 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 12:13:51 +0000 Subject: [PATCH 051/125] add tests --- src/amd_rapl.c | 117 +++++++++++++++++++++++++++++++++++++++++++++-- src/small_test.h | 5 ++ 2 files changed, 117 insertions(+), 5 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 9bdfbed..4877825 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -30,10 +30,7 @@ #include "util.h" #include "amd_rapl.h" -#warning "Must be modified before release" #define BUFFER_SIZE 64 -#define MAX_CPUS 64 -#define NB_KEYS 2 // ---------------------------MSR_REGISTERS static const uint64_t amd_energy_mask = 0xFFFFFFFF; @@ -46,8 +43,6 @@ static const uint64_t energy_pkg_msr = 0xC001029B; static const char *base_str = "/dev/cpu/%d/msr"; struct cpu_sensor_t { - //TODO: check the reset of the msr registers -#warning "Check the reset of the msr registers" size_t cpu_id; size_t package_id; char *name; @@ -68,6 +63,11 @@ typedef struct _amd_rapl_t _amd_rapl_t; // -----------------------------INFO_READER #ifdef __READ_CPUINFO__ + +#warning "Must be modified before release" +#define MAX_CPUS 64 +#define NB_KEYS 2 + static const char *cpuinfo = "/proc/cpuinfo"; static GenericPointer _size_t_allocator(char *s) { @@ -408,9 +408,116 @@ void test_raw_to_microjoule() { TEST_UINT64_T(&result, &expected); } +void test_get_name() { + printf("==== TEST get_name() ====\n"); + size_t cpu_id = 0; + char* result = NULL; + char expected[100]; + + // TEST 1: + // -- Setup + cpu_id = 0; + strcpy(expected, "core0"); + // -- Run + result = get_name(cpu_id); + // -- Verification + TEST_STR(result, expected); + free(result); + + // TEST 2: + // -- Setup + cpu_id = 10000; + strcpy(expected, "core10000"); + // -- Run + result = get_name(cpu_id); + // -- Verification + TEST_STR(result, expected); + free(result); +} + +#define NONE 0 +#define DUMB_SENSOR(sensor, cpu_id, name) \ + do { \ + sensor = (cpu_sensor_t) { \ + cpu_id, \ + NONE, \ + name, \ + NONE, \ + NONE, \ + NONE, \ + NONE \ + }; \ + } while(0); + +#define DUMB_RAPL(rapl, sensors, nb) \ + do { \ + rapl = (_amd_rapl_t) { \ + sensors, \ + nb \ + }; \ + } while(0); + +void test_label_amd_rapl() { + printf("==== TEST label_amd_rapl() ====\n"); + cpu_sensor_t sensors[100]; + _amd_rapl_t rapl; + char *results[100]; + char expecteds[10][100]; + uint64_t nb = 0; + + // Test 1: + // -- Setup + nb = 1; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + // -- Run + label_amd_rapl(results, (void*) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + + // Test 2: + // -- Setup + nb = 4; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_SENSOR(sensors[1], 1, "core1"); + DUMB_SENSOR(sensors[2], 2, "core2"); + DUMB_SENSOR(sensors[3], 3, "core3"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + strcpy(expecteds[1], "core1"); + strcpy(expecteds[2], "core2"); + strcpy(expecteds[3], "core3"); + // -- Run + label_amd_rapl(results, (void*) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + + // Test 3: + // -- Setup + nb = 4; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_SENSOR(sensors[1], 3, "core3"); + DUMB_SENSOR(sensors[2], 1, "core1"); + DUMB_SENSOR(sensors[3], 2, "core2"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + strcpy(expecteds[1], "core3"); + strcpy(expecteds[2], "core1"); + strcpy(expecteds[3], "core2"); + // -- Run + label_amd_rapl(results, (void*) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); +} + + int main() { test_raw_to_microjoule(); + test_get_name(); + test_label_amd_rapl(); + static const unsigned int time = 10; _amd_rapl_t *rapl = NULL; unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); diff --git a/src/small_test.h b/src/small_test.h index a63cca8..b8673dd 100644 --- a/src/small_test.h +++ b/src/small_test.h @@ -16,6 +16,11 @@ #define TEST_UINT64_T(result, expected) \ test_uint64_t(__FILE__, __LINE__, result, expected) +#define TEST_T_ARRAY(function, size, results, expecteds) \ + for (unsigned int i = 0; i < size; i++) { \ + function(results[i], expecteds[i]); \ + } + typedef int (Comparator) (void *, void *); typedef char *(Formatter) (char *, void *); -- GitLab From 79214a8bf2356abb3ca5996c01ae5775999704e2 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 13:11:53 +0000 Subject: [PATCH 052/125] add make tests --- .gitignore | 1 + makefile | 10 +- src/amd_rapl.c | 293 +++++++++--------- src/info_reader.h | 211 ------------- tests/amd_rapl.c | 220 +++++++++++++ .../example_info_reader.c | 2 +- tests/info_reader.c | 233 ++++++++++++++ tests/main.c | 13 + {src => tests}/small_test.h | 36 ++- 9 files changed, 647 insertions(+), 372 deletions(-) create mode 100644 tests/amd_rapl.c rename src/info_reader.c => tests/example_info_reader.c (98%) create mode 100644 tests/info_reader.c create mode 100644 tests/main.c rename {src => tests}/small_test.h (69%) diff --git a/.gitignore b/.gitignore index 5a8f74f..ca55d73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o src/counters_option.h +tests/tests bin obj diff --git a/makefile b/makefile index 6e47e9e..15503a9 100644 --- a/makefile +++ b/makefile @@ -1,9 +1,10 @@ -.PHONY: all clean mojitos mojitos_group debug format +.PHONY: all clean mojitos mojitos_group debug format tests SRC_DIR = src DOC_DIR = doc OBJ_DIR = obj BIN_DIR = bin +TESTS_DIR = tests OBJECTS = $(addprefix $(OBJ_DIR)/, mojitos.o counters.o rapl.o network.o load.o infiniband.o temperature.o util.o) @@ -42,10 +43,17 @@ $(BIN_DIR): debug: CFLAGS += -DDEBUG -g debug: all +tests: + gcc -Wall -Wextra -Wpedantic $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/tests + $(TESTS_DIR)/tests + format: $(ASTYLE) $(SRC_DIR)/*.c $(SRC_DIR)/*.h $(ASTYLE) $(DOC_DIR)/*.c $(DOC_DIR)/*.h + $(ASTYLE) $(TESTS_DIR)/*.c $(TESTS_DIR)/*.h + clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \rm -f $(SRC_DIR)/counters_option.h + \rm $(TESTS_DIR)/tests diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 4877825..91b6009 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -128,17 +128,17 @@ uint64_t read_raw_pkg_energy(int fd) uint64_t raw_to_microjoule(uint64_t raw, uint64_t unit) { - static const uint64_t to_microjoule = 1000000UL; + static const uint64_t to_microjoule = 1000000UL; // raw * (1 / (unit^2)) -> Joule // Joule * 1000000 -> uJoule - uint64_t microjoule = (raw * to_microjoule) / (1UL << unit); - return microjoule; + uint64_t microjoule = (raw * to_microjoule) / (1UL << unit); + return microjoule; } uint64_t raw_to_joule(uint64_t raw, uint64_t unit) { - // raw * (1 / (unit^2)) -> Joule - int64_t joule = raw / (1UL << unit); - return joule; + // raw * (1 / (unit^2)) -> Joule + int64_t joule = raw / (1UL << unit); + return joule; } // -----------------------------------DEBUG @@ -170,12 +170,12 @@ void debug_print_amd_rapl(_amd_rapl_t *rapl) // uint64_t *results; // size_t capacity; // } CpuLogger; -// +// // CpuLogger init_logger(size_t cpu_id, size_t capacity) // { -// +// // } -// +// // void log_value(); @@ -350,89 +350,91 @@ void clean_amd_rapl(void *ptr) #ifdef __TESTING_AMD__ #include "small_test.h" -void test_raw_to_microjoule() { - printf("==== TEST raw_to_microjoule() ====\n"); - uint64_t raw = 0; - uint64_t unit = 0; - uint64_t result = 0; - uint64_t expected = 0; - - // Test 1: - // -- Setup - raw = 100; - unit = 0; - expected = 100000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 2: - // -- Setup - raw = 200; - unit = 1; - expected = 100000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 3: - // -- Setup - raw = 500; - unit = 2; - expected = 125000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 4: - // -- Setup - raw = 1000; - unit = 3; - expected = 125000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 5: - // -- Setup - raw = 10000; - unit = 4; - expected = 625000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); +void test_raw_to_microjoule() +{ + printf("==== TEST raw_to_microjoule() ====\n"); + uint64_t raw = 0; + uint64_t unit = 0; + uint64_t result = 0; + uint64_t expected = 0; + + // Test 1: + // -- Setup + raw = 100; + unit = 0; + expected = 100000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 2: + // -- Setup + raw = 200; + unit = 1; + expected = 100000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 3: + // -- Setup + raw = 500; + unit = 2; + expected = 125000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 4: + // -- Setup + raw = 1000; + unit = 3; + expected = 125000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); + + // TEST 5: + // -- Setup + raw = 10000; + unit = 4; + expected = 625000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + TEST_UINT64_T(&result, &expected); } -void test_get_name() { - printf("==== TEST get_name() ====\n"); - size_t cpu_id = 0; - char* result = NULL; - char expected[100]; - - // TEST 1: - // -- Setup - cpu_id = 0; - strcpy(expected, "core0"); - // -- Run - result = get_name(cpu_id); - // -- Verification - TEST_STR(result, expected); - free(result); - - // TEST 2: - // -- Setup - cpu_id = 10000; - strcpy(expected, "core10000"); - // -- Run - result = get_name(cpu_id); - // -- Verification - TEST_STR(result, expected); - free(result); +void test_get_name() +{ + printf("==== TEST get_name() ====\n"); + size_t cpu_id = 0; + char *result = NULL; + char expected[100]; + + // TEST 1: + // -- Setup + cpu_id = 0; + strcpy(expected, "core0"); + // -- Run + result = get_name(cpu_id); + // -- Verification + TEST_STR(result, expected); + free(result); + + // TEST 2: + // -- Setup + cpu_id = 10000; + strcpy(expected, "core10000"); + // -- Run + result = get_name(cpu_id); + // -- Verification + TEST_STR(result, expected); + free(result); } #define NONE 0 @@ -457,66 +459,67 @@ void test_get_name() { }; \ } while(0); -void test_label_amd_rapl() { - printf("==== TEST label_amd_rapl() ====\n"); - cpu_sensor_t sensors[100]; - _amd_rapl_t rapl; - char *results[100]; - char expecteds[10][100]; - uint64_t nb = 0; - - // Test 1: - // -- Setup - nb = 1; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - // -- Run - label_amd_rapl(results, (void*) &rapl); - // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); - - // Test 2: - // -- Setup - nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 1, "core1"); - DUMB_SENSOR(sensors[2], 2, "core2"); - DUMB_SENSOR(sensors[3], 3, "core3"); - DUMB_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - strcpy(expecteds[1], "core1"); - strcpy(expecteds[2], "core2"); - strcpy(expecteds[3], "core3"); - // -- Run - label_amd_rapl(results, (void*) &rapl); - // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); - - // Test 3: - // -- Setup - nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 3, "core3"); - DUMB_SENSOR(sensors[2], 1, "core1"); - DUMB_SENSOR(sensors[3], 2, "core2"); - DUMB_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - strcpy(expecteds[1], "core3"); - strcpy(expecteds[2], "core1"); - strcpy(expecteds[3], "core2"); - // -- Run - label_amd_rapl(results, (void*) &rapl); - // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); +void test_label_amd_rapl() +{ + printf("==== TEST label_amd_rapl() ====\n"); + cpu_sensor_t sensors[100]; + _amd_rapl_t rapl; + char *results[100]; + char expecteds[10][100]; + uint64_t nb = 0; + + // Test 1: + // -- Setup + nb = 1; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + // -- Run + label_amd_rapl(results, (void *) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + + // Test 2: + // -- Setup + nb = 4; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_SENSOR(sensors[1], 1, "core1"); + DUMB_SENSOR(sensors[2], 2, "core2"); + DUMB_SENSOR(sensors[3], 3, "core3"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + strcpy(expecteds[1], "core1"); + strcpy(expecteds[2], "core2"); + strcpy(expecteds[3], "core3"); + // -- Run + label_amd_rapl(results, (void *) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + + // Test 3: + // -- Setup + nb = 4; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_SENSOR(sensors[1], 3, "core3"); + DUMB_SENSOR(sensors[2], 1, "core1"); + DUMB_SENSOR(sensors[3], 2, "core2"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + strcpy(expecteds[1], "core3"); + strcpy(expecteds[2], "core1"); + strcpy(expecteds[3], "core2"); + // -- Run + label_amd_rapl(results, (void *) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); } int main() { - test_raw_to_microjoule(); - test_get_name(); - test_label_amd_rapl(); + test_raw_to_microjoule(); + test_get_name(); + test_label_amd_rapl(); static const unsigned int time = 10; _amd_rapl_t *rapl = NULL; diff --git a/src/info_reader.h b/src/info_reader.h index 40948bd..019667f 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -224,214 +224,3 @@ static bool start_with(const char *prefix, const char *string) } } - -#ifdef __TESTING__ -#include "small_test.h" - -void test_replace_first() -{ - printf("==== TEST replace_first() ====\n"); - char test1[] = "This is my string"; - replace_first(test1, 'i', 'I'); - TEST_STR(test1, "ThIs is my string"); - - char test2[] = "This is my string"; - replace_first(test2, 'x', 'X'); - TEST_STR(test2, "This is my string"); - - - char test3[] = "This is my string"; - replace_first(test3, ' ', '_'); - TEST_STR(test3, "This_is my string"); -} - -void test_split_on_delimiter() -{ - printf("==== TEST split_on_delimite() ====\n"); - char test4[] = "key:value"; - char *key; - char *value; - split_on_delimiter(test4, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test5[] = "key: value"; - split_on_delimiter(test5, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value"); - - char test6[] = "key:value"; - replace_first(test6, ':', ' '); - split_on_delimiter(test6, " ", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test7[] = ""; - split_on_delimiter(test7, ":", &key, &value); - TEST_STR(key, NULL); - TEST_STR(value, NULL); - - char test9[] = "key:value:extra"; - split_on_delimiter(test9, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value:extra"); - - char test10[] = "key: value :extra"; - split_on_delimiter(test10, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value :extra"); -} - -void test_start_with() -{ - printf("==== TEST start_with() ====\n"); - char *prefix = NULL; - char *string = NULL; - bool result = false; - bool _true = true; - bool _false = false; - - prefix = "Hello"; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); - - prefix = "Goodbye"; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); - - prefix = "Hello World"; - string = "Hello"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); - - prefix = "Hello"; - string = "Hello"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); - - prefix = NULL; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); -} - -#define DUMB_KEYFINDER(key_finder, key, delimiter) \ - do { \ - key_finder = (KeyFinder) { \ - key, \ - delimiter, \ - 0, \ - 0 \ - }; \ - } while (0); - -#define DUMB_PARSER(parser, keys, nb_keys) \ - do { \ - parser = (Parser) { \ - 0, \ - 0, \ - 0, \ - 0, \ - keys, \ - nb_keys, \ - 0 \ - }; \ - } while (0); - - -void test_match() -{ - printf("==== TEST match() ====\n"); - // usefull variable : - bool _true = true; - bool _false = false; - KeyFinder keys[10]; - char line[100]; - Parser parser; - bool result; - KeyFinder *found_key_finder = NULL; - char *raw_value = NULL; - - // Test 1: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); - strcpy(line, "key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_true); - TEST_PTR(found_key_finder, &keys[0]); - TEST_STR(raw_value, "value"); - - // Test 2: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1) - strcpy(line, "not a key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); - - // Test 3: - // -- Setup - DUMB_KEYFINDER(keys[0],"key", ": "); - DUMB_PARSER(parser, keys, 1); - strcpy(line, "key:value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); - - // Test 4: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_KEYFINDER(keys[1], "second_key", ": "); - DUMB_PARSER(parser, keys, 2); - strcpy(line, "second_key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOLEAN(&result, &_true); - TEST_PTR(found_key_finder, &keys[1]); - TEST_STR(raw_value, "value"); - - // Test 5: - // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); - strcpy(line, ""); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - TEST_BOOLEAN(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); -} - -int main() -{ - test_replace_first(); - test_split_on_delimiter(); - test_start_with(); - test_match(); - return 0; -} - -#endif diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c new file mode 100644 index 0000000..10e5695 --- /dev/null +++ b/tests/amd_rapl.c @@ -0,0 +1,220 @@ +#include "small_test.h" +#include "../src/amd_rapl.c" + +int test_raw_to_microjoule() +{ + printf("==== TEST raw_to_microjoule() ====\n"); + int nb_error = 0; + + uint64_t raw = 0; + uint64_t unit = 0; + uint64_t result = 0; + uint64_t expected = 0; + + // Test 1: + // -- Setup + raw = 100; + unit = 0; + expected = 100000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + nb_error += TEST_UINT64_T(&result, &expected); + + // nb_error += TEST 2: + // -- Setup + raw = 200; + unit = 1; + expected = 100000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + nb_error += TEST_UINT64_T(&result, &expected); + + // nb_error += TEST 3: + // -- Setup + raw = 500; + unit = 2; + expected = 125000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + nb_error += TEST_UINT64_T(&result, &expected); + + // nb_error += TEST 4: + // -- Setup + raw = 1000; + unit = 3; + expected = 125000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + nb_error += TEST_UINT64_T(&result, &expected); + + // nb_error += TEST 5: + // -- Setup + raw = 10000; + unit = 4; + expected = 625000000; + // -- Run + result = raw_to_microjoule(raw, unit); + // -- Verification + nb_error += TEST_UINT64_T(&result, &expected); +} + +int test_get_name() +{ + int nb_error = 0; + + printf("==== TEST get_name() ====\n"); + size_t cpu_id = 0; + char *result = NULL; + char expected[100]; + + // nb_error += TEST 1: + // -- Setup + cpu_id = 0; + strcpy(expected, "core0"); + // -- Run + result = get_name(cpu_id); + // -- Verification + nb_error += TEST_STR(result, expected); + free(result); + + // nb_error += TEST 2: + // -- Setup + cpu_id = 10000; + strcpy(expected, "core10000"); + // -- Run + result = get_name(cpu_id); + // -- Verification + nb_error += TEST_STR(result, expected); + free(result); + + return nb_error; +} + +#define NONE 0 +#define DUMB_SENSOR(sensor, cpu_id, name) \ + do { \ + sensor = (cpu_sensor_t) { \ + cpu_id, \ + NONE, \ + name, \ + NONE, \ + NONE, \ + NONE, \ + NONE \ + }; \ + } while(0); + +#define DUMB_RAPL(rapl, sensors, nb) \ + do { \ + rapl = (_amd_rapl_t) { \ + sensors, \ + nb \ + }; \ + } while(0); + +int test_label_amd_rapl() +{ + int nb_error = 0; + printf("==== TEST label_amd_rapl() ====\n"); + cpu_sensor_t sensors[100]; + _amd_rapl_t rapl; + char *results[100]; + char expecteds[10][100]; + uint64_t nb = 0; + + // Test 1: + // -- Setup + nb = 1; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + // -- Run + label_amd_rapl(results, (void *) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb_error, nb, results, expecteds); + + // Test 2: + // -- Setup + nb = 4; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_SENSOR(sensors[1], 1, "core1"); + DUMB_SENSOR(sensors[2], 2, "core2"); + DUMB_SENSOR(sensors[3], 3, "core3"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + strcpy(expecteds[1], "core1"); + strcpy(expecteds[2], "core2"); + strcpy(expecteds[3], "core3"); + // -- Run + label_amd_rapl(results, (void *) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb_error, nb, results, expecteds); + + // Test 3: + // -- Setup + nb = 4; + DUMB_SENSOR(sensors[0], 0, "core0"); + DUMB_SENSOR(sensors[1], 3, "core3"); + DUMB_SENSOR(sensors[2], 1, "core1"); + DUMB_SENSOR(sensors[3], 2, "core2"); + DUMB_RAPL(rapl, sensors, nb); + strcpy(expecteds[0], "core0"); + strcpy(expecteds[1], "core3"); + strcpy(expecteds[2], "core1"); + strcpy(expecteds[3], "core2"); + // -- Run + label_amd_rapl(results, (void *) &rapl); + // -- Verification + TEST_T_ARRAY(TEST_STR, nb_error, nb, results, expecteds); + + return nb_error; +} + +int test_amd_rapl() +{ + int nb_error = 0; + nb_error += test_raw_to_microjoule(); + nb_error += test_get_name(); + nb_error += test_label_amd_rapl(); + return nb_error; +} + +#ifdef __TESTING__AMD__ +int main() +{ + test_amd_rapl(); + static const unsigned int time = 10; + _amd_rapl_t *rapl = NULL; + unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); + uint64_t results[nb_cpu]; + char *labels[nb_cpu]; + + label_amd_rapl(labels, (void *) rapl); + + for (unsigned int i = 0; i < rapl->nb; ++i) { + printf("%s ", labels[i]); + } + printf("\n"); + + // -- Run + + for (unsigned int i = 0; i < time; ++i) { + sleep(1); + get_amd_rapl(results, (void *)rapl); + + for (unsigned int j = 0; j < rapl->nb; ++j) { + printf("%ld ", results[j]); + } + printf("\n"); + } + + clean_amd_rapl(rapl); + return 0; +} + +#endif + diff --git a/src/info_reader.c b/tests/example_info_reader.c similarity index 98% rename from src/info_reader.c rename to tests/example_info_reader.c index 19d84de..1dd6464 100644 --- a/src/info_reader.c +++ b/tests/example_info_reader.c @@ -2,7 +2,7 @@ #include <stdint.h> #ifdef DEBUG -#warning "PTR_TO_TPTR hide a cast warning"aa +#warning "PTR_TO_TPTR hide a cast warning" #endif #define MAX_PROCS 2 diff --git a/tests/info_reader.c b/tests/info_reader.c new file mode 100644 index 0000000..36d2e96 --- /dev/null +++ b/tests/info_reader.c @@ -0,0 +1,233 @@ +#include "small_test.h" + +int test_replace_first() +{ + int nb_error = 0; + + printf("==== TEST replace_first() ====\n"); + char test1[] = "This is my string"; + replace_first(test1, 'i', 'I'); + nb_error += TEST_STR(test1, "ThIs is my string"); + + char test2[] = "This is my string"; + replace_first(test2, 'x', 'X'); + nb_error += TEST_STR(test2, "This is my string"); + + + char test3[] = "This is my string"; + replace_first(test3, ' ', '_'); + nb_error += TEST_STR(test3, "This_is my string"); + return nb_error; +} + +int test_split_on_delimiter() +{ + int nb_error = 0; + + printf("==== TEST split_on_delimite() ====\n"); + char test4[] = "key:value"; + char *key; + char *value; + split_on_delimiter(test4, ":", &key, &value); + nb_error += TEST_STR(key, "key"); + nb_error += TEST_STR(value, "value"); + + char test5[] = "key: value"; + split_on_delimiter(test5, ":", &key, &value); + nb_error += TEST_STR(key, "key"); + nb_error += TEST_STR(value, " value"); + + char test6[] = "key:value"; + replace_first(test6, ':', ' '); + split_on_delimiter(test6, " ", &key, &value); + nb_error += TEST_STR(key, "key"); + nb_error += TEST_STR(value, "value"); + + char test7[] = ""; + split_on_delimiter(test7, ":", &key, &value); + nb_error += TEST_STR(key, NULL); + nb_error += TEST_STR(value, NULL); + + char test9[] = "key:value:extra"; + split_on_delimiter(test9, ":", &key, &value); + nb_error += TEST_STR(key, "key"); + nb_error += TEST_STR(value, "value:extra"); + + char test10[] = "key: value :extra"; + split_on_delimiter(test10, ":", &key, &value); + nb_error += TEST_STR(key, "key"); + nb_error += TEST_STR(value, " value :extra"); + + return nb_error; +} + +int test_start_with() +{ + int nb_error = 0; + + printf("==== TEST start_with() ====\n"); + char *prefix = NULL; + char *string = NULL; + bool result = false; + bool _true = true; + bool _false = false; + + prefix = "Hello"; + string = "Hello World"; + result = start_with(prefix, string); + nb_error += TEST_BOOLEAN(&result, &_true); + + prefix = "Goodbye"; + string = "Hello World"; + result = start_with(prefix, string); + nb_error += TEST_BOOLEAN(&result, &_false); + + prefix = "Hello World"; + string = "Hello"; + result = start_with(prefix, string); + nb_error += TEST_BOOLEAN(&result, &_false); + + prefix = "Hello"; + string = "Hello"; + result = start_with(prefix, string); + nb_error += TEST_BOOLEAN(&result, &_true); + + prefix = NULL; + string = "Hello World"; + result = start_with(prefix, string); + nb_error += TEST_BOOLEAN(&result, &_false); + + return nb_error; +} + +#define DUMB_KEYFINDER(key_finder, key, delimiter) \ + do { \ + key_finder = (KeyFinder) { \ + key, \ + delimiter, \ + 0, \ + 0 \ + }; \ + } while (0); + +#define DUMB_PARSER(parser, keys, nb_keys) \ + do { \ + parser = (Parser) { \ + 0, \ + 0, \ + 0, \ + 0, \ + keys, \ + nb_keys, \ + 0 \ + }; \ + } while (0); + + +int test_match() +{ + int nb_error = 0; + printf("==== TEST match() ====\n"); + // usefull variable : + bool _true = true; + bool _false = false; + KeyFinder keys[10]; + char line[100]; + Parser parser; + bool result; + KeyFinder *found_key_finder = NULL; + char *raw_value = NULL; + + // Test 1: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, "key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + nb_error += TEST_BOOLEAN(&result, &_true); + nb_error += TEST_PTR(found_key_finder, &keys[0]); + nb_error += TEST_STR(raw_value, "value"); + + // Test 2: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1) + strcpy(line, "not a key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + nb_error += TEST_BOOLEAN(&result, &_false); + nb_error += TEST_PTR(found_key_finder, NULL); + nb_error += TEST_STR(raw_value, NULL); + + // Test 3: + // -- Setup + DUMB_KEYFINDER(keys[0],"key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, "key:value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + nb_error += TEST_BOOLEAN(&result, &_false); + nb_error += TEST_PTR(found_key_finder, NULL); + nb_error += TEST_STR(raw_value, NULL); + + // Test 4: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_KEYFINDER(keys[1], "second_key", ": "); + DUMB_PARSER(parser, keys, 2); + strcpy(line, "second_key: value"); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + // -- Verification + nb_error += TEST_BOOLEAN(&result, &_true); + nb_error += TEST_PTR(found_key_finder, &keys[1]); + nb_error += TEST_STR(raw_value, "value"); + + // Test 5: + // -- Setup + DUMB_KEYFINDER(keys[0], "key", ": "); + DUMB_PARSER(parser, keys, 1); + strcpy(line, ""); + found_key_finder = NULL; + raw_value = NULL; + // -- Run + result = match(&parser, line, &found_key_finder, &raw_value); + nb_error += TEST_BOOLEAN(&result, &_false); + nb_error += TEST_PTR(found_key_finder, NULL); + nb_error += TEST_STR(raw_value, NULL); + + return nb_error; +} + +int test_info_reader() +{ + int nb_error = 0; + + nb_error += test_replace_first(); + nb_error += test_split_on_delimiter(); + nb_error += test_start_with(); + nb_error += test_match(); + + return nb_error; +} + +#ifdef __TESTING_INFO_READER__ +int main() +{ + test_info_reader(); + return 0; +} +#endif + diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000..ee65c19 --- /dev/null +++ b/tests/main.c @@ -0,0 +1,13 @@ +#include "amd_rapl.c" +#include "info_reader.c" + +int main() +{ + int nb_error = 0; + + nb_error += test_amd_rapl(); + nb_error += test_info_reader(); + + return nb_error; +} + diff --git a/src/small_test.h b/tests/small_test.h similarity index 69% rename from src/small_test.h rename to tests/small_test.h index b8673dd..8f426ce 100644 --- a/src/small_test.h +++ b/tests/small_test.h @@ -1,5 +1,10 @@ #ifndef __SMALL_TEST_H -#define __SMALL_TEST_H +#define __SMALL_TEST_H + +#include <stdbool.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> #define FMT_NULL(string) \ string = string ? string : "NULL" @@ -16,9 +21,9 @@ #define TEST_UINT64_T(result, expected) \ test_uint64_t(__FILE__, __LINE__, result, expected) -#define TEST_T_ARRAY(function, size, results, expecteds) \ - for (unsigned int i = 0; i < size; i++) { \ - function(results[i], expecteds[i]); \ +#define TEST_T_ARRAY(function, nb_error, size, results, expecteds) \ + for (unsigned int i = 0; i < size; i++) { \ + nb_error += function(results[i], expecteds[i]); \ } typedef int (Comparator) (void *, void *); @@ -74,11 +79,12 @@ char *uint64_t_format(char *buffer, uint64_t *value) return buffer; } -void test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) +int test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) { static char buffer_result[1000]; static char buffer_expected[1000]; - if (compare(result, expected) == 0) { + int is_equal = compare(result, expected); + if (!is_equal) { printf("Test %s:%d failed: expected %s, got %s\n", file, line, @@ -88,37 +94,39 @@ void test(char *file, int line, void *result, void *expected, Comparator *compar } else { printf("Test %s:%d passed\n", file, line); } + return !is_equal; } -void test_str(char *file, int line, char *result, char *expected) +int test_str(char *file, int line, char *result, char *expected) { Comparator *compare = (Comparator *) string_compare; Formatter *format = (Formatter *) string_format; - test(file, line, result, expected, compare, format); + return test(file, line, result, expected, compare, format); } -void test_boolean(char *file, int line, bool *result, bool *expected) +int test_boolean(char *file, int line, bool *result, bool *expected) { Comparator *compare = (Comparator *) boolean_compare; Formatter *format = (Formatter *) boolean_format; - test(file, line, (void *) result, (void *) expected, compare, format); + return test(file, line, (int *) result, (void *) expected, compare, format); } -void test_ptr(char *file, int line, void *result, void *expected) +int test_ptr(char *file, int line, void *result, void *expected) { Comparator *compare = (Comparator *) ptr_compare; Formatter *format = (Formatter *) ptr_format; - test(file, line, result, expected, compare, format); + return test(file, line, result, expected, compare, format); } -void test_uint64_t(char *file, int line, void *result, void *expected) +int test_uint64_t(char *file, int line, void *result, void *expected) { Comparator *compare = (Comparator *) uint64_t_compare; Formatter *format = (Formatter *) uint64_t_format; - test(file, line, (uint64_t *)result, (uint64_t *)expected, compare, format); + return test(file, line, (uint64_t *)result, (uint64_t *)expected, compare, format); } #endif + -- GitLab From 87fc85cb4ed4d3b8cf7fb554590e7674b9a9329c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 13:20:50 +0000 Subject: [PATCH 053/125] add new macro --- src/amd_rapl.c | 3 +-- src/info_reader.h | 8 -------- src/util.h | 6 ++++++ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 91b6009..e0baad8 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -320,8 +320,7 @@ unsigned int get_amd_rapl(uint64_t *results, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { - // TODO: check if unit is the same -#warning "check if unit is the same" + DEBUG_WARNING("check if unit is the same") results[i] = get_core_energy(&rapl->sensors[i]); } return rapl->nb; diff --git a/src/info_reader.h b/src/info_reader.h index 019667f..1696ede 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -113,14 +113,6 @@ static void set_value(Parser *parser, KeyFinder *key_finder, char *raw_value) key_finder->set(address, value); } -// static void storage_zero(Parser *parser) { -// static const int zero = 0; -// GenericPointer storage = parser->storage; -// size_t capacity = parser->capacity; -// size_t struct_size = parser->storage_struct_size; -// memset(storage, zero, struct_size * capacity); -// } - static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value) { for (unsigned int i = 0; i < parser->nb_keys; i++) { diff --git a/src/util.h b/src/util.h index 6d4a644..9468d41 100644 --- a/src/util.h +++ b/src/util.h @@ -29,6 +29,12 @@ #define _impl_CASSERT_LINE(predicate, line, file) \ typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; +#ifdef DEBUG + #define DEBUG_WARNING(warning) #warning warning +#else + #define DEBUG_WARNING(warning) do { } while(0); +#endif + #define UNUSED(expr) do { (void)(expr); } while (0) #define PANIC(code, fmt, ...) \ do { \ -- GitLab From cd89c3608c3d8dd7eb026d0732d059e881b45932 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 14:02:22 +0000 Subject: [PATCH 054/125] add util tests --- src/util.c | 4 ++-- tests/amd_rapl.c | 2 ++ tests/main.c | 2 ++ tests/small_test.h | 3 ++- tests/util.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 tests/util.c diff --git a/src/util.c b/src/util.c index fe3efa1..7efa66f 100644 --- a/src/util.c +++ b/src/util.c @@ -22,6 +22,6 @@ uint64_t modulo_substraction(uint64_t previous, uint64_t new) { - return new > previous ? (new - previous) - : (UINT64_MAX - previous) + new; + return new >= previous ? (new - previous) + : (UINT64_MAX - previous + 1) + new; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 10e5695..e890ca4 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -60,6 +60,8 @@ int test_raw_to_microjoule() result = raw_to_microjoule(raw, unit); // -- Verification nb_error += TEST_UINT64_T(&result, &expected); + + return nb_error; } int test_get_name() diff --git a/tests/main.c b/tests/main.c index ee65c19..950632d 100644 --- a/tests/main.c +++ b/tests/main.c @@ -1,4 +1,5 @@ #include "amd_rapl.c" +#include "util.c" #include "info_reader.c" int main() @@ -7,6 +8,7 @@ int main() nb_error += test_amd_rapl(); nb_error += test_info_reader(); + nb_error += test_util(); return nb_error; } diff --git a/tests/small_test.h b/tests/small_test.h index 8f426ce..5cb6616 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -3,6 +3,7 @@ #include <stdbool.h> #include <string.h> +#include <inttypes.h> #include <stdint.h> #include <stdio.h> @@ -75,7 +76,7 @@ int uint64_t_compare(uint64_t *value1, uint64_t *value2) char *uint64_t_format(char *buffer, uint64_t *value) { - sprintf(buffer, "%ld", *value); + sprintf(buffer, "%"PRIu64"", *value); return buffer; } diff --git a/tests/util.c b/tests/util.c new file mode 100644 index 0000000..218cf5a --- /dev/null +++ b/tests/util.c @@ -0,0 +1,58 @@ +#include "../src/util.h" +#include "small_test.h" + + +int test_modulo_substraction() { + printf("==== TEST test_modulo_substraction() ====\n"); + int nb_error = 0; + uint64_t previous = 0; + uint64_t new = 0; + uint64_t result = 0; + uint64_t expected = 0; + + // Test 1: + // -- Setup + previous = 10; + new = 10; + expected = 0; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + // Test 2: + // -- Setup + previous = UINT64_MAX; + new = 0; + expected = 1; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + // Test 3: + // -- Setup + previous = 0; + new = UINT64_MAX; + expected = UINT64_MAX; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + // Test 4: + // -- Setup + previous = 20; + new = 10; + expected = UINT64_MAX - 9; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + return nb_error; +} +int test_util() { + int nb_error = test_modulo_substraction(); + return nb_error; +} -- GitLab From 917d9d1e0b4d0343ae8da67730696801ff227ee9 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 14:03:24 +0000 Subject: [PATCH 055/125] update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 44d1164..2721f47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ src/counters_option.h src/captors.h -tests/tests +tests/run bin obj -- GitLab From 4afbb05a4f52230ad4aa928467bf8a87c13d92d6 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 15:09:29 +0000 Subject: [PATCH 056/125] update test framework --- tests/.small_test.h.swp | Bin 0 -> 16384 bytes tests/amd_rapl.c | 10 ++-- tests/info_reader.c | 9 ++-- tests/main.c | 3 +- tests/small_test.h | 28 +++++++++-- tests/util.c | 103 +++++++++++++++++++++------------------- 6 files changed, 90 insertions(+), 63 deletions(-) create mode 100644 tests/.small_test.h.swp diff --git a/tests/.small_test.h.swp b/tests/.small_test.h.swp new file mode 100644 index 0000000000000000000000000000000000000000..3ebcb5fb09f2f1e9646145b69c8054103f3a9a64 GIT binary patch literal 16384 zcmYc?2=nw+u+TGNU|?VnU|<OUaz1&gsRF~QAO?n_%;Mt2l-$fbkQ^QiQkPm(mRf{I z4M?gEq!4VNetCXTc5y*sa;koAepY5lezAT@YH>-iesOMMPEI_Ct(O7PGKxn-U^E1% z5dx(pX}T7?48}%=1|Z{<l@t|(g+f8hQ9K#~qaiRF0;3@?8UmvsFd71*Aut*OqaiRt zLZGC8iJ_i>fq@C?-&QEih(<F*`65tyGL(j?gK|fy(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!83z7y^kY3=A@i3=BS?4!!^b1FZl5lAnR$5<dgOMScc`J^Ty| zEBF~0Ch;>c)bTSgWb-pHWbrdF`13O`=<qWzX!A2Lu<<i6T;pS4xXQ=Cu!fI;p@NTr zp`4F_A&8HGL5YunL6MJv;X5w_!y#S<hJ(Be3^lwA3|_np48pt&3<A6i4E($d3}1K{ z7|!!BFr4FIU|7$?z%YS_fuWy=fgy*7fkBmrfkB0bf#D}N1H)Nv28J`-3=Ffm85m}A zGcaUxGcZJQGcc%dGcX8oGcd4nGca7`VqiGW#lUcui-F+`7Xw2J7Xw2R7Xw2o7Xw2w z7Xw2Q7Xw2g7XyPX7XyPf7Xt$a7Xt$u7Xt$;7X!m?P6mdZoD2*TIT;xGIT;xGI2jny zI2jmHI2jncIT;u{IT;u{I2jn^I2jmZI2joJa4;~u<X~WU&cVR&jDvyUDF*|?8V&}A zRU8Zq-5d-Iog54d9UKe{!5j<>fgB7B>KqIVA{-11LL3YXf*cGCSJ@dDF0(T*OkrnW zn8eP&Fp-^sA(@?lA(5Sd!IqtY!J3_c!HS)M;VK&g!(}!GhIMQV4DD<T43TUM4Ek&g z3_n;I7{0SIFg#>sVA#mYz|hFbz!1dBz~IQrz+l44z#zfOz#zoR!0?BKf#DYm1H(@i z28JCh3=G>?7#M0<7#KWQ7#Q4H7#P@D7#LVt7#LVs7#Q|5GcfFBW?*P$W?=AThNKT~ zW(EcoW(EcpW(EdkW(Ec(P?}+8V7SA?z;KI+f#E0<1H)k^28M%73=B({7#RAQ7#R9s z14~4veFX&t1-Ja7+{BWS)FK6~G!T;kn_!88t%8PIei4HL2x8TRS0B^{1_cHNLh1;~ zgI%hrK+qhhx}^O4oYcg;c(C6}tih%`=jRqA7A2PC7b$2ZgW0Jd{~-%&D!?>C6<9M= zGi2tKD1cVW#6#sYk~0!P!Iqhms-pms%*o74)dA~N&?-tTF3l-{@lq=aQj<$kQ#2VE zYQb(ON-ZfZ$^#pxkp?yZq8X+Qra?ym>Hr-Dh!-@iiS>GMNl|8AI_W-#>Vw*g;_>2= zA{?HE1O?3X5FX4A=$=;0ERIhtEKSU@1_uQsKtRc^peQr1Buzu9AhEbOH6<obNfW9< zAvLEsRiPTJ9HbC}p|TJTn1lq8Mp9{7T53@|%zhmOh`Th=^g}}wrW~S3M**fyQwOdd z=CHKH%$(E|gc1eSVjYF_{1OG#;+Q-oi2BSl1qBVb7c~{CA@Kz>B3d;$7Ub3%1=V6J z)f6iQB^`z2c$nRYqyY6CI3!{63bqQcpi{6{P!CgAuu@QuP=^E(C;`G{ZDGkq17<SZ zR}j_3C5a`O$qHcO(Sj@5(7?bT7N;_ZfiOjgT!ABDl;vlpAaVnQ2Xl*#0&<>%CO938 zBB=zPfM9`GV{50NTCAZ73Ur0E(!Au7%=|n}P*Me3keQcR0$$e^50leK&d)0@fp}L7 zCWv9IEgUF>xCVzPWacTT7Axo?+Xc?5a09T}n3<D`Y8zM!Ui+bi0VE!v0T1;mL`+9P zNmVHz$g|YUL`g|UL8~k=r!*DpUvLC!m1gFZn3=?vKr=fuDqwnHvM_yUWe~(PLj_w~ zr~)I9w?N4WrZFBGH5xDhs6s;>1vC*OO$Id6A&$W1sRAV(g@TeIB(D^d6k+!TIA*m# ziqUK+C@BIvzM!NC?sAYRFh|2R8tN#(*&v5P3La?SYe5Tj1$zahkfPF5B?T)5CAY+! z;#4J2a6rNtss`r3`1r(<lA_F{(vsBpcnyuxywc*-6irQNGK2UWRs%q_!qXg@wO}8> z+yM6mR1-Y>L3{<6Dnm4*L0&?wUEF*_;{8H>d^8|MI#MV@1W5A-BnTin;og9RA*euu zdI)4!a&7^L%FIhQ)KP$FFwz92F9T?)R*PPsLp2*f(g{>LGfe?z3`jG`Ckiz+Fau#i zpb{2jKL|sOF@zX{O~0BNHvN!N4B}FFU?cn2PzM^R5H+BnE~zX?O-W6Iii285kXDYS z0yO)<Qk$kV157O_Q)wW|JWT}+NP<LC%D|bDuTZT3&HhU863JG<B{eOzs3<i>!L_I; zzevGKK^0U*>L}zT#ixQqG_4hC70NR}<&S|TgK|o0T4r9Vf{Ux0YfzA@OT24PkbjT{ zT(Lq70|O_Pf-)XlX2!>BTEmU-^z#gf2Nj6%ZlQk8A)fwz8k*?ZLAJ)nyLtM!#>eX@ z;5Wq6#}#ToEdwVf%tZ>?w(z1HT5A<YXT~BbTM$pvnv;{0GlqdPEx$-XqcpELGd(Xg z1>E?`RIpVruvW-auu&+^tV*?3$kf)>RHz222kC%?2iPAW@s2@3j*%L$f*cWuI$+JP z7DF+T?V6mR5CgaWV1=FrvX6Z{{lI>Q)Q<>_h^PQt9qQ>9VrCK_0`(%2I&hGJ%`Ye^ zBFE@}kRW`ff(nn+#5{6LcJlZ4adq^=XF8~9NJel3<8(75rzzM%^Q(eAjA5mq1S$%Y z;OP^+m;(i*a%Ns~PH9T2f=zKrN@l)Zh8+W{P+keDSY}=cD3=zaib5QLE|vlcN{}Gj z3Gwm4zK%XVkX+)ypq!bO2PzxTghBm(6J7>}1-y{;|FHS}_52JBYxx-%)<FCFnfwe4 z#{3KnjQk7?4EziX2lyBm_VF<=?1lF8OZgZWtoRrhnE4nOnD`hNR`D`0tl(u}SO_(H zKFE9``+%d$MnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(M23KJYF<ia8tNb#s7H=6 zMT0a7stN1tBa0zMx1l4Dq)*+z1{k0NbdcdJ#JCZjX)Cx+sNJBkOVFqj$QSW2N$3C- zWU>Jy3z>U@j77n`1mVFv10V2%4zYpELkSg_HkbwqCayq(w~(0}5<Cvlgw4;Ou@uNi a9#y@o0SY!PP3X*$4s0M#6Fz%{&Hn%&q=H-k literal 0 HcmV?d00001 diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index e890ca4..1ddf234 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -3,7 +3,7 @@ int test_raw_to_microjoule() { - printf("==== TEST raw_to_microjoule() ====\n"); + INIT_TEST_FUNCTION(); int nb_error = 0; uint64_t raw = 0; @@ -61,14 +61,14 @@ int test_raw_to_microjoule() // -- Verification nb_error += TEST_UINT64_T(&result, &expected); - return nb_error; + return nb_error; } int test_get_name() { + INIT_TEST_FUNCTION(); int nb_error = 0; - printf("==== TEST get_name() ====\n"); size_t cpu_id = 0; char *result = NULL; char expected[100]; @@ -120,8 +120,8 @@ int test_get_name() int test_label_amd_rapl() { + INIT_TEST_FUNCTION(); int nb_error = 0; - printf("==== TEST label_amd_rapl() ====\n"); cpu_sensor_t sensors[100]; _amd_rapl_t rapl; char *results[100]; @@ -178,6 +178,8 @@ int test_label_amd_rapl() int test_amd_rapl() { + INIT_TEST_FILE(); + int nb_error = 0; nb_error += test_raw_to_microjoule(); nb_error += test_get_name(); diff --git a/tests/info_reader.c b/tests/info_reader.c index 36d2e96..3953109 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -2,9 +2,9 @@ int test_replace_first() { + INIT_TEST_FUNCTION(); int nb_error = 0; - printf("==== TEST replace_first() ====\n"); char test1[] = "This is my string"; replace_first(test1, 'i', 'I'); nb_error += TEST_STR(test1, "ThIs is my string"); @@ -22,9 +22,9 @@ int test_replace_first() int test_split_on_delimiter() { + INIT_TEST_FUNCTION(); int nb_error = 0; - printf("==== TEST split_on_delimite() ====\n"); char test4[] = "key:value"; char *key; char *value; @@ -63,9 +63,9 @@ int test_split_on_delimiter() int test_start_with() { + INIT_TEST_FUNCTION(); int nb_error = 0; - printf("==== TEST start_with() ====\n"); char *prefix = NULL; char *string = NULL; bool result = false; @@ -126,8 +126,8 @@ int test_start_with() int test_match() { + INIT_TEST_FUNCTION(); int nb_error = 0; - printf("==== TEST match() ====\n"); // usefull variable : bool _true = true; bool _false = false; @@ -213,6 +213,7 @@ int test_match() int test_info_reader() { + INIT_TEST_FILE(); int nb_error = 0; nb_error += test_replace_first(); diff --git a/tests/main.c b/tests/main.c index 950632d..b14f518 100644 --- a/tests/main.c +++ b/tests/main.c @@ -8,8 +8,9 @@ int main() nb_error += test_amd_rapl(); nb_error += test_info_reader(); - nb_error += test_util(); + nb_error += test_util(); + DEFERRED_ERROR(nb_error); return nb_error; } diff --git a/tests/small_test.h b/tests/small_test.h index 5cb6616..b93cd7b 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -27,6 +27,15 @@ nb_error += function(results[i], expecteds[i]); \ } +#define INIT_TEST_FILE() \ + init_test_file(__FILE__, __func__); + +#define INIT_TEST_FUNCTION() \ + init_test_function(__func__); + +#define DEFERRED_ERROR(nb_error) \ + do { printf("========== Deferred Error : %d\n", nb_error); } while(0) + typedef int (Comparator) (void *, void *); typedef char *(Formatter) (char *, void *); @@ -80,20 +89,31 @@ char *uint64_t_format(char *buffer, uint64_t *value) return buffer; } +void init_test_file(const char *file, const char *function) +{ + printf("========== TEST in %s -> %s()\n", file, function); +} + +void init_test_function(const char *function) +{ + printf("|=> %s()\n", function); +} + int test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) { static char buffer_result[1000]; static char buffer_expected[1000]; int is_equal = compare(result, expected); + char c_result = is_equal ? 'V' : 'X'; + printf("[%c] | %s:%d: ", c_result, file, line); + if (!is_equal) { - printf("Test %s:%d failed: expected %s, got %s\n", - file, - line, + printf("failed, expected %s, got %s\n", format(buffer_result, expected), format(buffer_expected, result) ); } else { - printf("Test %s:%d passed\n", file, line); + printf("passed\n"); } return !is_equal; } diff --git a/tests/util.c b/tests/util.c index 218cf5a..eba4da3 100644 --- a/tests/util.c +++ b/tests/util.c @@ -2,57 +2,60 @@ #include "small_test.h" -int test_modulo_substraction() { - printf("==== TEST test_modulo_substraction() ====\n"); - int nb_error = 0; - uint64_t previous = 0; - uint64_t new = 0; - uint64_t result = 0; - uint64_t expected = 0; +int test_modulo_substraction() +{ + INIT_TEST_FUNCTION(); + int nb_error = 0; + uint64_t previous = 0; + uint64_t new = 0; + uint64_t result = 0; + uint64_t expected = 0; - // Test 1: - // -- Setup - previous = 10; - new = 10; - expected = 0; - // -- Run - result = modulo_substraction(previous, new); - // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); - - // Test 2: - // -- Setup - previous = UINT64_MAX; - new = 0; - expected = 1; - // -- Run - result = modulo_substraction(previous, new); - // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); + // Test 1: + // -- Setup + previous = 10; + new = 10; + expected = 0; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); - // Test 3: - // -- Setup - previous = 0; - new = UINT64_MAX; - expected = UINT64_MAX; - // -- Run - result = modulo_substraction(previous, new); - // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); - - // Test 4: - // -- Setup - previous = 20; - new = 10; - expected = UINT64_MAX - 9; - // -- Run - result = modulo_substraction(previous, new); - // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); - - return nb_error; + // Test 2: + // -- Setup + previous = UINT64_MAX; + new = 0; + expected = 1; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + // Test 3: + // -- Setup + previous = 0; + new = UINT64_MAX; + expected = UINT64_MAX; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + // Test 4: + // -- Setup + previous = 20; + new = 10; + expected = UINT64_MAX - 9; + // -- Run + result = modulo_substraction(previous, new); + // -- Verification + nb_error = TEST_UINT64_T(&result, &expected); + + return nb_error; } -int test_util() { - int nb_error = test_modulo_substraction(); - return nb_error; +int test_util() +{ + INIT_TEST_FILE(); + int nb_error = test_modulo_substraction(); + return nb_error; } -- GitLab From f96d52de8b37b8e22cfd0b275cfba014f279555d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 15:10:06 +0000 Subject: [PATCH 057/125] fix: format --- doc/counter_ex.c | 4 ++-- doc/counter_ex.h | 2 +- src/amd_rapl.c | 2 +- src/util.h | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/counter_ex.c b/doc/counter_ex.c index 73696ad..0dc6f29 100644 --- a/doc/counter_ex.c +++ b/doc/counter_ex.c @@ -21,6 +21,6 @@ void label_acc(char **labels, void *none) void clean_acc(void *none) { - /* That's a no-op for this example */ - UNUSED(none); + /* That's a no-op for this example */ + UNUSED(none); } diff --git a/doc/counter_ex.h b/doc/counter_ex.h index beeef91..4ab7915 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -4,7 +4,7 @@ unsigned int init_acc(char *, void **); unsigned int get_acc(uint64_t *results, void *); -void clean_acc(void*); +void clean_acc(void *); void label_acc(char **labels, void *); struct optparse_long counters_opt = {"accumulator", 'a', OPTPARSE_NONE}; diff --git a/src/amd_rapl.c b/src/amd_rapl.c index e0baad8..238161c 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -320,7 +320,7 @@ unsigned int get_amd_rapl(uint64_t *results, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { - DEBUG_WARNING("check if unit is the same") + DEBUG_WARNING("check if unit is the same") results[i] = get_core_energy(&rapl->sensors[i]); } return rapl->nb; diff --git a/src/util.h b/src/util.h index 9468d41..991c71e 100644 --- a/src/util.h +++ b/src/util.h @@ -29,10 +29,10 @@ #define _impl_CASSERT_LINE(predicate, line, file) \ typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; -#ifdef DEBUG - #define DEBUG_WARNING(warning) #warning warning +#ifdef DEBUG +#define DEBUG_WARNING(warning) #warning warning #else - #define DEBUG_WARNING(warning) do { } while(0); +#define DEBUG_WARNING(warning) do { } while(0); #endif #define UNUSED(expr) do { (void)(expr); } while (0) -- GitLab From 23b861984b65c10228036fd19fcc71a66971263d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 15:11:16 +0000 Subject: [PATCH 058/125] rm vim file --- tests/.small_test.h.swp | Bin 16384 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/.small_test.h.swp diff --git a/tests/.small_test.h.swp b/tests/.small_test.h.swp deleted file mode 100644 index 3ebcb5fb09f2f1e9646145b69c8054103f3a9a64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmYc?2=nw+u+TGNU|?VnU|<OUaz1&gsRF~QAO?n_%;Mt2l-$fbkQ^QiQkPm(mRf{I z4M?gEq!4VNetCXTc5y*sa;koAepY5lezAT@YH>-iesOMMPEI_Ct(O7PGKxn-U^E1% z5dx(pX}T7?48}%=1|Z{<l@t|(g+f8hQ9K#~qaiRF0;3@?8UmvsFd71*Aut*OqaiRt zLZGC8iJ_i>fq@C?-&QEih(<F*`65tyGL(j?gK|fy(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!83z7y^kY3=A@i3=BS?4!!^b1FZl5lAnR$5<dgOMScc`J^Ty| zEBF~0Ch;>c)bTSgWb-pHWbrdF`13O`=<qWzX!A2Lu<<i6T;pS4xXQ=Cu!fI;p@NTr zp`4F_A&8HGL5YunL6MJv;X5w_!y#S<hJ(Be3^lwA3|_np48pt&3<A6i4E($d3}1K{ z7|!!BFr4FIU|7$?z%YS_fuWy=fgy*7fkBmrfkB0bf#D}N1H)Nv28J`-3=Ffm85m}A zGcaUxGcZJQGcc%dGcX8oGcd4nGca7`VqiGW#lUcui-F+`7Xw2J7Xw2R7Xw2o7Xw2w z7Xw2Q7Xw2g7XyPX7XyPf7Xt$a7Xt$u7Xt$;7X!m?P6mdZoD2*TIT;xGIT;xGI2jny zI2jmHI2jncIT;u{IT;u{I2jn^I2jmZI2joJa4;~u<X~WU&cVR&jDvyUDF*|?8V&}A zRU8Zq-5d-Iog54d9UKe{!5j<>fgB7B>KqIVA{-11LL3YXf*cGCSJ@dDF0(T*OkrnW zn8eP&Fp-^sA(@?lA(5Sd!IqtY!J3_c!HS)M;VK&g!(}!GhIMQV4DD<T43TUM4Ek&g z3_n;I7{0SIFg#>sVA#mYz|hFbz!1dBz~IQrz+l44z#zfOz#zoR!0?BKf#DYm1H(@i z28JCh3=G>?7#M0<7#KWQ7#Q4H7#P@D7#LVt7#LVs7#Q|5GcfFBW?*P$W?=AThNKT~ zW(EcoW(EcpW(EdkW(Ec(P?}+8V7SA?z;KI+f#E0<1H)k^28M%73=B({7#RAQ7#R9s z14~4veFX&t1-Ja7+{BWS)FK6~G!T;kn_!88t%8PIei4HL2x8TRS0B^{1_cHNLh1;~ zgI%hrK+qhhx}^O4oYcg;c(C6}tih%`=jRqA7A2PC7b$2ZgW0Jd{~-%&D!?>C6<9M= zGi2tKD1cVW#6#sYk~0!P!Iqhms-pms%*o74)dA~N&?-tTF3l-{@lq=aQj<$kQ#2VE zYQb(ON-ZfZ$^#pxkp?yZq8X+Qra?ym>Hr-Dh!-@iiS>GMNl|8AI_W-#>Vw*g;_>2= zA{?HE1O?3X5FX4A=$=;0ERIhtEKSU@1_uQsKtRc^peQr1Buzu9AhEbOH6<obNfW9< zAvLEsRiPTJ9HbC}p|TJTn1lq8Mp9{7T53@|%zhmOh`Th=^g}}wrW~S3M**fyQwOdd z=CHKH%$(E|gc1eSVjYF_{1OG#;+Q-oi2BSl1qBVb7c~{CA@Kz>B3d;$7Ub3%1=V6J z)f6iQB^`z2c$nRYqyY6CI3!{63bqQcpi{6{P!CgAuu@QuP=^E(C;`G{ZDGkq17<SZ zR}j_3C5a`O$qHcO(Sj@5(7?bT7N;_ZfiOjgT!ABDl;vlpAaVnQ2Xl*#0&<>%CO938 zBB=zPfM9`GV{50NTCAZ73Ur0E(!Au7%=|n}P*Me3keQcR0$$e^50leK&d)0@fp}L7 zCWv9IEgUF>xCVzPWacTT7Axo?+Xc?5a09T}n3<D`Y8zM!Ui+bi0VE!v0T1;mL`+9P zNmVHz$g|YUL`g|UL8~k=r!*DpUvLC!m1gFZn3=?vKr=fuDqwnHvM_yUWe~(PLj_w~ zr~)I9w?N4WrZFBGH5xDhs6s;>1vC*OO$Id6A&$W1sRAV(g@TeIB(D^d6k+!TIA*m# ziqUK+C@BIvzM!NC?sAYRFh|2R8tN#(*&v5P3La?SYe5Tj1$zahkfPF5B?T)5CAY+! z;#4J2a6rNtss`r3`1r(<lA_F{(vsBpcnyuxywc*-6irQNGK2UWRs%q_!qXg@wO}8> z+yM6mR1-Y>L3{<6Dnm4*L0&?wUEF*_;{8H>d^8|MI#MV@1W5A-BnTin;og9RA*euu zdI)4!a&7^L%FIhQ)KP$FFwz92F9T?)R*PPsLp2*f(g{>LGfe?z3`jG`Ckiz+Fau#i zpb{2jKL|sOF@zX{O~0BNHvN!N4B}FFU?cn2PzM^R5H+BnE~zX?O-W6Iii285kXDYS z0yO)<Qk$kV157O_Q)wW|JWT}+NP<LC%D|bDuTZT3&HhU863JG<B{eOzs3<i>!L_I; zzevGKK^0U*>L}zT#ixQqG_4hC70NR}<&S|TgK|o0T4r9Vf{Ux0YfzA@OT24PkbjT{ zT(Lq70|O_Pf-)XlX2!>BTEmU-^z#gf2Nj6%ZlQk8A)fwz8k*?ZLAJ)nyLtM!#>eX@ z;5Wq6#}#ToEdwVf%tZ>?w(z1HT5A<YXT~BbTM$pvnv;{0GlqdPEx$-XqcpELGd(Xg z1>E?`RIpVruvW-auu&+^tV*?3$kf)>RHz222kC%?2iPAW@s2@3j*%L$f*cWuI$+JP z7DF+T?V6mR5CgaWV1=FrvX6Z{{lI>Q)Q<>_h^PQt9qQ>9VrCK_0`(%2I&hGJ%`Ye^ zBFE@}kRW`ff(nn+#5{6LcJlZ4adq^=XF8~9NJel3<8(75rzzM%^Q(eAjA5mq1S$%Y z;OP^+m;(i*a%Ns~PH9T2f=zKrN@l)Zh8+W{P+keDSY}=cD3=zaib5QLE|vlcN{}Gj z3Gwm4zK%XVkX+)ypq!bO2PzxTghBm(6J7>}1-y{;|FHS}_52JBYxx-%)<FCFnfwe4 z#{3KnjQk7?4EziX2lyBm_VF<=?1lF8OZgZWtoRrhnE4nOnD`hNR`D`0tl(u}SO_(H zKFE9``+%d$MnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(M23KJYF<ia8tNb#s7H=6 zMT0a7stN1tBa0zMx1l4Dq)*+z1{k0NbdcdJ#JCZjX)Cx+sNJBkOVFqj$QSW2N$3C- zWU>Jy3z>U@j77n`1mVFv10V2%4zYpELkSg_HkbwqCayq(w~(0}5<Cvlgw4;Ou@uNi a9#y@o0SY!PP3X*$4s0M#6Fz%{&Hn%&q=H-k -- GitLab From b5b2cf76a91d0956ac085173b3e1297e69dc039a Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 24 Jan 2023 15:13:12 +0000 Subject: [PATCH 059/125] add ignore vim files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 2721f47..6aa6785 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ src/captors.h tests/run bin obj +*.swp +*.swo -- GitLab From 09e8fc5ab8e5b36ef1c7d14b4196990843a0bcd4 Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Tue, 24 Jan 2023 17:22:51 +0100 Subject: [PATCH 060/125] late commit fix registres acc --- .vscode/settings.json | 5 +++++ src/counters.c | 4 +++- src/network.c | 3 ++- src/rapl.c | 3 ++- src/util.c | 6 +++--- 5 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..480615b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "util.h": "c" + } +} \ No newline at end of file diff --git a/src/counters.c b/src/counters.c index de00d62..874e6fc 100644 --- a/src/counters.c +++ b/src/counters.c @@ -27,6 +27,8 @@ #include <stdint.h> #include <asm/unistd.h> #include <stdint.h> +#include "util.h" + struct _counter_t { int nbcores; @@ -217,7 +219,7 @@ unsigned int get_counters(uint64_t *results, void *ptr) _get_counters(state, state->tmp_counters_values); for (int i = 0; i < state->nbperf; i++) { - results[i] = state->tmp_counters_values[i] - state->counters_values[i]; + results[i] = modulo_substraction(state->tmp_counters_values[i], state->counters_values[i]); } memcpy(state->counters_values, state->tmp_counters_values, state->nbperf * sizeof(uint64_t)); diff --git a/src/network.c b/src/network.c index f57a383..bee3e5a 100644 --- a/src/network.c +++ b/src/network.c @@ -23,6 +23,7 @@ #include <stdio.h> #include <string.h> #include <stdint.h> +#include "util.h" #define NB_SENSOR 4 #define UNUSED(expr) do { (void)(expr); } while (0) @@ -112,7 +113,7 @@ unsigned int get_network(uint64_t *results, void *ptr) _get_network(state->tmp_values, state->sources); for (int i = 0; i < NB_SENSOR; i++) { - results[i] = state->tmp_values[i] - state->values[i]; + results[i] = modulo_substraction(state->tmp_values[i], state->values[i]); } memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); diff --git a/src/rapl.c b/src/rapl.c index cd558d2..26e9854 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -25,6 +25,7 @@ #include <fcntl.h> #include <inttypes.h> #include <errno.h> +#include "util.h" #define MAX_HEADER 128 @@ -167,7 +168,7 @@ unsigned int get_rapl(uint64_t *results, void *ptr) _get_rapl(state->tmp_values, state); for (unsigned int i = 0; i < state->nb; i++) { - results[i] = state->tmp_values[i] - state->values[i]; + results[i] = modulo_substraction(state->tmp_values[i], state->values[i]); } memcpy(state->values, state->tmp_values, sizeof(uint64_t)*state->nb); diff --git a/src/util.c b/src/util.c index 7efa66f..71928c4 100644 --- a/src/util.c +++ b/src/util.c @@ -20,8 +20,8 @@ #include "util.h" -uint64_t modulo_substraction(uint64_t previous, uint64_t new) +uint64_t uint64_t modulo_substraction(const uint64_t l, const uint64_t r) { - return new >= previous ? (new - previous) - : (UINT64_MAX - previous + 1) + new; + return l >= r ? (l - r) + : (UINT64_MAX - r + 1) + l; } -- GitLab From 8c8bed402e1b9ea46bf4e902b162bb6dd1e6699b Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Tue, 24 Jan 2023 17:37:52 +0100 Subject: [PATCH 061/125] fix build util + format --- makefile | 3 ++- src/util.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index f92c57a..d3d470f 100644 --- a/makefile +++ b/makefile @@ -14,7 +14,8 @@ OBJ = \ $(OBJ_DIR)/network.o \ $(OBJ_DIR)/load.o \ $(OBJ_DIR)/infiniband.o \ - $(OBJ_DIR)/temperature.o + $(OBJ_DIR)/temperature.o \ + $(OBJ_DIR)/util.o CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function diff --git a/src/util.c b/src/util.c index 71928c4..e7324e6 100644 --- a/src/util.c +++ b/src/util.c @@ -20,7 +20,7 @@ #include "util.h" -uint64_t uint64_t modulo_substraction(const uint64_t l, const uint64_t r) +uint64_t modulo_substraction(const uint64_t l, const uint64_t r) { return l >= r ? (l - r) : (UINT64_MAX - r + 1) + l; -- GitLab From 70da6bd39077135cd21b43c24d5bf04c45da6f0d Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Wed, 25 Jan 2023 10:23:17 +0100 Subject: [PATCH 062/125] format --- .gitignore | 14 +++++++------- .vscode/settings.json | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 6aa6785..37d1e63 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ -src/counters_option.h -src/captors.h -tests/run -bin -obj -*.swp -*.swo +src/counters_option.h +src/captors.h +tests/run +bin +obj +*.swp +*.swo diff --git a/.vscode/settings.json b/.vscode/settings.json index 480615b..bf13b61 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ -{ - "files.associations": { - "util.h": "c" - } +{ + "files.associations": { + "util.h": "c" + } } \ No newline at end of file -- GitLab From b18cbdcb7225d95e25ca7ec0e139d225208ae75f Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Wed, 25 Jan 2023 10:33:01 +0100 Subject: [PATCH 063/125] mod_subst doc + fix --- src/util.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/util.c b/src/util.c index e7324e6..936a704 100644 --- a/src/util.c +++ b/src/util.c @@ -20,8 +20,15 @@ #include "util.h" -uint64_t modulo_substraction(const uint64_t l, const uint64_t r) +/** + * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, + * meaning that if lhs is greater, rhs's value overflowed. + * @param lhs + * @param rhs + * @return uint64_t + */ +uint64_t modulo_substraction(const uint64_t lhs, const uint64_t rhs) { - return l >= r ? (l - r) - : (UINT64_MAX - r + 1) + l; + return rhs >= lhs ? (rhs - lhs) + : (UINT64_MAX - lhs + 1) + rhs; } -- GitLab From 37f3ea271952fbed80c3f1c31b87f0c622cf0d84 Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Wed, 25 Jan 2023 10:35:30 +0100 Subject: [PATCH 064/125] ignore .vscode --- .gitignore | 1 + .vscode/settings.json | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 37d1e63..8110229 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ bin obj *.swp *.swo +.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index bf13b61..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "util.h": "c" - } -} \ No newline at end of file -- GitLab From 6d780a6f57df660413ba345d3e68602c7dcd0222 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 09:41:58 +0000 Subject: [PATCH 065/125] split code --- tests/small_test.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index b93cd7b..774d497 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -7,8 +7,17 @@ #include <stdint.h> #include <stdio.h> -#define FMT_NULL(string) \ - string = string ? string : "NULL" + +// ---------------------------API_INTERFACE + +#define INIT_TEST_FILE() \ + init_test_file(__FILE__, __func__); + +#define INIT_TEST_FUNCTION() \ + init_test_function(__func__); + +#define DEFERRED_ERROR(nb_error) \ + do { printf("========== Deferred Error : %d\n", nb_error); } while(0) #define TEST_STR(result, expected) \ test_str(__FILE__, __LINE__, result, expected) @@ -27,14 +36,11 @@ nb_error += function(results[i], expecteds[i]); \ } -#define INIT_TEST_FILE() \ - init_test_file(__FILE__, __func__); -#define INIT_TEST_FUNCTION() \ - init_test_function(__func__); +// --------------------------------API_CODE -#define DEFERRED_ERROR(nb_error) \ - do { printf("========== Deferred Error : %d\n", nb_error); } while(0) +#define FMT_NULL(string) \ + string = string ? string : "NULL" typedef int (Comparator) (void *, void *); typedef char *(Formatter) (char *, void *); -- GitLab From fb5aceb534d213df0665c359f8d7d718089ae472 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 09:50:29 +0000 Subject: [PATCH 066/125] fix interface --- tests/small_test.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index 774d497..9e5842d 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -11,13 +11,13 @@ // ---------------------------API_INTERFACE #define INIT_TEST_FILE() \ - init_test_file(__FILE__, __func__); + init_test_file(__FILE__, __func__) #define INIT_TEST_FUNCTION() \ - init_test_function(__func__); + init_test_function(__func__) #define DEFERRED_ERROR(nb_error) \ - do { printf("========== Deferred Error : %d\n", nb_error); } while(0) + printf("========== Deferred Error : %d\n", nb_error) #define TEST_STR(result, expected) \ test_str(__FILE__, __LINE__, result, expected) -- GitLab From 293c73b40a191d92b7ccbef4198f25d9843c3153 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 09:58:48 +0000 Subject: [PATCH 067/125] change test flags --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index d3d470f..f7779a6 100644 --- a/makefile +++ b/makefile @@ -52,7 +52,7 @@ debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og debug: all tests: - gcc -Wall -Wextra -Wpedantic $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run + gcc $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run $(TESTS_DIR)/run format: -- GitLab From 3f358f242077732e267dfc53a5625b45db593d53 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 20:17:46 +0000 Subject: [PATCH 068/125] move doc .c to .h --- src/util.c | 8 +------- src/util.h | 8 ++++++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/util.c b/src/util.c index 936a704..e473d01 100644 --- a/src/util.c +++ b/src/util.c @@ -20,13 +20,7 @@ #include "util.h" -/** - * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, - * meaning that if lhs is greater, rhs's value overflowed. - * @param lhs - * @param rhs - * @return uint64_t - */ + uint64_t modulo_substraction(const uint64_t lhs, const uint64_t rhs) { return rhs >= lhs ? (rhs - lhs) diff --git a/src/util.h b/src/util.h index 991c71e..099c903 100644 --- a/src/util.h +++ b/src/util.h @@ -44,6 +44,14 @@ exit(code); \ } while (0) + +/** + * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, + * meaning that if lhs is greater, rhs's value overflowed. + * @param lhs + * @param rhs + * @return uint64_t + */ uint64_t modulo_substraction(const uint64_t l, const uint64_t r); #endif -- GitLab From 08cf1f376b868b5d0caed236cab0e5b82cdbb407 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 20:45:35 +0000 Subject: [PATCH 069/125] format --- src/util.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util.h b/src/util.h index 099c903..fe6584b 100644 --- a/src/util.h +++ b/src/util.h @@ -46,11 +46,11 @@ /** - * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, + * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, * meaning that if lhs is greater, rhs's value overflowed. - * @param lhs - * @param rhs - * @return uint64_t + * @param lhs + * @param rhs + * @return uint64_t */ uint64_t modulo_substraction(const uint64_t l, const uint64_t r); -- GitLab From e73132cf555541805c4f2462384f21f873960d1b Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 20:45:46 +0000 Subject: [PATCH 070/125] add doc --- tests/small_test.h | 107 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/tests/small_test.h b/tests/small_test.h index 9e5842d..1cdb700 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -10,27 +10,134 @@ // ---------------------------API_INTERFACE +/** + * @def INIT_TEST_FILE() + * @brief Initialize the test file + * This macro is used to initialize the test file. It takes the `__FILE__` and `__func__` preprocessor macros as arguments, which provide the name of the current file and the current function, respectively. + * + * @param __FILE__ preprocessor macro that provides the name of the current file + * @param __func__ preprocessor macro that provides the name of the current function + * + * @code + * INIT_TEST_FILE(); + * @endcode + */ #define INIT_TEST_FILE() \ init_test_file(__FILE__, __func__) +/** + * @def INIT_TEST_FUNCTION() + * @brief Initialize the test function + * This macro is used to initialize the test function. It takes the `__func__` preprocessor macro as an argument, which provides the name of the current function. + * + * @param __func__ preprocessor macro that provides the name of the current function + * + * @code + * INIT_TEST_FUNCTION(); + * @endcode + */ #define INIT_TEST_FUNCTION() \ init_test_function(__func__) +/** + * @def DEFERRED_ERROR(nb_error) + * @brief Print deferred errors + * This macro is used to print deferred errors. It takes a single argument, `nb_error`, which is the number of errors encountered during the test. + * + * @param nb_error the number of errors encountered during the test + * + * @code + * DEFERRED_ERROR(5); + * @endcode + */ #define DEFERRED_ERROR(nb_error) \ printf("========== Deferred Error : %d\n", nb_error) +/** + * @def TEST_STR(result, expected) + * @brief Test strings + * This macro is used to test strings. It takes two arguments: `result`, which is the string to be tested, and `expected`, which is the expected value of the string. + * The macro uses the `test_str()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. + * + * @param result the string to be tested + * @param expected the expected value of the string + * + * @code + * TEST_STR("Hello", "Hello"); + * @endcode + */ #define TEST_STR(result, expected) \ test_str(__FILE__, __LINE__, result, expected) +/** + * @def TEST_BOOLEAN(result, expected) + * @brief Test booleans + * This macro is used to test booleans. It takes two arguments: `result`, which is the boolean to be tested, and `expected`, which is the expected value of the boolean. + * The macro uses the `test_boolean()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. + * + * @param result the boolean to be tested + * @param expected the expected value of the boolean + * + * @code + * TEST_BOOLEAN(1 == 1, true); + * @endcode + */ #define TEST_BOOLEAN(result, expected) \ test_boolean(__FILE__, __LINE__, result, expected) +/** + * @def TEST_PTR(result, expected) + * @brief Test pointers + * This macro is used to test pointers. It takes two arguments: `result`, which is the pointer to be tested, and `expected`, which is the expected value of the pointer. + * The macro uses the `test_ptr()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. + * + * @param result the pointer to be tested + * @param expected the expected value of the pointer + * + * @code + * int x = 5; + * int *ptr = &x; + * TEST_PTR(ptr, &x); + * @endcode + */ #define TEST_PTR(result, expected) \ test_ptr(__FILE__, __LINE__, result, expected) + +/** + * @def TEST_UINT64_T(result, expected) + * @brief Test 64-bit unsigned integers + * This macro is used to test 64-bit unsigned integers. It takes two arguments: `result`, which is the integer to be tested, and `expected`, which is the expected value of the integer. + * The macro uses the `test_uint64_t()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. + * + * @param result the integer to be tested + * @param expected the expected value of the integer + * + * @code + * TEST_UINT64_T(5, 5); + * @endcode + */ #define TEST_UINT64_T(result, expected) \ test_uint64_t(__FILE__, __LINE__, result, expected) +/** + * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) + * @brief Test arrays of data + * The macro uses a for loop to iterate through the array and apply the test function to each element, + * adding any errors to the nb_error variable. + * + * @param function the test function to be used on each element of the array + * @param nb_error the number of errors encountered during the test + * @param size the number of elements in the array + * @param results the array of elements to be tested + * @param expecteds the array of expected values + + * @code + * int results[3] = {1, 2, 3}; + * int expecteds[3] = {1, 2, 3}; + * TEST_T_ARRAY(TEST_INT, errors, 3, results, expecteds); + * @endcode +*/ #define TEST_T_ARRAY(function, nb_error, size, results, expecteds) \ for (unsigned int i = 0; i < size; i++) { \ nb_error += function(results[i], expecteds[i]); \ -- GitLab From da14a2d94922ed8ea93e207f7bfd818a5e4f2f11 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 21:34:14 +0000 Subject: [PATCH 071/125] delete redefinitions of macros --- makefile | 2 +- src/infiniband.c | 4 +--- src/load.c | 2 +- src/mojitos.c | 10 +--------- src/network.c | 1 - src/rapl.c | 3 --- src/temperature.c | 3 +-- 7 files changed, 5 insertions(+), 20 deletions(-) diff --git a/makefile b/makefile index f7779a6..07c7e4f 100644 --- a/makefile +++ b/makefile @@ -63,6 +63,6 @@ format: clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \rm -f $(SRC_DIR)/counters_option.h - \rm $(TESTS_DIR)/run + \rm -f $(TESTS_DIR)/run .PHONY: all clean mojitos debug format tests diff --git a/src/infiniband.c b/src/infiniband.c index 6f47ab2..303795e 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -21,13 +21,11 @@ #include <fcntl.h> #include <stdio.h> #include <string.h> - #include <glob.h> - #include <stdint.h> +#include "util.h" #define NB_SENSOR 4 -#define UNUSED(expr) do { (void)(expr); } while (0) struct network_t { uint64_t values[NB_SENSOR]; diff --git a/src/load.c b/src/load.c index 96d08b8..6dcf2b0 100644 --- a/src/load.c +++ b/src/load.c @@ -23,9 +23,9 @@ #include <stdint.h> #include <string.h> #include <stdio.h> +#include "util.h" #define LOAD_BUFFER_SIZE 1024 -#define UNUSED(expr) do { (void)(expr); } while (0) char buffer[LOAD_BUFFER_SIZE]; static int load_fid = -1; diff --git a/src/mojitos.c b/src/mojitos.c index 55af9f5..3c164c6 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <time.h> #include <unistd.h> +#include "util.h" #define NB_MAX_OPTS 10 #define NB_MAX_CAPTORS 20 @@ -33,15 +34,6 @@ #define OPTPARSE_API static #include "optparse.h" -#define UNUSED(expr) do { (void)(expr); } while (0) -#define PANIC(code, fmt, ...) \ - do { \ - fprintf(stderr, "Exit on error: "); \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - fprintf(stderr, "\n"); \ - exit(code); \ - } while (0) - typedef unsigned int (*initializer_t)(char *, void **); typedef void (*labeler_t)(char **, void *); typedef unsigned int (*getter_t)(uint64_t *, void *); diff --git a/src/network.c b/src/network.c index bee3e5a..543a053 100644 --- a/src/network.c +++ b/src/network.c @@ -26,7 +26,6 @@ #include "util.h" #define NB_SENSOR 4 -#define UNUSED(expr) do { (void)(expr); } while (0) static char *route = "/proc/net/route"; struct network_t { diff --git a/src/rapl.c b/src/rapl.c index 26e9854..8a04d31 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -27,10 +27,7 @@ #include <errno.h> #include "util.h" - #define MAX_HEADER 128 -#define UNUSED(expr) do { (void)(expr); } while (0) - char *get_rapl_string(const char *filename) { diff --git a/src/temperature.c b/src/temperature.c index 049ade7..acc0702 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -24,8 +24,7 @@ #include <string.h> #include <stdio.h> #include <stdint.h> - -#define UNUSED(expr) do { (void)(expr); } while (0) +#include "util.h" struct temperature_t { char **label_list; -- GitLab From 1a3157b0107b270137de33518e857110873bfbe3 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Wed, 25 Jan 2023 22:38:47 +0000 Subject: [PATCH 072/125] cleanup --- src/amd_rapl.c | 200 +------------------------------------------------ src/util.h | 6 -- 2 files changed, 3 insertions(+), 203 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 238161c..26d1446 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -25,6 +25,7 @@ #include <string.h> #include <errno.h> #include <stdlib.h> +#include <assert.h> #include "info_reader.h" #include "util.h" @@ -269,30 +270,6 @@ void free_amd_rapl(_amd_rapl_t *rapl) unsigned int init_amd_rapl(char *none, void **ptr) { -// FILE *fcpuinfo = fopen(cpuinfo, "r"); -// if (fcpuinfo == NULL) { -// perror("fopen"); -// exit(1); -// } -// Parser parser = { -// (GenericPointer) cpus, -// 0, -// MAX_CPUS, -// sizeof(cpu_sensor_t), -// keys, -// NB_KEYS, -// fcpuinfo -// }; -// parse(&parser); -// fclose(fcpuinfo); - -// #ifdef DEBUG -// printf("nb_cpus: %d\n", parser.nb_stored); -// for (unsigned int nb_cpu = 0; nb_cpu < parser.nb_stored; ++nb_cpu) { -// debug_print_sensor(&cpus[nb_cpu]); -// } -// #endif - UNUSED(none); _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); @@ -320,7 +297,6 @@ unsigned int get_amd_rapl(uint64_t *results, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { - DEBUG_WARNING("check if unit is the same") results[i] = get_core_energy(&rapl->sensors[i]); } return rapl->nb; @@ -347,179 +323,9 @@ void clean_amd_rapl(void *ptr) #ifdef __TESTING_AMD__ -#include "small_test.h" - -void test_raw_to_microjoule() -{ - printf("==== TEST raw_to_microjoule() ====\n"); - uint64_t raw = 0; - uint64_t unit = 0; - uint64_t result = 0; - uint64_t expected = 0; - - // Test 1: - // -- Setup - raw = 100; - unit = 0; - expected = 100000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 2: - // -- Setup - raw = 200; - unit = 1; - expected = 100000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 3: - // -- Setup - raw = 500; - unit = 2; - expected = 125000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 4: - // -- Setup - raw = 1000; - unit = 3; - expected = 125000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 5: - // -- Setup - raw = 10000; - unit = 4; - expected = 625000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); -} - -void test_get_name() -{ - printf("==== TEST get_name() ====\n"); - size_t cpu_id = 0; - char *result = NULL; - char expected[100]; - - // TEST 1: - // -- Setup - cpu_id = 0; - strcpy(expected, "core0"); - // -- Run - result = get_name(cpu_id); - // -- Verification - TEST_STR(result, expected); - free(result); - - // TEST 2: - // -- Setup - cpu_id = 10000; - strcpy(expected, "core10000"); - // -- Run - result = get_name(cpu_id); - // -- Verification - TEST_STR(result, expected); - free(result); -} - -#define NONE 0 -#define DUMB_SENSOR(sensor, cpu_id, name) \ - do { \ - sensor = (cpu_sensor_t) { \ - cpu_id, \ - NONE, \ - name, \ - NONE, \ - NONE, \ - NONE, \ - NONE \ - }; \ - } while(0); - -#define DUMB_RAPL(rapl, sensors, nb) \ - do { \ - rapl = (_amd_rapl_t) { \ - sensors, \ - nb \ - }; \ - } while(0); - -void test_label_amd_rapl() -{ - printf("==== TEST label_amd_rapl() ====\n"); - cpu_sensor_t sensors[100]; - _amd_rapl_t rapl; - char *results[100]; - char expecteds[10][100]; - uint64_t nb = 0; - - // Test 1: - // -- Setup - nb = 1; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - // -- Run - label_amd_rapl(results, (void *) &rapl); - // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); - - // Test 2: - // -- Setup - nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 1, "core1"); - DUMB_SENSOR(sensors[2], 2, "core2"); - DUMB_SENSOR(sensors[3], 3, "core3"); - DUMB_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - strcpy(expecteds[1], "core1"); - strcpy(expecteds[2], "core2"); - strcpy(expecteds[3], "core3"); - // -- Run - label_amd_rapl(results, (void *) &rapl); - // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); - - // Test 3: - // -- Setup - nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 3, "core3"); - DUMB_SENSOR(sensors[2], 1, "core1"); - DUMB_SENSOR(sensors[3], 2, "core2"); - DUMB_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - strcpy(expecteds[1], "core3"); - strcpy(expecteds[2], "core1"); - strcpy(expecteds[3], "core2"); - // -- Run - label_amd_rapl(results, (void *) &rapl); - // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); -} - - +#ifdef DEBUG int main() { - test_raw_to_microjoule(); - test_get_name(); - test_label_amd_rapl(); - static const unsigned int time = 10; _amd_rapl_t *rapl = NULL; unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); @@ -548,5 +354,5 @@ int main() clean_amd_rapl(rapl); return 0; } - +#endif #endif diff --git a/src/util.h b/src/util.h index fe6584b..6e510fb 100644 --- a/src/util.h +++ b/src/util.h @@ -29,12 +29,6 @@ #define _impl_CASSERT_LINE(predicate, line, file) \ typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; -#ifdef DEBUG -#define DEBUG_WARNING(warning) #warning warning -#else -#define DEBUG_WARNING(warning) do { } while(0); -#endif - #define UNUSED(expr) do { (void)(expr); } while (0) #define PANIC(code, fmt, ...) \ do { \ -- GitLab From 3a2df456a3b08d6a010fe2debcc07c0ca68102be Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 30 Jan 2023 07:07:39 +0000 Subject: [PATCH 073/125] format --- src/amd_rapl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 26d1446..c06bb29 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -258,15 +258,13 @@ void clean_cpu_sensor(cpu_sensor_t *sensor) free(sensor->name); } -// ----------------------AMD_RAPL_INTERFACE - - void free_amd_rapl(_amd_rapl_t *rapl) { free(rapl->sensors); free(rapl); } +// ----------------------AMD_RAPL_INTERFACE unsigned int init_amd_rapl(char *none, void **ptr) { -- GitLab From 8cb79df658c60b6c30d59f04f723f46aee48ea98 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 30 Jan 2023 09:34:07 +0100 Subject: [PATCH 074/125] build: change how captors are initialised --- configure.sh | 105 +++++++++++++++++++++++++++++++------------------- src/mojitos.c | 27 ++++++------- 2 files changed, 80 insertions(+), 52 deletions(-) diff --git a/configure.sh b/configure.sh index 6a957ff..2d21bf5 100755 --- a/configure.sh +++ b/configure.sh @@ -10,34 +10,52 @@ isnum() { *) return 0 ;; esac } +dprint() { + for v in "$@"; do + decho "$v : $(eval "echo \$$v")" + done +} +decho() { + [ "$debug" = '1' ] && echo "$@" +} +debug=0 target=src/captors.h -noncaptor='counters_option|optparse|captors' +noncaptor='counters_option|optparse|captors|util|info_reader' hdr_blacklist=$noncaptor hdr_whitelist='' usage() { - printf -- 'Usage: %s [-l] [-e <captor>] [-i <captor>]\n' "$(basename "$0")" >&2 + printf -- 'Usage: %s [-l] [-e <captor>] [-i <captor>] [-u <captor>]\n' "$(basename "$0")" >&2 printf -- '-e | --exclude : exclude captor, can be called multiple times\n' >&2 printf -- '-i | --include : include captor, can be called multiple times\n' >&2 printf -- '-l | --list-captors : list all captors and exit\n' >&2 + printf -- '-u | --unique : only include the specified captor\n' >&2 + printf -- ' if this option is used, any usage of `-e` or `-i` will be ignored\n' >&2 exit 1 } ls_captors() { try cd src - printf -- 'captors:\n' >&2 + + [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' + dprint hdr_blacklist + dprint hdr_whitelist + ls -1 *.h | - grep -vE "^($hdr_blacklist)\.h$" | - grep -E "^($hdr_whitelist)\.h$" | - sed 's/\.h$//' | - tee /dev/stderr + grep -xEv "($hdr_blacklist)\.h" | + grep -xE "($hdr_whitelist)\.h" | + sed 's/\.h$//' } gen_captors_h() { captors=$(ls_captors) + nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) + printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 + printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 + echo "$captors" >&2 [ -n "$captors" ] || return @@ -45,17 +63,50 @@ gen_captors_h() { for captor in $captors; do printf '#include "%s.h"\n' "$captor" done - printf '\n' + printf '\n#define NB_CAPTORS %d\n\n' "$nb_captors" # gen `init_captors()` - printf 'void init_captors()\n{\n' + printf 'void init_captors(struct optparse_long *longopts, struct captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' for captor in $captors; do - printf ' longopts[NB_MAX_OPTS + nb_defined_captors] = %s_opt;\n' "$captor" - printf ' captors[nb_defined_captors++] = %s;\n' "$captor" + printf ' longopts[offset + *nb_defined] = %s_opt;\n' "$captor" + printf ' captors[(*nb_defined)++] = %s;\n' "$captor" done + printf ' assert((offset + *nb_defined) <= len);\n' printf '}\n' } +detect_caps() { + [ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters + [ -d /sys/class/infiniband ] && hdr_whitelist=${hdr_whitelist}|infiniband + [ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load" + + if [ -r /proc/net/route ]; then + dev=$(awk 'NR == 2 { print $1 }' /proc/net/route) + [ -e "/sys/class/net/$dev" ] && hdr_whitelist="${hdr_whitelist}|network" + fi + + vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) + vendor_lc=$(echo "$vendor" | tr 'A-Z' 'a-z') + case $vendor_lc in + *intel*) + hdr_whitelist="${hdr_whitelist}|rapl" + ;; + *amd*) + family=$(awk '/cpu[ \t]*family/ {print $3; exit}' /proc/cpuinfo) + if isnum "$family"; then + [ $family -ge 17 ] && hdr_whitelist="${hdr_whitelist}|amd_rapl" + fi + ;; + *) + yell "unsupported processor vendor id: $vendor" + ;; + esac + + [ $(ls -1 /sys/class/hwmon | wc -l) -gt 0 ] && hdr_whitelist="${hdr_whitelist}|temperature" +} + +detect_caps + while [ "$1" ]; do case $1 in --include|-i) @@ -70,6 +121,10 @@ while [ "$1" ]; do ls_captors exit 0 ;; + --unique|-u) + shift; [ "$1" ] || usage + hdr_whitelist=$1 + ;; --help|-h) usage ;; @@ -77,32 +132,4 @@ while [ "$1" ]; do shift done -[ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters -[ -d /sys/class/infiniband ] && hdr_whitelist=${hdr_whitelist}|infiniband -[ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load" - -if [ -r /proc/net/route ]; then - dev=$(awk 'NR == 2 { print $1 }' /proc/net/route) - [ -e "/sys/class/net/$dev" ] && hdr_whitelist="${hdr_whitelist}|network" -fi - -vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) -vendor_lc=$(echo "$vendor" | tr 'A-Z' 'a-z') -case $vendor_lc in -*intel*) - hdr_whitelist="${hdr_whitelist}|rapl" - ;; -*amd*) - family=$(awk '/cpu[ \t]*family/ {print $3; exit}' /proc/cpuinfo) - if isnum "$family"; then - [ $family -ge 17 ] && hdr_whitelist="${hdr_whitelist}|amd_rapl" - fi - ;; -*) - yell "unsupported processor vendor id: $vendor" - ;; -esac - -[ $(ls -1 /sys/class/hwmon | wc -l) -gt 0 ] && hdr_whitelist="${hdr_whitelist}|temperature" - gen_captors_h > "$target" diff --git a/src/mojitos.c b/src/mojitos.c index 3c164c6..dc113fc 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -19,6 +19,7 @@ *******************************************************/ +#include <assert.h> #include <inttypes.h> #include <signal.h> #include <stdio.h> @@ -27,9 +28,6 @@ #include <unistd.h> #include "util.h" -#define NB_MAX_OPTS 10 -#define NB_MAX_CAPTORS 20 - #define OPTPARSE_IMPLEMENTATION #define OPTPARSE_API static #include "optparse.h" @@ -48,9 +46,14 @@ struct captor { labeler_t label; }; -struct captor captors[NB_MAX_CAPTORS]; +int nb_defined_captors = 0; + +#include "captors.h" + +struct captor captors[NB_CAPTORS]; -struct optparse_long longopts[NB_MAX_OPTS + NB_MAX_CAPTORS] = { +#define NB_OPTS 6 +struct optparse_long longopts[NB_OPTS + NB_CAPTORS + 1] = { {"overhead-stats", 's', OPTPARSE_NONE}, {"list", 'l', OPTPARSE_NONE}, {"freq", 'f', OPTPARSE_REQUIRED}, @@ -59,16 +62,14 @@ struct optparse_long longopts[NB_MAX_OPTS + NB_MAX_CAPTORS] = { {"logfile", 'o', OPTPARSE_REQUIRED}, }; -int nb_defined_captors = 0; - -#include "captors.h" void usage(char **argv) { printf("Usage : %s [OPTIONS] [CAPTOR ...] [-o logfile] [-e cmd ...]\n" "\nOPTIONS:\n" - "-t <time>\n" - "-f <freq>\n" + "-t <time>\t\tspecify time\n" + "-f <freq>\t\tspecify frequency\n" + "-e <cmd>\t\tspecify a command\n" "-l\t\tlist the possible performance counters and quit\n" "-s\t\tenable overhead statistics in nanoseconds\n" "if time==0 then loops infinitively\n" @@ -83,7 +84,7 @@ void usage(char **argv) printf("\nCAPTORS:\n"); for (int i = 0; i < nb_defined_captors; i++) { - printf("-%c", longopts[NB_MAX_OPTS + i].shortname); + printf("-%c", longopts[NB_OPTS + i].shortname); if (captors[i].usage_arg != NULL) { printf(" %s", captors[i].usage_arg); } @@ -159,7 +160,7 @@ int main(int argc, char **argv) char **application = NULL; int stat_mode = -1; - init_captors(); + init_captors(longopts, captors, NB_OPTS + NB_CAPTORS, NB_OPTS, &nb_defined_captors); if (argc == 1) { usage(argv); @@ -207,7 +208,7 @@ int main(int argc, char **argv) default: { int ismatch = 0; for (int i = 0; i < nb_defined_captors && !ismatch; i++) { - if (opt == longopts[NB_MAX_OPTS + i].shortname) { + if (opt == longopts[NB_OPTS + i].shortname) { ismatch = 1; add_source(&captors[i], options.optarg); } -- GitLab From 30f3885e9da6d0b6ab4cf0ba6a8b79e318911a7c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 30 Jan 2023 09:21:50 +0000 Subject: [PATCH 075/125] compile with amd --- makefile | 3 ++- src/amd_rapl.c | 12 ++++++++---- src/amd_rapl.h | 10 ++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/makefile b/makefile index 07c7e4f..eabffaf 100644 --- a/makefile +++ b/makefile @@ -15,7 +15,8 @@ OBJ = \ $(OBJ_DIR)/load.o \ $(OBJ_DIR)/infiniband.o \ $(OBJ_DIR)/temperature.o \ - $(OBJ_DIR)/util.o + $(OBJ_DIR)/util.o \ + $(OBJ_DIR)/amd_rapl.o CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function diff --git a/src/amd_rapl.c b/src/amd_rapl.c index c06bb29..eca6831 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -29,7 +29,6 @@ #include "info_reader.h" #include "util.h" -#include "amd_rapl.h" #define BUFFER_SIZE 64 @@ -100,7 +99,7 @@ uint64_t read_msr(int fd, uint64_t msr) { uint64_t data; if (pread(fd, &data, sizeof data, msr) != sizeof data) { - fprintf(stderr, "msr(%ld):", msr); + fprintf(stderr, "read_msr(%ld):", msr); perror("pread"); exit(127); } @@ -217,7 +216,9 @@ void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) int fd = open(filename, O_RDONLY); if (fd < 0) { - perror("rdmsr:open"); + fprintf(stderr, "open("); + fprintf(stderr, base_str, cpu_id); + perror(")"); exit(127); } @@ -273,7 +274,9 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int nb_cpu = get_nb_cpu(); if (nb_cpu == 0) { - perror("get_nb_cpu"); + fprintf(stderr, "open("); + fprintf(stderr, base_str,0); + perror(")"); exit(127); } @@ -319,6 +322,7 @@ void clean_amd_rapl(void *ptr) free(rapl); } +// -----------------------------ENTRY_POINT #ifdef __TESTING_AMD__ #ifdef DEBUG diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 459c136..4f375b9 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -22,3 +22,13 @@ unsigned int init_amd_rapl(char *, void **); unsigned int get_amd_rapl(uint64_t *results, void *); void clean_amd_rapl(void *); void label_amd_rapl(char **labels, void *); + +struct optparse_long amd_rapl_opt = {"amd_rapl", 'a', OPTPARSE_NONE}; +struct captor amd_rapl = { + .usage_arg = NULL, + .usage_msg = "AMD_RAPL", + .init = init_amd_rapl, + .get = get_amd_rapl, + .clean = clean_amd_rapl, + .label = label_amd_rapl, +}; -- GitLab From eb2a21a7c30e8da64ee7db24558a8e39ba797be4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 07:08:21 +0000 Subject: [PATCH 076/125] update test lib --- tests/amd_rapl.c | 78 ++++++++++----------------- tests/info_reader.c | 129 ++++++++++++++++++-------------------------- tests/main.c | 19 +++---- tests/small_test.h | 122 ++++++++++++++++++++++++++++------------- tests/util.c | 25 ++++----- 5 files changed, 180 insertions(+), 193 deletions(-) diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 1ddf234..25408f1 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -1,11 +1,7 @@ #include "small_test.h" #include "../src/amd_rapl.c" -int test_raw_to_microjoule() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; - +TFUNCTION(test_raw_to_microjoule, { uint64_t raw = 0; uint64_t unit = 0; uint64_t result = 0; @@ -19,9 +15,9 @@ int test_raw_to_microjoule() // -- Run result = raw_to_microjoule(raw, unit); // -- Verification - nb_error += TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); - // nb_error += TEST 2: + // TEST 2: // -- Setup raw = 200; unit = 1; @@ -29,9 +25,9 @@ int test_raw_to_microjoule() // -- Run result = raw_to_microjoule(raw, unit); // -- Verification - nb_error += TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); - // nb_error += TEST 3: + // TEST 3: // -- Setup raw = 500; unit = 2; @@ -39,9 +35,9 @@ int test_raw_to_microjoule() // -- Run result = raw_to_microjoule(raw, unit); // -- Verification - nb_error += TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); - // nb_error += TEST 4: + // TEST 4: // -- Setup raw = 1000; unit = 3; @@ -49,9 +45,9 @@ int test_raw_to_microjoule() // -- Run result = raw_to_microjoule(raw, unit); // -- Verification - nb_error += TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); - // nb_error += TEST 5: + // TEST 5: // -- Setup raw = 10000; unit = 4; @@ -59,42 +55,34 @@ int test_raw_to_microjoule() // -- Run result = raw_to_microjoule(raw, unit); // -- Verification - nb_error += TEST_UINT64_T(&result, &expected); - - return nb_error; -} - -int test_get_name() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; + TEST_UINT64_T(&result, &expected); +}) +TFUNCTION(test_get_name, { size_t cpu_id = 0; char *result = NULL; char expected[100]; - // nb_error += TEST 1: + // TEST 1: // -- Setup cpu_id = 0; strcpy(expected, "core0"); // -- Run result = get_name(cpu_id); // -- Verification - nb_error += TEST_STR(result, expected); + TEST_STR(result, expected); free(result); - // nb_error += TEST 2: + // TEST 2: // -- Setup cpu_id = 10000; strcpy(expected, "core10000"); // -- Run result = get_name(cpu_id); // -- Verification - nb_error += TEST_STR(result, expected); + TEST_STR(result, expected); free(result); - - return nb_error; -} +}) #define NONE 0 #define DUMB_SENSOR(sensor, cpu_id, name) \ @@ -118,10 +106,7 @@ int test_get_name() }; \ } while(0); -int test_label_amd_rapl() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; +TFUNCTION(test_label_amd_rapl, { cpu_sensor_t sensors[100]; _amd_rapl_t rapl; char *results[100]; @@ -137,7 +122,7 @@ int test_label_amd_rapl() // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb_error, nb, results, expecteds); + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); // Test 2: // -- Setup @@ -154,7 +139,7 @@ int test_label_amd_rapl() // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb_error, nb, results, expecteds); + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); // Test 3: // -- Setup @@ -171,21 +156,14 @@ int test_label_amd_rapl() // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb_error, nb, results, expecteds); - - return nb_error; -} - -int test_amd_rapl() -{ - INIT_TEST_FILE(); - - int nb_error = 0; - nb_error += test_raw_to_microjoule(); - nb_error += test_get_name(); - nb_error += test_label_amd_rapl(); - return nb_error; -} + TEST_T_ARRAY(TEST_STR, nb, results, expecteds); +}) + +TFILE_ENTRY_POINT(test_amd_rapl, { + CALL_TFUNCTION(test_raw_to_microjoule); + CALL_TFUNCTION(test_get_name); + CALL_TFUNCTION(test_label_amd_rapl); +}) #ifdef __TESTING__AMD__ int main() diff --git a/tests/info_reader.c b/tests/info_reader.c index 3953109..761d86a 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -1,71 +1,57 @@ #include "small_test.h" -int test_replace_first() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; - +TFUNCTION(test_replace_first, { char test1[] = "This is my string"; replace_first(test1, 'i', 'I'); - nb_error += TEST_STR(test1, "ThIs is my string"); + TEST_STR(test1, "ThIs is my string"); char test2[] = "This is my string"; replace_first(test2, 'x', 'X'); - nb_error += TEST_STR(test2, "This is my string"); + TEST_STR(test2, "This is my string"); char test3[] = "This is my string"; replace_first(test3, ' ', '_'); - nb_error += TEST_STR(test3, "This_is my string"); - return nb_error; -} - -int test_split_on_delimiter() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; + TEST_STR(test3, "This_is my string"); +}) +TFUNCTION(test_split_on_delimiter, { char test4[] = "key:value"; char *key; char *value; + split_on_delimiter(test4, ":", &key, &value); - nb_error += TEST_STR(key, "key"); - nb_error += TEST_STR(value, "value"); + TEST_STR(key, "key"); + TEST_STR(value, "value"); char test5[] = "key: value"; split_on_delimiter(test5, ":", &key, &value); - nb_error += TEST_STR(key, "key"); - nb_error += TEST_STR(value, " value"); + TEST_STR(key, "key"); + TEST_STR(value, " value"); char test6[] = "key:value"; replace_first(test6, ':', ' '); split_on_delimiter(test6, " ", &key, &value); - nb_error += TEST_STR(key, "key"); - nb_error += TEST_STR(value, "value"); + TEST_STR(key, "key"); + TEST_STR(value, "value"); char test7[] = ""; split_on_delimiter(test7, ":", &key, &value); - nb_error += TEST_STR(key, NULL); - nb_error += TEST_STR(value, NULL); + TEST_STR(key, NULL); + TEST_STR(value, NULL); char test9[] = "key:value:extra"; split_on_delimiter(test9, ":", &key, &value); - nb_error += TEST_STR(key, "key"); - nb_error += TEST_STR(value, "value:extra"); + TEST_STR(key, "key"); + TEST_STR(value, "value:extra"); char test10[] = "key: value :extra"; split_on_delimiter(test10, ":", &key, &value); - nb_error += TEST_STR(key, "key"); - nb_error += TEST_STR(value, " value :extra"); - - return nb_error; -} - -int test_start_with() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; + TEST_STR(key, "key"); + TEST_STR(value, " value :extra"); +}) +TFUNCTION(test_start_with, { char *prefix = NULL; char *string = NULL; bool result = false; @@ -75,30 +61,28 @@ int test_start_with() prefix = "Hello"; string = "Hello World"; result = start_with(prefix, string); - nb_error += TEST_BOOLEAN(&result, &_true); + TEST_BOOLEAN(&result, &_true); prefix = "Goodbye"; string = "Hello World"; result = start_with(prefix, string); - nb_error += TEST_BOOLEAN(&result, &_false); + TEST_BOOLEAN(&result, &_false); prefix = "Hello World"; string = "Hello"; result = start_with(prefix, string); - nb_error += TEST_BOOLEAN(&result, &_false); + TEST_BOOLEAN(&result, &_false); prefix = "Hello"; string = "Hello"; result = start_with(prefix, string); - nb_error += TEST_BOOLEAN(&result, &_true); + TEST_BOOLEAN(&result, &_true); prefix = NULL; string = "Hello World"; result = start_with(prefix, string); - nb_error += TEST_BOOLEAN(&result, &_false); - - return nb_error; -} + TEST_BOOLEAN(&result, &_false); +}) #define DUMB_KEYFINDER(key_finder, key, delimiter) \ do { \ @@ -124,10 +108,7 @@ int test_start_with() } while (0); -int test_match() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; +TFUNCTION(test_match, { // usefull variable : bool _true = true; bool _false = false; @@ -148,9 +129,9 @@ int test_match() // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - nb_error += TEST_BOOLEAN(&result, &_true); - nb_error += TEST_PTR(found_key_finder, &keys[0]); - nb_error += TEST_STR(raw_value, "value"); + TEST_BOOLEAN(&result, &_true); + TEST_PTR(found_key_finder, &keys[0]); + TEST_STR(raw_value, "value"); // Test 2: // -- Setup @@ -162,9 +143,9 @@ int test_match() // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - nb_error += TEST_BOOLEAN(&result, &_false); - nb_error += TEST_PTR(found_key_finder, NULL); - nb_error += TEST_STR(raw_value, NULL); + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); // Test 3: // -- Setup @@ -176,9 +157,9 @@ int test_match() // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - nb_error += TEST_BOOLEAN(&result, &_false); - nb_error += TEST_PTR(found_key_finder, NULL); - nb_error += TEST_STR(raw_value, NULL); + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); // Test 4: // -- Setup @@ -191,9 +172,9 @@ int test_match() // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - nb_error += TEST_BOOLEAN(&result, &_true); - nb_error += TEST_PTR(found_key_finder, &keys[1]); - nb_error += TEST_STR(raw_value, "value"); + TEST_BOOLEAN(&result, &_true); + TEST_PTR(found_key_finder, &keys[1]); + TEST_STR(raw_value, "value"); // Test 5: // -- Setup @@ -204,25 +185,17 @@ int test_match() raw_value = NULL; // -- Run result = match(&parser, line, &found_key_finder, &raw_value); - nb_error += TEST_BOOLEAN(&result, &_false); - nb_error += TEST_PTR(found_key_finder, NULL); - nb_error += TEST_STR(raw_value, NULL); - - return nb_error; -} - -int test_info_reader() -{ - INIT_TEST_FILE(); - int nb_error = 0; - - nb_error += test_replace_first(); - nb_error += test_split_on_delimiter(); - nb_error += test_start_with(); - nb_error += test_match(); - - return nb_error; -} + TEST_BOOLEAN(&result, &_false); + TEST_PTR(found_key_finder, NULL); + TEST_STR(raw_value, NULL); +}) + +TFILE_ENTRY_POINT(test_info_reader, { + CALL_TFUNCTION(test_replace_first); + CALL_TFUNCTION(test_split_on_delimiter); + CALL_TFUNCTION(test_start_with); + CALL_TFUNCTION(test_match); +}) #ifdef __TESTING_INFO_READER__ int main() diff --git a/tests/main.c b/tests/main.c index b14f518..a3a43cb 100644 --- a/tests/main.c +++ b/tests/main.c @@ -1,16 +1,9 @@ -#include "amd_rapl.c" #include "util.c" +#include "amd_rapl.c" #include "info_reader.c" -int main() -{ - int nb_error = 0; - - nb_error += test_amd_rapl(); - nb_error += test_info_reader(); - nb_error += test_util(); - - DEFERRED_ERROR(nb_error); - return nb_error; -} - +TFILE_ENTRY_POINT(main, { + CALL_TFUNCTION(test_util); + CALL_TFUNCTION(test_amd_rapl); + CALL_TFUNCTION(test_info_reader); +}) diff --git a/tests/small_test.h b/tests/small_test.h index 1cdb700..0e39868 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -7,51 +7,66 @@ #include <stdint.h> #include <stdio.h> - // ---------------------------API_INTERFACE /** - * @def INIT_TEST_FILE() - * @brief Initialize the test file - * This macro is used to initialize the test file. It takes the `__FILE__` and `__func__` preprocessor macros as arguments, which provide the name of the current file and the current function, respectively. + * @brief Define the entry point of a test file. + * This macro is used to define the entry point of a test file. + * It defines a function with the specified file_name that contains the test code specified in code. * - * @param __FILE__ preprocessor macro that provides the name of the current file - * @param __func__ preprocessor macro that provides the name of the current function + * When the function is called, it initializes the test file using the INIT_TEST_FILE macro, + * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, + * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. + * The function returns the value of __error_counter__, + * which indicates the number of errors encountered during the tests. * - * @code - * INIT_TEST_FILE(); - * @endcode + * @param file_name The name of the function that serves as the entry point for the test file. + * @param code The test code to be executed in the function. */ -#define INIT_TEST_FILE() \ - init_test_file(__FILE__, __func__) +#define TFILE_ENTRY_POINT(file_name, code) \ + int file_name() \ +{ \ + INIT_TEST_FILE();\ + int __error_counter__ = 0;\ + do code while(0);\ + DEFERRED_FILE_ERROR(__error_counter__); \ + return __error_counter__;\ +} /** - * @def INIT_TEST_FUNCTION() - * @brief Initialize the test function - * This macro is used to initialize the test function. It takes the `__func__` preprocessor macro as an argument, which provides the name of the current function. + * @brief Define a test function within a test file. + * This macro is used to define a test function within a test file. + * It defines a function with the specified function_name that contains the test code specified in code. * - * @param __func__ preprocessor macro that provides the name of the current function + * When the function is called, it initializes the test function using the INIT_TEST_FUNCTION macro, + * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, + * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. + * The function returns the value of __error_counter__, which indicates the number of errors encountered during the tests. * - * @code - * INIT_TEST_FUNCTION(); - * @endcode + * @param function_name The name of the test function. + * @param code The test code to be executed in the function. */ -#define INIT_TEST_FUNCTION() \ - init_test_function(__func__) +#define TFUNCTION(function_name, code) \ + int function_name() \ +{ \ + INIT_TEST_FUNCTION(); \ + int __error_counter__ = 0; \ + do code while(0); \ + DEFERRED_FUNCTION_ERROR(__error_counter__); \ + return __error_counter__; \ +} /** - * @def DEFERRED_ERROR(nb_error) - * @brief Print deferred errors - * This macro is used to print deferred errors. It takes a single argument, `nb_error`, which is the number of errors encountered during the test. + * @brief Call a test function within a test file. + * This macro is used to call a test function within a test file. + * It calls the function specified by function_name and adds the return value to the __error_counter__ variable. + * This allows multiple test functions to be executed and their error count to be accumulated. * - * @param nb_error the number of errors encountered during the test - * - * @code - * DEFERRED_ERROR(5); - * @endcode + * @param function_name The name of the test function to be called. */ -#define DEFERRED_ERROR(nb_error) \ - printf("========== Deferred Error : %d\n", nb_error) +#define CALL_TFUNCTION(function_name) \ + __error_counter__ += function_name() + /** * @def TEST_STR(result, expected) @@ -67,7 +82,7 @@ * @endcode */ #define TEST_STR(result, expected) \ - test_str(__FILE__, __LINE__, result, expected) + __error_counter__ += test_str(__FILE__, __LINE__, result, expected) /** * @def TEST_BOOLEAN(result, expected) @@ -83,7 +98,7 @@ * @endcode */ #define TEST_BOOLEAN(result, expected) \ - test_boolean(__FILE__, __LINE__, result, expected) + __error_counter__ += test_boolean(__FILE__, __LINE__, result, expected) /** * @def TEST_PTR(result, expected) @@ -101,7 +116,7 @@ * @endcode */ #define TEST_PTR(result, expected) \ - test_ptr(__FILE__, __LINE__, result, expected) + __error_counter__ += test_ptr(__FILE__, __LINE__, result, expected) /** @@ -118,7 +133,7 @@ * @endcode */ #define TEST_UINT64_T(result, expected) \ - test_uint64_t(__FILE__, __LINE__, result, expected) + __error_counter__ += test_uint64_t(__FILE__, __LINE__, result, expected) /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) @@ -138,14 +153,49 @@ * TEST_T_ARRAY(TEST_INT, errors, 3, results, expecteds); * @endcode */ -#define TEST_T_ARRAY(function, nb_error, size, results, expecteds) \ +#define TEST_T_ARRAY(function, size, results, expecteds) \ for (unsigned int i = 0; i < size; i++) { \ - nb_error += function(results[i], expecteds[i]); \ + function(results[i], expecteds[i]); \ } // --------------------------------API_CODE +/** + * @def INIT_TEST_FILE() + * @brief Initialize the test file + * This macro is used to initialize the test file. It takes the `__FILE__` and `__func__` preprocessor macros as arguments, which provide the name of the current file and the current function, respectively. + * + * @param __FILE__ preprocessor macro that provides the name of the current file + * @param __func__ preprocessor macro that provides the name of the current function + * + * @code + * INIT_TEST_FILE(); + * @endcode + */ +#define INIT_TEST_FILE() \ + init_test_file(__FILE__, __func__) + +/** + * @def INIT_TEST_FUNCTION() + * @brief Initialize the test function + * This macro is used to initialize the test function. It takes the `__func__` preprocessor macro as an argument, which provides the name of the current function. + * + * @param __func__ preprocessor macro that provides the name of the current function + * + * @code + * INIT_TEST_FUNCTION(); + * @endcode + */ +#define INIT_TEST_FUNCTION() \ + init_test_function(__func__) + +#define DEFERRED_FILE_ERROR(nb_error) \ + printf("========== Deferred Error : %d\n", nb_error); + +#define DEFERRED_FUNCTION_ERROR(nb_error) \ + printf(" | Deferred Error : %d\n", nb_error); + #define FMT_NULL(string) \ string = string ? string : "NULL" diff --git a/tests/util.c b/tests/util.c index eba4da3..2416049 100644 --- a/tests/util.c +++ b/tests/util.c @@ -2,10 +2,7 @@ #include "small_test.h" -int test_modulo_substraction() -{ - INIT_TEST_FUNCTION(); - int nb_error = 0; +TFUNCTION(test_modulo_substraction, { uint64_t previous = 0; uint64_t new = 0; uint64_t result = 0; @@ -19,7 +16,7 @@ int test_modulo_substraction() // -- Run result = modulo_substraction(previous, new); // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); // Test 2: // -- Setup @@ -29,7 +26,7 @@ int test_modulo_substraction() // -- Run result = modulo_substraction(previous, new); // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); // Test 3: // -- Setup @@ -39,7 +36,7 @@ int test_modulo_substraction() // -- Run result = modulo_substraction(previous, new); // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); // Test 4: // -- Setup @@ -49,13 +46,9 @@ int test_modulo_substraction() // -- Run result = modulo_substraction(previous, new); // -- Verification - nb_error = TEST_UINT64_T(&result, &expected); + TEST_UINT64_T(&result, &expected); +}) - return nb_error; -} -int test_util() -{ - INIT_TEST_FILE(); - int nb_error = test_modulo_substraction(); - return nb_error; -} +TFILE_ENTRY_POINT(test_util, { + CALL_TFUNCTION(test_modulo_substraction); +}) -- GitLab From d3f4897ac40194204c35b55cf2ab2d579f607ab9 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 08:58:16 +0000 Subject: [PATCH 077/125] patch conversion --- src/amd_rapl.c | 35 +++++++++++++++++++---------------- tests/amd_rapl.c | 8 ++++---- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index eca6831..0eeb2d2 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -26,6 +26,7 @@ #include <errno.h> #include <stdlib.h> #include <assert.h> +#include <math.h> #include "info_reader.h" #include "util.h" @@ -108,19 +109,19 @@ uint64_t read_msr(int fd, uint64_t msr) uint64_t read_unit(int fd) { - u_int64_t unit = read_msr(fd, msr_rapl_power_unit); + uint64_t unit = read_msr(fd, msr_rapl_power_unit); return ((unit & amd_energy_unit_mask) >> 8); } uint64_t read_raw_core_energy(int fd) { - u_int64_t energy = read_msr(fd, energy_core_msr); + uint64_t energy = read_msr(fd, energy_core_msr); return energy & amd_energy_mask; } uint64_t read_raw_pkg_energy(int fd) { - u_int64_t energy = read_msr(fd, energy_pkg_msr); + uint64_t energy = read_msr(fd, energy_pkg_msr); return energy & amd_energy_mask; } @@ -128,11 +129,12 @@ uint64_t read_raw_pkg_energy(int fd) uint64_t raw_to_microjoule(uint64_t raw, uint64_t unit) { - static const uint64_t to_microjoule = 1000000UL; + static const double to_microjoule = 1000000.0; + double d_raw = (double) raw; + double d_unit = (double) unit; // raw * (1 / (unit^2)) -> Joule // Joule * 1000000 -> uJoule - uint64_t microjoule = (raw * to_microjoule) / (1UL << unit); - return microjoule; + return ((d_raw * to_microjoule) / (d_unit * d_unit)); } uint64_t raw_to_joule(uint64_t raw, uint64_t unit) { @@ -222,8 +224,8 @@ void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) exit(127); } - u_int64_t raw_core_energy = read_raw_core_energy(fd); - u_int64_t raw_pkg_energy = read_raw_pkg_energy(fd); + uint64_t raw_core_energy = read_raw_core_energy(fd); + uint64_t raw_pkg_energy = read_raw_pkg_energy(fd); sensor->cpu_id = cpu_id; sensor->name = get_name(cpu_id); @@ -233,22 +235,22 @@ void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) sensor->pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); } -u_int64_t get_core_energy(cpu_sensor_t *sensor) +uint64_t get_core_energy(cpu_sensor_t *sensor) { - u_int64_t raw_core_energy = read_raw_core_energy(sensor->fd); - u_int64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); + uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); + uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - u_int64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); + uint64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); sensor->core_energy = core_energy; return energy_consumed; } -u_int64_t get_pkg_energy(cpu_sensor_t *sensor) +uint64_t get_pkg_energy(cpu_sensor_t *sensor) { - u_int64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); - u_int64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); + uint64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); + uint64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); - u_int64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); + uint64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); sensor->pkg_energy = pkg_energy; return energy_consumed; } @@ -328,6 +330,7 @@ void clean_amd_rapl(void *ptr) #ifdef DEBUG int main() { + s_round_to_uint64(1.0); static const unsigned int time = 10; _amd_rapl_t *rapl = NULL; unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 25408f1..3f97f32 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -10,8 +10,8 @@ TFUNCTION(test_raw_to_microjoule, { // Test 1: // -- Setup raw = 100; - unit = 0; - expected = 100000000; + unit = 1000; + expected = 100; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification @@ -21,7 +21,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 200; unit = 1; - expected = 100000000; + expected = 200000000; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification @@ -41,7 +41,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 1000; unit = 3; - expected = 125000000; + expected = 111111111; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification -- GitLab From 7235a17559222838681c350646667d3d87cd15fb Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 10:13:55 +0000 Subject: [PATCH 078/125] fix: doc incompatible with definition --- src/amd_rapl.c | 4 ++-- src/util.c | 4 ++-- src/util.h | 4 ++-- tests/util.c | 40 ++++++++++++++++++++++++---------------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 0eeb2d2..09ea7c0 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -240,7 +240,7 @@ uint64_t get_core_energy(cpu_sensor_t *sensor) uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - uint64_t energy_consumed = modulo_substraction(sensor->core_energy, core_energy); + uint64_t energy_consumed = modulo_substraction(core_energy, sensor->core_energy); sensor->core_energy = core_energy; return energy_consumed; } @@ -250,7 +250,7 @@ uint64_t get_pkg_energy(cpu_sensor_t *sensor) uint64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); uint64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); - uint64_t energy_consumed = modulo_substraction(sensor->pkg_energy, pkg_energy); + uint64_t energy_consumed = modulo_substraction(pkg_energy, sensor->pkg_energy); sensor->pkg_energy = pkg_energy; return energy_consumed; } diff --git a/src/util.c b/src/util.c index e473d01..5e835a7 100644 --- a/src/util.c +++ b/src/util.c @@ -23,6 +23,6 @@ uint64_t modulo_substraction(const uint64_t lhs, const uint64_t rhs) { - return rhs >= lhs ? (rhs - lhs) - : (UINT64_MAX - lhs + 1) + rhs; + return lhs >= rhs ? (lhs - rhs) + : (UINT64_MAX - rhs + 1) + lhs; } diff --git a/src/util.h b/src/util.h index 6e510fb..23978c1 100644 --- a/src/util.h +++ b/src/util.h @@ -41,11 +41,11 @@ /** * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, - * meaning that if lhs is greater, rhs's value overflowed. + * meaning that if rhs is greater, lhs's value overflowed. * @param lhs * @param rhs * @return uint64_t */ -uint64_t modulo_substraction(const uint64_t l, const uint64_t r); +uint64_t modulo_substraction(const uint64_t lhs, const uint64_t rhs); #endif diff --git a/tests/util.c b/tests/util.c index 2416049..a91c58f 100644 --- a/tests/util.c +++ b/tests/util.c @@ -3,50 +3,58 @@ TFUNCTION(test_modulo_substraction, { - uint64_t previous = 0; - uint64_t new = 0; + uint64_t lhs = 0; + uint64_t rhs = 0; uint64_t result = 0; uint64_t expected = 0; // Test 1: // -- Setup - previous = 10; - new = 10; + lhs = 10; + rhs = 10; expected = 0; // -- Run - result = modulo_substraction(previous, new); + result = modulo_substraction(lhs, rhs); // -- Verification TEST_UINT64_T(&result, &expected); // Test 2: // -- Setup - previous = UINT64_MAX; - new = 0; - expected = 1; + lhs = UINT64_MAX; + rhs = 0; + expected = UINT64_MAX; // -- Run - result = modulo_substraction(previous, new); + result = modulo_substraction(lhs, rhs); // -- Verification TEST_UINT64_T(&result, &expected); // Test 3: // -- Setup - previous = 0; - new = UINT64_MAX; - expected = UINT64_MAX; + lhs = 0; + rhs = UINT64_MAX; + expected = 1; // -- Run - result = modulo_substraction(previous, new); + result = modulo_substraction(lhs, rhs); // -- Verification TEST_UINT64_T(&result, &expected); // Test 4: // -- Setup - previous = 20; - new = 10; + lhs = 10; + rhs = 20; expected = UINT64_MAX - 9; // -- Run - result = modulo_substraction(previous, new); + result = modulo_substraction(lhs, rhs); // -- Verification TEST_UINT64_T(&result, &expected); + + // Test 5: + // -- Setup + lhs = 1000; + rhs = 1000; + expected = 0; + result = modulo_substraction(lhs, rhs); + TEST_UINT64_T(&result, &expected); }) TFILE_ENTRY_POINT(test_util, { -- GitLab From 093e6696fb64b16f04d799170f9c1cb9059a1f4c Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 12:39:47 +0100 Subject: [PATCH 079/125] build: support for multiple options per captor - Makefile now includes captors.mk which defines captor object files to build (the previous behaviour was to build all captors regardless of the captor selection during configuration) - correct a bug in configure.sh : now properly detect amd cpu family - configure.sh now print an error when 0 captors are selected - configure.sh now do a `make clean` on successful configuration --- .gitignore | 17 ++++---- configure.sh | 71 ++++++++++++++++++++++++-------- makefile | 14 +++---- src/amd_rapl.h | 16 ++++++-- src/counters.h | 29 +++++++++---- src/infiniband.h | 17 ++++++-- src/load.h | 16 ++++++-- src/mojitos.c | 101 ++++++++++++++++++++++++++++++---------------- src/network.h | 15 +++++-- src/optparse.h | 2 + src/rapl.h | 16 ++++++-- src/temperature.h | 16 ++++++-- 12 files changed, 232 insertions(+), 98 deletions(-) diff --git a/.gitignore b/.gitignore index 8110229..095c70a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,9 @@ -src/counters_option.h -src/captors.h -tests/run -bin -obj -*.swp -*.swo -.vscode +tests/run +src/counters_option.h +src/captors.h +captors.mk +bin +obj +*.swp +*.swo +.vscode diff --git a/configure.sh b/configure.sh index 2d21bf5..49e1789 100755 --- a/configure.sh +++ b/configure.sh @@ -20,7 +20,8 @@ decho() { } debug=0 -target=src/captors.h +target_hdr=src/captors.h +target_mk=captors.mk noncaptor='counters_option|optparse|captors|util|info_reader' @@ -41,8 +42,8 @@ ls_captors() { try cd src [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' - dprint hdr_blacklist - dprint hdr_whitelist + dprint hdr_blacklist >&2 + dprint hdr_whitelist >&2 ls -1 *.h | grep -xEv "($hdr_blacklist)\.h" | @@ -50,31 +51,53 @@ ls_captors() { sed 's/\.h$//' } +# gen_captors_h(captors, nb_captors) gen_captors_h() { - captors=$(ls_captors) - nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) - printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 - printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 - echo "$captors" >&2 - - [ -n "$captors" ] || return + captors=$1 + nb_captors=$2 + nb_captor_opts=$( + for captor in $captors; do + sed -n 's/.*'"${captor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${captor}.h" + done | + paste -s -d '+' | + bc + ) + + dprint captors >&2 + dprint nb_captor_opts >&2 + isnum "$nb_captor_opts" || die "could not get total number of captors's command-line options" # gen includes for captor in $captors; do printf '#include "%s.h"\n' "$captor" done - printf '\n#define NB_CAPTORS %d\n\n' "$nb_captors" + printf '\n#define NB_CAPTOR %d\n\n' "$nb_captors" + printf '\n#define NB_CAPTOR_OPT %d\n\n' "$nb_captor_opts" # gen `init_captors()` - printf 'void init_captors(struct optparse_long *longopts, struct captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' + printf 'void init_captors(Optparse *longopts, Captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' + printf ' int opt_idx = offset;\n' for captor in $captors; do - printf ' longopts[offset + *nb_defined] = %s_opt;\n' "$captor" - printf ' captors[(*nb_defined)++] = %s;\n' "$captor" + cat <<-! + for (int i = 0; i < ${captor}.nb_opt; i++) { + longopts[opt_idx++] = ${captor}_opt[i]; + } + captors[(*nb_defined)++] = ${captor}; + ! done printf ' assert((offset + *nb_defined) <= len);\n' printf '}\n' } +gen_captors_mk() { + captors=$1 + printf 'CAPTOR_OBJ = ' + for captor in $captors; do + printf '$(OBJ_DIR)/%s.o ' "$captor" + done + printf '\n' +} + detect_caps() { [ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters [ -d /sys/class/infiniband ] && hdr_whitelist=${hdr_whitelist}|infiniband @@ -92,7 +115,7 @@ detect_caps() { hdr_whitelist="${hdr_whitelist}|rapl" ;; *amd*) - family=$(awk '/cpu[ \t]*family/ {print $3; exit}' /proc/cpuinfo) + family=$(awk '/cpu[ \t]*family/ {print $4; exit}' /proc/cpuinfo) if isnum "$family"; then [ $family -ge 17 ] && hdr_whitelist="${hdr_whitelist}|amd_rapl" fi @@ -132,4 +155,20 @@ while [ "$1" ]; do shift done -gen_captors_h > "$target" +captors=$(ls_captors) +nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) + +if [ "$nb_captors" -eq 0 ]; then + printf -- '0 captors are selected. cannot build.\n' >&2 + exit 1 +fi + +try gen_captors_h "$captors" "$nb_captors" > "$target_hdr" +try gen_captors_mk "$captors" > "$target_mk" + +printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 +printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 +echo "$captors" >&2 + +make clean >/dev/null + diff --git a/makefile b/makefile index eabffaf..3f8a70b 100644 --- a/makefile +++ b/makefile @@ -8,15 +8,13 @@ TESTS_DIR = tests BIN = mojitos +CAPTOR_OBJ = + +include ./captors.mk + OBJ = \ - $(OBJ_DIR)/counters.o \ - $(OBJ_DIR)/rapl.o \ - $(OBJ_DIR)/network.o \ - $(OBJ_DIR)/load.o \ - $(OBJ_DIR)/infiniband.o \ - $(OBJ_DIR)/temperature.o \ - $(OBJ_DIR)/util.o \ - $(OBJ_DIR)/amd_rapl.o + $(CAPTOR_OBJ) \ + $(OBJ_DIR)/util.o CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 4f375b9..90f6161 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -23,12 +23,20 @@ unsigned int get_amd_rapl(uint64_t *results, void *); void clean_amd_rapl(void *); void label_amd_rapl(char **labels, void *); -struct optparse_long amd_rapl_opt = {"amd_rapl", 'a', OPTPARSE_NONE}; -struct captor amd_rapl = { - .usage_arg = NULL, - .usage_msg = "AMD_RAPL", +Captor amd_rapl = { .init = init_amd_rapl, .get = get_amd_rapl, .clean = clean_amd_rapl, .label = label_amd_rapl, + .nb_opt = 1, +}; + +Optparse amd_rapl_opt[1] = { + { + .longname = "amd-rapl", + .shortname = 'a', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "AMD RAPL", + }, }; diff --git a/src/counters.h b/src/counters.h index 313feeb..a191e5a 100644 --- a/src/counters.h +++ b/src/counters.h @@ -22,17 +22,32 @@ unsigned int init_counters(char *, void **); unsigned int get_counters(uint64_t *results, void *); void clean_counters(void *); void label_counters(char **labels, void *); +void show_all_counters(); -struct optparse_long counters_opt = {"perf-list", 'p', OPTPARSE_REQUIRED}; -struct captor counters = { - .usage_arg = "<perf_list>", - .usage_msg = "performance counters\n" - "\tperf_list is a coma separated list of performance counters.\n" - "\tEx: instructions,cache_misses", +Captor counters = { .init = init_counters, .get = get_counters, .clean = clean_counters, .label = label_counters, + .nb_opt = 2, +}; + +Optparse counters_opt[2] = { + { + .longname = "perf-list", + .shortname = 'p', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<perf_list>", + .usage_msg = "performance counters\n" + "\tperf_list is a coma separated list of performance counters.\n" + "\tEx: instructions,cache_misses", + }, + { + .longname = "list", + .shortname = 'l', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "list the possible performance counters and quit" + }, }; -void show_all_counters(); diff --git a/src/infiniband.h b/src/infiniband.h index 0f1ad11..285b2ba 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -21,12 +21,21 @@ unsigned int init_infiniband(char *infi_path, void **ptr); void label_infiniband(char **labels, void *); -struct optparse_long infiniband_opt = {"monitor-infiniband", 'i', OPTPARSE_REQUIRED}; -struct captor infiniband = { - .usage_arg = "<infiniband_path>", - .usage_msg = "infiniband monitoring (if infiniband_path is X, tries to detect it automatically)", +Captor infiniband = { .init = init_infiniband, .get = NULL, .clean = NULL, .label = label_infiniband, + .nb_opt = 1, }; + +Optparse infiniband_opt[1] = { + { + .longname = "monitor-infiniband", + .shortname = 'i', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<infiniband_path>", + .usage_msg = "infiniband monitoring (if infiniband_path is X, tries to detect it automatically)", + }, +}; + diff --git a/src/load.h b/src/load.h index 366e448..c7c5575 100644 --- a/src/load.h +++ b/src/load.h @@ -23,12 +23,20 @@ unsigned int get_load(uint64_t *results, void *); void clean_load(void *); void label_load(char **labels, void *); -struct optparse_long load_opt = {"sysload", 'u', OPTPARSE_NONE}; -struct captor load = { - .usage_arg = NULL, - .usage_msg = "system load", +Captor load = { .init = init_load, .get = get_load, .clean = clean_load, .label = label_load, + .nb_opt = 1, +}; + +Optparse load_opt[1] = { + { + .longname = "sysload", + .shortname = 'u', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "system load", + }, }; diff --git a/src/mojitos.c b/src/mojitos.c index dc113fc..683bdfa 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -37,44 +37,75 @@ typedef void (*labeler_t)(char **, void *); typedef unsigned int (*getter_t)(uint64_t *, void *); typedef void (*cleaner_t)(void *); -struct captor { - char *usage_arg; - char *usage_msg; +typedef struct Opt Opt; +typedef struct Captor Captor; +/* optparse typedef */ +typedef struct optparse_long Optparse; + +struct Captor { initializer_t init; getter_t get; cleaner_t clean; labeler_t label; + int nb_opt; }; int nb_defined_captors = 0; #include "captors.h" -struct captor captors[NB_CAPTORS]; - -#define NB_OPTS 6 -struct optparse_long longopts[NB_OPTS + NB_CAPTORS + 1] = { - {"overhead-stats", 's', OPTPARSE_NONE}, - {"list", 'l', OPTPARSE_NONE}, - {"freq", 'f', OPTPARSE_REQUIRED}, - {"time", 't', OPTPARSE_REQUIRED}, - {"exec", 'e', OPTPARSE_REQUIRED}, - {"logfile", 'o', OPTPARSE_REQUIRED}, +Captor captors[NB_CAPTOR]; + +#define NB_OPT 5 +Optparse longopts[NB_OPT + NB_CAPTOR_OPT + 1] = { + { + .longname = "freq", .shortname = 'f', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<freq>", + .usage_msg = "specify frequency", + }, + { + .longname = "time", .shortname = 't', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<time>", + .usage_msg = "specify time", + }, + { + .longname = "exec", .shortname = 'e', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<cmd>", + .usage_msg = "specify a command", + }, + { + .longname = "logfile", .shortname = 'o', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<file>", + .usage_msg = "specify a log file", + }, + { + .longname = "overhead-stats", .shortname = 's', .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "enable overhead statistics in nanoseconds", + }, }; +void printopt(Optparse *opt) +{ + printf("-%c", opt->shortname); + printf("|--%s", opt->longname); + if (opt->usage_arg != NULL) { + printf(" %s", opt->usage_arg); + } + printf("\n\t%s\n", opt->usage_msg); +} + void usage(char **argv) { - printf("Usage : %s [OPTIONS] [CAPTOR ...] [-o logfile] [-e cmd ...]\n" - "\nOPTIONS:\n" - "-t <time>\t\tspecify time\n" - "-f <freq>\t\tspecify frequency\n" - "-e <cmd>\t\tspecify a command\n" - "-l\t\tlist the possible performance counters and quit\n" - "-s\t\tenable overhead statistics in nanoseconds\n" - "if time==0 then loops infinitively\n" - "if -e is present, time and freq are not used\n" - , argv[0]); + printf("Usage : %s [OPTIONS] [CAPTOR ...]\n", argv[0]); + + printf("\nOPTIONS:\n"); + for (int i = 0; i < NB_OPT; i++) { + printopt(&longopts[i]); + } + printf("if time==0 then loops infinitively\n" + "if -e is present, time and freq are not used\n"); if (nb_defined_captors == 0) { // no captor to show @@ -82,13 +113,8 @@ void usage(char **argv) } printf("\nCAPTORS:\n"); - - for (int i = 0; i < nb_defined_captors; i++) { - printf("-%c", longopts[NB_OPTS + i].shortname); - if (captors[i].usage_arg != NULL) { - printf(" %s", captors[i].usage_arg); - } - printf("\n\t%s\n", captors[i].usage_msg); + for (int i = 0; i < NB_CAPTOR_OPT; i++) { + printopt(&longopts[NB_OPT + i]); } exit(EXIT_FAILURE); @@ -123,7 +149,7 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void add_source(struct captor *cpt, char *arg) +void add_source(Captor *cpt, char *arg) { nb_sources++; initializer_t init = cpt->init; @@ -160,7 +186,7 @@ int main(int argc, char **argv) char **application = NULL; int stat_mode = -1; - init_captors(longopts, captors, NB_OPTS + NB_CAPTORS, NB_OPTS, &nb_defined_captors); + init_captors(longopts, captors, NB_OPT + NB_CAPTOR_OPT, NB_OPT, &nb_defined_captors); if (argc == 1) { usage(argv); @@ -207,10 +233,15 @@ int main(int argc, char **argv) break; default: { int ismatch = 0; + int opt_idx = NB_OPT; for (int i = 0; i < nb_defined_captors && !ismatch; i++) { - if (opt == longopts[NB_OPTS + i].shortname) { - ismatch = 1; - add_source(&captors[i], options.optarg); + for (int j = 0; j < captors[i].nb_opt; j++) { + if (opt == longopts[opt_idx].shortname) { + ismatch = 1; + add_source(&captors[i], options.optarg); + break; + } + opt_idx++; } } if (!ismatch) { diff --git a/src/network.h b/src/network.h index 3182587..82fcfc3 100644 --- a/src/network.h +++ b/src/network.h @@ -23,13 +23,20 @@ unsigned int get_network(uint64_t *results, void *); void clean_network(void *); void label_network(char **labels, void *); -struct optparse_long network_opt = {"net-dev", 'd', OPTPARSE_REQUIRED}; -struct captor network = { - .usage_arg = "<net_dev>", - .usage_msg = "network monitoring (if network_device is X, tries to detect it automatically)", +Captor network = { .init = init_network, .get = get_network, .clean = clean_network, .label = label_network, + .nb_opt = 1, }; +Optparse network_opt[1] = { + { + .longname = "net-dev", + .shortname = 'd', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<net_dev>", + .usage_msg = "network monitoring (if network_device is X, tries to detect it automatically)", + }, +}; diff --git a/src/optparse.h b/src/optparse.h index 04e60f6..b1908d4 100644 --- a/src/optparse.h +++ b/src/optparse.h @@ -71,6 +71,8 @@ struct optparse_long { const char *longname; int shortname; enum optparse_argtype argtype; + char *usage_arg; + char *usage_msg; }; /** diff --git a/src/rapl.h b/src/rapl.h index b8dc9a2..95f9fd4 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -23,13 +23,21 @@ unsigned int get_rapl(uint64_t *results, void *); void clean_rapl(void *); void label_rapl(char **labels, void *); -struct optparse_long rapl_opt = {"rapl", 'r', OPTPARSE_NONE}; -struct captor rapl = { - .usage_arg = NULL, - .usage_msg = "RAPL", +Captor rapl = { .init = init_rapl, .get = get_rapl, .clean = clean_rapl, .label = label_rapl, + .nb_opt = 1, +}; + +Optparse rapl_opt[1] = { + { + .longname = "rapl", + .shortname = 'r', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "RAPL", + }, }; diff --git a/src/temperature.h b/src/temperature.h index 5e8046e..ec2faef 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -23,12 +23,20 @@ unsigned int get_temperature(uint64_t *results, void *); void clean_temperature(void *); void label_temperature(char **labels, void *); -struct optparse_long temperature_opt = {"cpu-temp", 'c', OPTPARSE_NONE}; -struct captor temperature = { - .usage_arg = NULL, - .usage_msg = "processor temperature", +Captor temperature = { .init = init_temperature, .get = get_temperature, .clean = clean_temperature, .label = label_temperature, + .nb_opt = 1, +}; + +Optparse temperature_opt[1] = { + { + .longname = "cpu-temp", + .shortname = 'c', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "processor temperature" + }, }; -- GitLab From a334278f7599136ad24ef80da7388d2069ce2ae2 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 13:05:29 +0100 Subject: [PATCH 080/125] update documentation (doc/counter_ex.h) --- doc/counter_ex.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/counter_ex.h b/doc/counter_ex.h index 4ab7915..5702adc 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -7,12 +7,20 @@ unsigned int get_acc(uint64_t *results, void *); void clean_acc(void *); void label_acc(char **labels, void *); -struct optparse_long counters_opt = {"accumulator", 'a', OPTPARSE_NONE}; -struct captor counters = { - .usage_arg = NULL, - .usage_msg = "dumb accumulator\n" +Captor rapl = { .init = init_acc, .get = get_acc, .clean = clean_acc, .label = label_acc, + .nb_opt = 1, +}; + +Optparse rapl_opt[1] = { + { + .longname = "accumulator", + .shortname = 'a', + .argtype = OPTPARSE_NONE, /* OPTPARSE_NONE / OPTPARSE_OPTIONAL / OPTPARSE_REQUIRED */ + .usage_arg = NULL, + .usage_msg = "dumb accumulator", + }, }; -- GitLab From bc41b97dce02f936f0bdeff681941b3208b6fb9f Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 12:44:18 +0000 Subject: [PATCH 081/125] fix unit size --- src/amd_rapl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 09ea7c0..31944b1 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -49,7 +49,7 @@ struct cpu_sensor_t { char *name; int fd; - uint64_t energy_units; + unsigned int energy_units; uint64_t core_energy; uint64_t pkg_energy; }; @@ -107,7 +107,7 @@ uint64_t read_msr(int fd, uint64_t msr) return data; } -uint64_t read_unit(int fd) +unsigned int read_unit(int fd) { uint64_t unit = read_msr(fd, msr_rapl_power_unit); return ((unit & amd_energy_unit_mask) >> 8); @@ -127,14 +127,12 @@ uint64_t read_raw_pkg_energy(int fd) // ---------------------------------ENERGY -uint64_t raw_to_microjoule(uint64_t raw, uint64_t unit) +uint64_t raw_to_microjoule(uint64_t raw, unsigned int unit) { static const double to_microjoule = 1000000.0; - double d_raw = (double) raw; - double d_unit = (double) unit; // raw * (1 / (unit^2)) -> Joule // Joule * 1000000 -> uJoule - return ((d_raw * to_microjoule) / (d_unit * d_unit)); + return (uint64_t) (((double) raw * to_microjoule) / (double)(1U << unit)); } uint64_t raw_to_joule(uint64_t raw, uint64_t unit) { @@ -149,7 +147,7 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(cpu_sensor_t *sensor) { //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", + printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %d, core_energy: %ld, pkg_energy: %ld\n", sensor->cpu_id, sensor->package_id, sensor->name, -- GitLab From c71479936bb423c408af3355a920d6691af72173 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 13:03:20 +0000 Subject: [PATCH 082/125] clear code --- src/amd_rapl.c | 52 ------------------------------------------------ tests/amd_rapl.c | 6 +++--- 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 31944b1..0d2ed29 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -165,20 +165,6 @@ void debug_print_amd_rapl(_amd_rapl_t *rapl) } } -// typedef struct { -// size_t cpu_id; -// uint64_t *results; -// size_t capacity; -// } CpuLogger; -// -// CpuLogger init_logger(size_t cpu_id, size_t capacity) -// { -// -// } -// -// void log_value(); - - #endif // ---------------------------AMD_RAPL_UTIL @@ -321,41 +307,3 @@ void clean_amd_rapl(void *ptr) free(rapl->sensors); free(rapl); } - -// -----------------------------ENTRY_POINT - -#ifdef __TESTING_AMD__ -#ifdef DEBUG -int main() -{ - s_round_to_uint64(1.0); - static const unsigned int time = 10; - _amd_rapl_t *rapl = NULL; - unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); - uint64_t results[nb_cpu]; - char *labels[nb_cpu]; - - label_amd_rapl(labels, (void *) rapl); - - for (unsigned int i = 0; i < rapl->nb; ++i) { - printf("%s ", labels[i]); - } - printf("\n"); - - // -- Run - - for (unsigned int i = 0; i < time; ++i) { - sleep(1); - get_amd_rapl(results, (void *)rapl); - - for (unsigned int j = 0; j < rapl->nb; ++j) { - printf("%ld ", results[j]); - } - printf("\n"); - } - - clean_amd_rapl(rapl); - return 0; -} -#endif -#endif diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 3f97f32..ddf76ae 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -11,7 +11,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 100; unit = 1000; - expected = 100; + expected = 390625; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification @@ -21,7 +21,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 200; unit = 1; - expected = 200000000; + expected = 100000000; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification @@ -41,7 +41,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 1000; unit = 3; - expected = 111111111; + expected = 125000000; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification -- GitLab From 6eaf91e0c2641c2fdd58539b11d956e5ab3ee9d8 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 14:46:27 +0000 Subject: [PATCH 083/125] format --- tests/info_reader.c | 67 +++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/tests/info_reader.c b/tests/info_reader.c index 761d86a..9504631 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -84,28 +84,29 @@ TFUNCTION(test_start_with, { TEST_BOOLEAN(&result, &_false); }) -#define DUMB_KEYFINDER(key_finder, key, delimiter) \ - do { \ - key_finder = (KeyFinder) { \ - key, \ - delimiter, \ - 0, \ - 0 \ - }; \ - } while (0); - -#define DUMB_PARSER(parser, keys, nb_keys) \ - do { \ - parser = (Parser) { \ - 0, \ - 0, \ - 0, \ - 0, \ - keys, \ - nb_keys, \ - 0 \ - }; \ - } while (0); +#define NONE 0 +#define DUMMY_KEYFINDER(__key_finder, __key, __delimiter) \ + do { \ + __key_finder = (KeyFinder) { \ + .key = __key, \ + .delimiter = __delimiter, \ + .copy = NONE, \ + .set = NONE \ + }; \ + } while (0); + +#define DUMMY_PARSER(__parser, __keys, __nb_keys) \ + do { \ + __parser = (Parser) { \ + .storage = NONE, \ + .nb_stored = NONE, \ + .capacity = NONE, \ + .storage_struct_size = NONE, \ + .keys = __keys, \ + .nb_keys = __nb_keys, \ + .file = NONE \ + }; \ + } while (0); TFUNCTION(test_match, { @@ -121,8 +122,8 @@ TFUNCTION(test_match, { // Test 1: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_PARSER(parser, keys, 1); strcpy(line, "key: value"); found_key_finder = NULL; raw_value = NULL; @@ -135,8 +136,8 @@ TFUNCTION(test_match, { // Test 2: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1) + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_PARSER(parser, keys, 1) strcpy(line, "not a key: value"); found_key_finder = NULL; raw_value = NULL; @@ -149,8 +150,8 @@ TFUNCTION(test_match, { // Test 3: // -- Setup - DUMB_KEYFINDER(keys[0],"key", ": "); - DUMB_PARSER(parser, keys, 1); + DUMMY_KEYFINDER(keys[0],"key", ": "); + DUMMY_PARSER(parser, keys, 1); strcpy(line, "key:value"); found_key_finder = NULL; raw_value = NULL; @@ -163,9 +164,9 @@ TFUNCTION(test_match, { // Test 4: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_KEYFINDER(keys[1], "second_key", ": "); - DUMB_PARSER(parser, keys, 2); + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_KEYFINDER(keys[1], "second_key", ": "); + DUMMY_PARSER(parser, keys, 2); strcpy(line, "second_key: value"); found_key_finder = NULL; raw_value = NULL; @@ -178,8 +179,8 @@ TFUNCTION(test_match, { // Test 5: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_PARSER(parser, keys, 1); strcpy(line, ""); found_key_finder = NULL; raw_value = NULL; -- GitLab From 847023900aa79ea95fea4b50be39d5e801c46c67 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 17:32:40 +0100 Subject: [PATCH 084/125] Add a generation system for README.md and doc/mojitos.1 - README.md can be updated via `make readme` - doc/mojitos.1 can be generated via `make man` - README.md is updated and doc/mojitos.1 generated on `make all` - correct wrong translation "captor", to "sensor" - update README.md build instructions - mv src/optparse.h and src/info_reader.h to ./lib/ - add the possibility to execute an alternative function when parsing sensor options (other than `add_source()`) --- .gitignore | 5 +- README.md | 75 +++++++++++++------------- configure.sh | 91 ++++++++++++++++--------------- doc/counter_ex.h | 2 +- doc/{mojitos.1 => mojitos.pre.1} | 41 +++----------- {src => lib}/info_reader.h | 0 {src => lib}/optparse.h | 1 + makefile | 18 +++++-- src/amd_rapl.h | 2 +- src/counters.c | 6 ++- src/counters.h | 7 +-- src/infiniband.h | 2 +- src/load.h | 2 +- src/mojitos.c | 93 +++++++++++++++++++++----------- src/network.h | 2 +- src/rapl.h | 2 +- src/temperature.h | 2 +- tools/update-readme-usage.sh | 27 ++++++++++ 18 files changed, 214 insertions(+), 164 deletions(-) rename doc/{mojitos.1 => mojitos.pre.1} (69%) rename {src => lib}/info_reader.h (100%) rename {src => lib}/optparse.h (99%) create mode 100755 tools/update-readme-usage.sh diff --git a/.gitignore b/.gitignore index 095c70a..6f52a2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ +doc/mojitos.1 tests/run src/counters_option.h -src/captors.h -captors.mk +src/sensors.h +sensors.mk bin obj *.swp diff --git a/README.md b/README.md index 6422ce0..10f5aaf 100644 --- a/README.md +++ b/README.md @@ -6,51 +6,52 @@ MojitO/S runs on GNU/Linux ## Usage ```bash -Usage : mojitos [-rsu] [-t time] [-f freq] [-p perf_list] \ - [-d network_device] [-o logfile] [-e command arguments...] - mojitos [-l] - - -s Enable overhead statistics (in nanoseconds). - - -u Enable system-level load monitoring. - - -r Enable RAPL. - - -p perf_list - Enable performance counters. The argument is a coma separated - list of performance counters. - - -d net_device - Enable network monitoring. - - -l List the available performance counters and quit. - - -t time - Set duration value (in seconds). If 0, then loops indefinitely. - - -f freq - Set amount of measurements per second. - - -e cmd ... - Execute a command with optional arguments. If this option is - used, any usage of -t or -f is ignored. +Usage : ./bin/mojitos [OPTIONS] [SENSOR ...] [-e <cmd> ...] + +OPTIONS: +-f|--freq <freq> + set amount of measurements per second. +-t|--time <time> + set duration value (seconds). If 0, then loops infinitely. +-e|--exec <cmd> ... + Execute a command with optional arguments. + If this option is used, any usage of -t or -f is ignored. +-o|--logfile <file> + specify a log file. +-s|--overhead-stats + enable overhead statistics (nanoseconds). + +SENSORS: +-p|--perf-list <perf_list> + performance counters + perf_list is a coma separated list of performance counters. + Ex: instructions,cache_misses +-l|--list + list the available performance counters and quit +-u|--sysload + system load +-d|--net-dev <net_dev> + network monitoring (if network_device is X, tries to detect it automatically) +-r|--rapl + RAPL +-c|--cpu-temp + processor temperature ``` ## Installation Instructions -Dependencies -```bash -sudo apt install libpowercap0 libpowercap-dev powercap-utils python3 -``` Download the source code ```bash git clone https://gitlab.irit.fr/sepia-pub/mojitos.git ``` -Compile the code +The quickest way to compile the code is: ```bash cd mojitos +./configure.sh make ``` +You may want to run `./configure.sh --help` to see configuration options. + To execute mojitos without being root to monitor performance counters ```bash sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' @@ -65,7 +66,7 @@ sudo chmod a+w /sys/class/powercap/intel-rapl/*/*/* RAPL values during 2 seconds with a frequency of 2 Hz ```bash -$ ./mojitos -t 2 -f 2 -r +$ ./bin/mojitos -t 2 -f 2 -r #timestamp package-00 core0 dram0 1036389.135659868 10986 2869 1526 1036389.500183551 1291440 255736 515562 @@ -75,7 +76,7 @@ $ ./mojitos -t 2 -f 2 -r Performance counters (cpu_cycle, cache_ll_r_a and page_faults) during 4 seconds with a frequency of 1Hz. For cache performance counters, _r and _w are respectively read and write, and _a, _m and _p are respectively access, miss, pending. ```bash -$ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults +$ ./bin/mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults #timestamp cpu_cycles cache_ll page_faults 1036846.351749455 571199 1232 0 1036847.001098880 348173344 2451387 872 @@ -85,7 +86,7 @@ $ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults Network values with no time limit with a frequency of 1Hz. rxp and txp are the number of received and sent packets, while rxb and txp are the number of received and sent bytes. ```bash -$ ./mojitos -t 0 -f 1 -d enp0s25 +$ ./bin/mojitos -t 0 -f 1 -d enp0s25 #timestamp rxp rxb txp txb 1036559.277376027 0 0 0 0 1036560.000161101 4 581 2 179 @@ -97,7 +98,7 @@ $ ./mojitos -t 0 -f 1 -d enp0s25 Overhead of the monitoring for RAPL and cpu_cycle ```bash -$ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s +$ ./bin/mojitos -t 5 -f 1 -p cpu_cycles -r -s #timestamp cpu_cycles package-00 core0 dram0 overhead 1036988.197227391 162214 19898 4944 1586 149612 1036989.000151326 332613664 2513116 379577 1115171 739573 diff --git a/configure.sh b/configure.sh index 49e1789..62f297a 100755 --- a/configure.sh +++ b/configure.sh @@ -20,25 +20,25 @@ decho() { } debug=0 -target_hdr=src/captors.h -target_mk=captors.mk +target_hdr=src/sensors.h +target_mk=sensors.mk -noncaptor='counters_option|optparse|captors|util|info_reader' +nonsensor='counters_option|optparse|sensors|util|info_reader' -hdr_blacklist=$noncaptor +hdr_blacklist=$nonsensor hdr_whitelist='' usage() { - printf -- 'Usage: %s [-l] [-e <captor>] [-i <captor>] [-u <captor>]\n' "$(basename "$0")" >&2 - printf -- '-e | --exclude : exclude captor, can be called multiple times\n' >&2 - printf -- '-i | --include : include captor, can be called multiple times\n' >&2 - printf -- '-l | --list-captors : list all captors and exit\n' >&2 - printf -- '-u | --unique : only include the specified captor\n' >&2 + printf -- 'Usage: %s [-l] [-e <sensor>] [-i <sensor>] [-u <sensor>]\n' "$(basename "$0")" >&2 + printf -- '-e | --exclude : exclude sensor, can be called multiple times\n' >&2 + printf -- '-i | --include : include sensor, can be called multiple times\n' >&2 + printf -- '-l | --list-sensors : list all sensors and exit\n' >&2 + printf -- '-u | --unique : only include the specified sensor\n' >&2 printf -- ' if this option is used, any usage of `-e` or `-i` will be ignored\n' >&2 exit 1 } -ls_captors() { +ls_sensors() { try cd src [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' @@ -51,49 +51,52 @@ ls_captors() { sed 's/\.h$//' } -# gen_captors_h(captors, nb_captors) -gen_captors_h() { - captors=$1 - nb_captors=$2 - nb_captor_opts=$( - for captor in $captors; do - sed -n 's/.*'"${captor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${captor}.h" +# gen_sensors_h(sensor, nb_sensors) +gen_sensors_h() { + sensors=$1 + nb_sensors=$2 + nb_sensor_opts=$( + for sensor in $sensors; do + sed -n 's/.*'"${sensor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${sensor}.h" done | paste -s -d '+' | bc ) - dprint captors >&2 - dprint nb_captor_opts >&2 - isnum "$nb_captor_opts" || die "could not get total number of captors's command-line options" + dprint sensors >&2 + dprint nb_sensor_opts >&2 + isnum "$nb_sensor_opts" || die "could not get total number of sensors's command-line options" # gen includes - for captor in $captors; do - printf '#include "%s.h"\n' "$captor" + for sensor in $sensors; do + printf '#include "%s.h"\n' "$sensor" done - printf '\n#define NB_CAPTOR %d\n\n' "$nb_captors" - printf '\n#define NB_CAPTOR_OPT %d\n\n' "$nb_captor_opts" + printf '\n' + + printf '#define NB_SENSOR %d\n' "$nb_sensors" + printf '#define NB_SENSOR_OPT %d\n' "$nb_sensor_opts" + printf '\n' - # gen `init_captors()` - printf 'void init_captors(Optparse *longopts, Captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' + # gen `init_sensors()` + printf 'void init_sensors(Optparse *opts, Sensor *sensors, size_t len, size_t offset, int *nb_defined)\n{\n' printf ' int opt_idx = offset;\n' - for captor in $captors; do + for sensor in $sensors; do cat <<-! - for (int i = 0; i < ${captor}.nb_opt; i++) { - longopts[opt_idx++] = ${captor}_opt[i]; + for (int i = 0; i < ${sensor}.nb_opt; i++) { + opts[opt_idx++] = ${sensor}_opt[i]; } - captors[(*nb_defined)++] = ${captor}; + sensors[(*nb_defined)++] = ${sensor}; ! done printf ' assert((offset + *nb_defined) <= len);\n' printf '}\n' } -gen_captors_mk() { - captors=$1 +gen_sensors_mk() { + sensors=$1 printf 'CAPTOR_OBJ = ' - for captor in $captors; do - printf '$(OBJ_DIR)/%s.o ' "$captor" + for sensor in $sensors; do + printf '$(OBJ_DIR)/%s.o ' "$sensor" done printf '\n' } @@ -140,8 +143,8 @@ while [ "$1" ]; do shift; [ "$1" ] || usage hdr_blacklist="${hdr_blacklist}|${1}" ;; - --list-captors|-l) - ls_captors + --list-sensors|-l) + ls_sensors exit 0 ;; --unique|-u) @@ -155,20 +158,20 @@ while [ "$1" ]; do shift done -captors=$(ls_captors) -nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) +sensors=$(ls_sensors) +nb_sensors=$(echo "$sensors" | sed '/^$/d' | wc -l) -if [ "$nb_captors" -eq 0 ]; then - printf -- '0 captors are selected. cannot build.\n' >&2 +if [ "$nb_sensors" -eq 0 ]; then + printf -- '0 sensors are selected. cannot build.\n' >&2 exit 1 fi -try gen_captors_h "$captors" "$nb_captors" > "$target_hdr" -try gen_captors_mk "$captors" > "$target_mk" +try gen_sensors_h "$sensors" "$nb_sensors" > "$target_hdr" +try gen_sensors_mk "$sensors" > "$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 -printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 -echo "$captors" >&2 +printf -- 'The resulting binary will have the %d following sensors:\n' "$nb_sensors" >&2 +echo "$sensors" >&2 make clean >/dev/null diff --git a/doc/counter_ex.h b/doc/counter_ex.h index 5702adc..65fabf3 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -7,7 +7,7 @@ unsigned int get_acc(uint64_t *results, void *); void clean_acc(void *); void label_acc(char **labels, void *); -Captor rapl = { +Sensor rapl = { .init = init_acc, .get = get_acc, .clean = clean_acc, diff --git a/doc/mojitos.1 b/doc/mojitos.pre.1 similarity index 69% rename from doc/mojitos.1 rename to doc/mojitos.pre.1 index a7927e8..af9cb9b 100644 --- a/doc/mojitos.1 +++ b/doc/mojitos.pre.1 @@ -3,47 +3,18 @@ .Os .Sh NAME .Nm mojitos -.Nd An open source system, energy and network monitoring tool. +.Nd An open source system monitoring tool. .Sh SYNOPSIS .Nm mojitos -.Op Fl rsu -.Op Fl t Ar time -.Op Fl f Ar freq -.Op Fl p Ar perf_list -.Op Fl d Ar net_device -.Op Fl o Ar logfile +.Op Ar OPTIONS +.Op Ar SENSOR ... .Op Fl e Ar cmd ... -.Nm mojitos -.Op Fl l .Sh DESCRIPTION .Nm -enables monitoring the system, its energy comsumption and the network activity, at the OS level. -It runs on GNU/Linux. -.Pp +is a monitoring tool with a multitude of sensors that does measurements at the OS level. .Nm -supports the following options: -.Bl -tag -width Ds -.It Fl s -Enable overhead statistics (in nanoseconds). -.It Fl u -Enable system-level load monitoring. -.It Fl r -Enable RAPL. -.It Fl p Ar perf_list -Enable performance counters. -The argument is a coma separated list of performance counters. -.It Fl d Ar net_device -Enable network monitoring. -.It Fl l -List the available performance counters and quit. -.It Fl t Ar time -Set duration value (in seconds). If 0, then loops indefinitely. -.It Fl f Ar freq -Set amount of measurements per second. -.It Fl e Ar cmd ... -Execute a command with optional arguments. -If this option is used, any usage of -t or -f is ignored. -.El +runs on GNU/Linux. +USAGE .Sh EXIT STATUS .Ex .Sh EXAMPLES diff --git a/src/info_reader.h b/lib/info_reader.h similarity index 100% rename from src/info_reader.h rename to lib/info_reader.h diff --git a/src/optparse.h b/lib/optparse.h similarity index 99% rename from src/optparse.h rename to lib/optparse.h index b1908d4..1925d73 100644 --- a/src/optparse.h +++ b/lib/optparse.h @@ -73,6 +73,7 @@ struct optparse_long { enum optparse_argtype argtype; char *usage_arg; char *usage_msg; + void *(*fn)(void *, size_t); }; /** diff --git a/makefile b/makefile index 3f8a70b..d5d2d23 100644 --- a/makefile +++ b/makefile @@ -10,21 +10,21 @@ BIN = mojitos CAPTOR_OBJ = -include ./captors.mk +include ./sensors.mk OBJ = \ $(CAPTOR_OBJ) \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib CFLAGS = $(CPPFLAGS) -O3 -Werror LDFLAGS = ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -all: $(BIN) +all: $(BIN) readme man $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o @@ -48,7 +48,7 @@ $(BIN_DIR): mkdir -p $(BIN_DIR) debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og -debug: all +debug: $(BIN) tests: gcc $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run @@ -64,4 +64,12 @@ clean: \rm -f $(SRC_DIR)/counters_option.h \rm -f $(TESTS_DIR)/run -.PHONY: all clean mojitos debug format tests +readme: $(BIN) + sh ./tools/update-readme-usage.sh + +man: $(BIN) + awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ + '/^USAGE/ { $$0=usage } 1' \ + doc/mojitos.pre.1 > doc/mojitos.1 2>/dev/null + +.PHONY: all clean mojitos debug format tests readme man diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 90f6161..fef1109 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -23,7 +23,7 @@ unsigned int get_amd_rapl(uint64_t *results, void *); void clean_amd_rapl(void *); void label_amd_rapl(char **labels, void *); -Captor amd_rapl = { +Sensor amd_rapl = { .init = init_amd_rapl, .get = get_amd_rapl, .clean = clean_amd_rapl, diff --git a/src/counters.c b/src/counters.c index 874e6fc..d42ceae 100644 --- a/src/counters.c +++ b/src/counters.c @@ -44,11 +44,15 @@ typedef struct _counter_t *counter_t; #include "counters_option.h" -void show_all_counters() +void *show_all_counters(void *none1, size_t none2) { for (unsigned int i = 0; i < nb_counter_option; i++) { printf("%s\n", perf_static_info[i].name); } + UNUSED(none1); + UNUSED(none2); + exit(EXIT_SUCCESS); + return NULL; /* not reached */ } void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) diff --git a/src/counters.h b/src/counters.h index a191e5a..0304a07 100644 --- a/src/counters.h +++ b/src/counters.h @@ -22,9 +22,9 @@ unsigned int init_counters(char *, void **); unsigned int get_counters(uint64_t *results, void *); void clean_counters(void *); void label_counters(char **labels, void *); -void show_all_counters(); +void *show_all_counters(void *, size_t); -Captor counters = { +Sensor counters = { .init = init_counters, .get = get_counters, .clean = clean_counters, @@ -47,7 +47,8 @@ Optparse counters_opt[2] = { .shortname = 'l', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "list the possible performance counters and quit" + .usage_msg = "list the available performance counters and quit", + .fn = show_all_counters, }, }; diff --git a/src/infiniband.h b/src/infiniband.h index 285b2ba..fac05f8 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -21,7 +21,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr); void label_infiniband(char **labels, void *); -Captor infiniband = { +Sensor infiniband = { .init = init_infiniband, .get = NULL, .clean = NULL, diff --git a/src/load.h b/src/load.h index c7c5575..038b263 100644 --- a/src/load.h +++ b/src/load.h @@ -23,7 +23,7 @@ unsigned int get_load(uint64_t *results, void *); void clean_load(void *); void label_load(char **labels, void *); -Captor load = { +Sensor load = { .init = init_load, .get = get_load, .clean = clean_load, diff --git a/src/mojitos.c b/src/mojitos.c index 683bdfa..3ecf111 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -38,11 +38,11 @@ typedef unsigned int (*getter_t)(uint64_t *, void *); typedef void (*cleaner_t)(void *); typedef struct Opt Opt; -typedef struct Captor Captor; +typedef struct Sensor Sensor; /* optparse typedef */ typedef struct optparse_long Optparse; -struct Captor { +struct Sensor { initializer_t init; getter_t get; cleaner_t clean; @@ -50,41 +50,70 @@ struct Captor { int nb_opt; }; -int nb_defined_captors = 0; +int nb_defined_sensors = 0; -#include "captors.h" +#include "sensors.h" -Captor captors[NB_CAPTOR]; +Sensor sensors[NB_SENSOR]; #define NB_OPT 5 -Optparse longopts[NB_OPT + NB_CAPTOR_OPT + 1] = { +Optparse opts[NB_OPT + NB_SENSOR_OPT + 1] = { { .longname = "freq", .shortname = 'f', .argtype = OPTPARSE_REQUIRED, .usage_arg = "<freq>", - .usage_msg = "specify frequency", + .usage_msg = "set amount of measurements per second.", }, { .longname = "time", .shortname = 't', .argtype = OPTPARSE_REQUIRED, .usage_arg = "<time>", - .usage_msg = "specify time", + .usage_msg = "set duration value (seconds). If 0, then loops infinitely.", }, { .longname = "exec", .shortname = 'e', .argtype = OPTPARSE_REQUIRED, - .usage_arg = "<cmd>", - .usage_msg = "specify a command", + .usage_arg = "<cmd> ...", + .usage_msg = "Execute a command with optional arguments.\n" + "\tIf this option is used, any usage of -t or -f is ignored.", }, { .longname = "logfile", .shortname = 'o', .argtype = OPTPARSE_REQUIRED, .usage_arg = "<file>", - .usage_msg = "specify a log file", + .usage_msg = "specify a log file.", }, { .longname = "overhead-stats", .shortname = 's', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "enable overhead statistics in nanoseconds", + .usage_msg = "enable overhead statistics (nanoseconds).", }, }; +void dumpopt(Optparse *opt) +{ + printf(".It Fl %c | Fl \\-%s", opt->shortname, opt->longname); + if (opt->usage_arg != NULL) { + printf(" Ar %s", opt->usage_arg); + } + printf("\n"); + printf("%s\n", opt->usage_msg); +} + +void dumpopts(Optparse *opts, size_t nb_opt, size_t nb_sensor_opt) +{ + size_t i; + + /* options */ + printf(".Pp\nOPTIONS:\n.Bl -tag -width Ds\n"); + for (i = 0; i < nb_opt; i++) { + dumpopt(&opts[i]); + } + printf(".El\n"); + + /* sensors */ + printf(".Pp\nSENSORS:\n.Bl -tag -width Ds\n"); + for (i++; i < nb_opt + nb_sensor_opt; i++) { + dumpopt(&opts[i]); + } + printf(".El\n"); +} void printopt(Optparse *opt) { @@ -98,23 +127,21 @@ void printopt(Optparse *opt) void usage(char **argv) { - printf("Usage : %s [OPTIONS] [CAPTOR ...]\n", argv[0]); + printf("Usage : %s [OPTIONS] [SENSOR ...] [-e <cmd> ...]\n", argv[0]); printf("\nOPTIONS:\n"); for (int i = 0; i < NB_OPT; i++) { - printopt(&longopts[i]); + printopt(&opts[i]); } - printf("if time==0 then loops infinitively\n" - "if -e is present, time and freq are not used\n"); - if (nb_defined_captors == 0) { + if (nb_defined_sensors == 0) { // no captor to show exit(EXIT_FAILURE); } - printf("\nCAPTORS:\n"); - for (int i = 0; i < NB_CAPTOR_OPT; i++) { - printopt(&longopts[NB_OPT + i]); + printf("\nSENSORS:\n"); + for (int i = 0; i < NB_SENSOR_OPT; i++) { + printopt(&opts[NB_OPT + i]); } exit(EXIT_FAILURE); @@ -149,7 +176,7 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void add_source(Captor *cpt, char *arg) +void add_source(Sensor *cpt, char *arg) { nb_sources++; initializer_t init = cpt->init; @@ -186,12 +213,17 @@ int main(int argc, char **argv) char **application = NULL; int stat_mode = -1; - init_captors(longopts, captors, NB_OPT + NB_CAPTOR_OPT, NB_OPT, &nb_defined_captors); + init_sensors(opts, sensors, NB_OPT + NB_SENSOR_OPT, NB_OPT, &nb_defined_sensors); if (argc == 1) { usage(argv); } + if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '1' && argv[1][2] == '\0') { + dumpopts(opts, NB_OPT, NB_SENSOR_OPT); + exit(EXIT_SUCCESS); + } + output = stdout; atexit(flushexit); @@ -202,7 +234,7 @@ int main(int argc, char **argv) options.permute = 0; optparse_init(&options, argv); - while ((opt = optparse_long(&options, longopts, NULL)) != -1 && application == NULL) { + while ((opt = optparse_long(&options, opts, NULL)) != -1 && application == NULL) { switch (opt) { case 'f': frequency = atoi(options.optarg); @@ -218,9 +250,6 @@ int main(int argc, char **argv) case 's': stat_mode = 0; break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); case 'o': if ((output = fopen(options.optarg, "wb")) == NULL) { perror("fopen"); @@ -234,11 +263,15 @@ int main(int argc, char **argv) default: { int ismatch = 0; int opt_idx = NB_OPT; - for (int i = 0; i < nb_defined_captors && !ismatch; i++) { - for (int j = 0; j < captors[i].nb_opt; j++) { - if (opt == longopts[opt_idx].shortname) { + for (int i = 0; i < nb_defined_sensors && !ismatch; i++) { + for (int j = 0; j < sensors[i].nb_opt; j++) { + if (opt == opts[opt_idx].shortname) { ismatch = 1; - add_source(&captors[i], options.optarg); + if (opts[opt_idx].fn != NULL) { + (void) opts[opt_idx].fn(NULL, 0); + } else { + add_source(&sensors[i], options.optarg); + } break; } opt_idx++; diff --git a/src/network.h b/src/network.h index 82fcfc3..994651a 100644 --- a/src/network.h +++ b/src/network.h @@ -23,7 +23,7 @@ unsigned int get_network(uint64_t *results, void *); void clean_network(void *); void label_network(char **labels, void *); -Captor network = { +Sensor network = { .init = init_network, .get = get_network, .clean = clean_network, diff --git a/src/rapl.h b/src/rapl.h index 95f9fd4..a02624d 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -23,7 +23,7 @@ unsigned int get_rapl(uint64_t *results, void *); void clean_rapl(void *); void label_rapl(char **labels, void *); -Captor rapl = { +Sensor rapl = { .init = init_rapl, .get = get_rapl, .clean = clean_rapl, diff --git a/src/temperature.h b/src/temperature.h index ec2faef..8609dba 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -23,7 +23,7 @@ unsigned int get_temperature(uint64_t *results, void *); void clean_temperature(void *); void label_temperature(char **labels, void *); -Captor temperature = { +Sensor temperature = { .init = init_temperature, .get = get_temperature, .clean = clean_temperature, diff --git a/tools/update-readme-usage.sh b/tools/update-readme-usage.sh new file mode 100755 index 0000000..b9f16de --- /dev/null +++ b/tools/update-readme-usage.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +die() { yell "$*"; exit 111; } +try() { "$@" || die "cannot $*"; } +yell() { echo "$0: $*" >&2; } +echo() { printf '%s\n' "$*"; } + +usage=$(./bin/mojitos) +[ -n "$usage" ] || die 'empty usage. try to recompile mojitos.' + +try awk -v "usage=$usage" ' + /^Usage/ { + print usage + del = 1 + } + { + if (del == 1) { + if (match($0, "^```")) { + del = 0 + print $0 + } + } else { + print $0 + } + } +' README.md > README.tmp +try mv README.tmp README.md -- GitLab From 3bb19b02e319a33b6c219c62b5a400553c3a0aa4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 4 Feb 2023 15:18:03 +0000 Subject: [PATCH 085/125] modification of test api --- tests/amd_rapl.c | 81 +++++++++++++++++++------------ tests/main.c | 2 +- tests/small_test.h | 115 ++++++++++++++++++++++++--------------------- 3 files changed, 115 insertions(+), 83 deletions(-) diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index ddf76ae..262c1f8 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -85,25 +85,25 @@ TFUNCTION(test_get_name, { }) #define NONE 0 -#define DUMB_SENSOR(sensor, cpu_id, name) \ - do { \ - sensor = (cpu_sensor_t) { \ - cpu_id, \ - NONE, \ - name, \ - NONE, \ - NONE, \ - NONE, \ - NONE \ - }; \ +#define DUMMY_SENSOR(__sensor, __cpu_id, __name) \ +do { \ + __sensor = (cpu_sensor_t) { \ + .cpu_id = __cpu_id, \ + .package_id = NONE, \ + .core_id = NONE, \ + .name = __name, \ + .fd = NONE, \ + .energy_units = NONE, \ + .core_energy = NONE, \ + }; \ } while(0); -#define DUMB_RAPL(rapl, sensors, nb) \ - do { \ - rapl = (_amd_rapl_t) { \ - sensors, \ - nb \ - }; \ +#define DUMMY_RAPL(__rapl, __sensors, __sensors_count) \ + do { \ + __rapl = (_amd_rapl_t) { \ + .sensors = __sensors, \ + .sensor_count = __sensors_count \ + }; \ } while(0); TFUNCTION(test_label_amd_rapl, { @@ -116,8 +116,8 @@ TFUNCTION(test_label_amd_rapl, { // Test 1: // -- Setup nb = 1; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_RAPL(rapl, sensors, nb); + DUMMY_SENSOR(sensors[0], 0, "core0"); + DUMMY_RAPL(rapl, sensors, nb); strcpy(expecteds[0], "core0"); // -- Run label_amd_rapl(results, (void *) &rapl); @@ -127,11 +127,11 @@ TFUNCTION(test_label_amd_rapl, { // Test 2: // -- Setup nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 1, "core1"); - DUMB_SENSOR(sensors[2], 2, "core2"); - DUMB_SENSOR(sensors[3], 3, "core3"); - DUMB_RAPL(rapl, sensors, nb); + DUMMY_SENSOR(sensors[0], 0, "core0"); + DUMMY_SENSOR(sensors[1], 1, "core1"); + DUMMY_SENSOR(sensors[2], 2, "core2"); + DUMMY_SENSOR(sensors[3], 3, "core3"); + DUMMY_RAPL(rapl, sensors, nb); strcpy(expecteds[0], "core0"); strcpy(expecteds[1], "core1"); strcpy(expecteds[2], "core2"); @@ -144,11 +144,11 @@ TFUNCTION(test_label_amd_rapl, { // Test 3: // -- Setup nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 3, "core3"); - DUMB_SENSOR(sensors[2], 1, "core1"); - DUMB_SENSOR(sensors[3], 2, "core2"); - DUMB_RAPL(rapl, sensors, nb); + DUMMY_SENSOR(sensors[0], 0, "core0"); + DUMMY_SENSOR(sensors[1], 3, "core3"); + DUMMY_SENSOR(sensors[2], 1, "core1"); + DUMMY_SENSOR(sensors[3], 2, "core2"); + DUMMY_RAPL(rapl, sensors, nb); strcpy(expecteds[0], "core0"); strcpy(expecteds[1], "core3"); strcpy(expecteds[2], "core1"); @@ -159,10 +159,33 @@ TFUNCTION(test_label_amd_rapl, { TEST_T_ARRAY(TEST_STR, nb, results, expecteds); }) +TFUNCTION(test_init_cpu_sensor, { + static const unsigned int max_cpus = 10; + unsigned char cpus_map[max_cpus * max_cpus]; + cpu_sensor_t sensor_t1; + unsigned int result; + unsigned int expected; + + // Test 1: + // -- Setup + memset(cpus_map, 0, max_cpus *max_cpus * sizeof(unsigned char)); + result = 0; + expected = 1; + memset(&sensor_t1, 0, sizeof(cpu_sensor_t)); + sensor_t1.cpu_id = 1; + sensor_t1.core_id = 0; + sensor_t1.package_id = 0; + // -- Run + result = init_cpu_sensor(&sensor_t1, 0, cpus_map, max_cpus); + // -- Verification + TEST_UINT64_T(&result, &expected); +}) + TFILE_ENTRY_POINT(test_amd_rapl, { CALL_TFUNCTION(test_raw_to_microjoule); CALL_TFUNCTION(test_get_name); CALL_TFUNCTION(test_label_amd_rapl); + // CALL_TFUNCTION(test_init_cpu_sensor); }) #ifdef __TESTING__AMD__ diff --git a/tests/main.c b/tests/main.c index a3a43cb..e48b56a 100644 --- a/tests/main.c +++ b/tests/main.c @@ -2,7 +2,7 @@ #include "amd_rapl.c" #include "info_reader.c" -TFILE_ENTRY_POINT(main, { +TMAIN({ CALL_TFUNCTION(test_util); CALL_TFUNCTION(test_amd_rapl); CALL_TFUNCTION(test_info_reader); diff --git a/tests/small_test.h b/tests/small_test.h index 0e39868..357479a 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -9,10 +9,23 @@ // ---------------------------API_INTERFACE + + +#define TMAIN(code) \ + int main() \ +{ \ + unsigned int __indentation_level = 0; \ + INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ + unsigned int __error_counter__ = 0; \ + do code while (0); \ + DEFERRED_FILE_ERROR(__error_counter__); \ + return __error_counter__; \ +} + /** * @brief Define the entry point of a test file. * This macro is used to define the entry point of a test file. - * It defines a function with the specified file_name that contains the test code specified in code. + * It defines a function with the specified __filename that contains the test code specified in code. * * When the function is called, it initializes the test file using the INIT_TEST_FILE macro, * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, @@ -20,17 +33,17 @@ * The function returns the value of __error_counter__, * which indicates the number of errors encountered during the tests. * - * @param file_name The name of the function that serves as the entry point for the test file. - * @param code The test code to be executed in the function. + * @param __filename The name of the function that serves as the entry point for the test file. + * @param __code The test code to be executed in the function. */ -#define TFILE_ENTRY_POINT(file_name, code) \ - int file_name() \ -{ \ - INIT_TEST_FILE();\ - int __error_counter__ = 0;\ - do code while(0);\ - DEFERRED_FILE_ERROR(__error_counter__); \ - return __error_counter__;\ +#define TFILE_ENTRY_POINT(__filename, __code) \ + int __filename (unsigned int __indentation_level) \ +{ \ + INIT_TEST_FILE(); \ + int __error_counter__ = 0; \ + do __code while(0); \ + DEFERRED_FILE_ERROR(__error_counter__); \ + return __error_counter__; \ } /** @@ -43,15 +56,15 @@ * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. * The function returns the value of __error_counter__, which indicates the number of errors encountered during the tests. * - * @param function_name The name of the test function. - * @param code The test code to be executed in the function. + * @param __function_name The name of the test function. + * @param __code The test code to be executed in the function. */ -#define TFUNCTION(function_name, code) \ - int function_name() \ +#define TFUNCTION(__function_name, __code) \ + int __function_name(unsigned int __indentation_level) \ { \ INIT_TEST_FUNCTION(); \ int __error_counter__ = 0; \ - do code while(0); \ + do __code while(0); \ DEFERRED_FUNCTION_ERROR(__error_counter__); \ return __error_counter__; \ } @@ -65,7 +78,7 @@ * @param function_name The name of the test function to be called. */ #define CALL_TFUNCTION(function_name) \ - __error_counter__ += function_name() + __error_counter__ += function_name(__indentation_level + 1) /** @@ -82,7 +95,7 @@ * @endcode */ #define TEST_STR(result, expected) \ - __error_counter__ += test_str(__FILE__, __LINE__, result, expected) + __error_counter__ += test_str(__FILE__, __LINE__, __indentation_level, result, expected) /** * @def TEST_BOOLEAN(result, expected) @@ -98,7 +111,7 @@ * @endcode */ #define TEST_BOOLEAN(result, expected) \ - __error_counter__ += test_boolean(__FILE__, __LINE__, result, expected) + __error_counter__ += test_boolean(__FILE__, __LINE__, __indentation_level, result, expected) /** * @def TEST_PTR(result, expected) @@ -116,7 +129,7 @@ * @endcode */ #define TEST_PTR(result, expected) \ - __error_counter__ += test_ptr(__FILE__, __LINE__, result, expected) + __error_counter__ += test_ptr(__FILE__, __LINE__, __indentation_level, result, expected) /** @@ -133,7 +146,7 @@ * @endcode */ #define TEST_UINT64_T(result, expected) \ - __error_counter__ += test_uint64_t(__FILE__, __LINE__, result, expected) + __error_counter__ += test_uint64_t(__FILE__, __LINE__, __indentation_level, result, expected) /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) @@ -161,6 +174,15 @@ // --------------------------------API_CODE + +#define INDENTED_PRINT(__fmt, ...) \ + do { \ + for(unsigned int i = 0; i < __indentation_level; i++) { \ + printf("| "); \ + } \ + printf(__fmt, ##__VA_ARGS__); \ + } while(0) + /** * @def INIT_TEST_FILE() * @brief Initialize the test file @@ -173,8 +195,8 @@ * INIT_TEST_FILE(); * @endcode */ -#define INIT_TEST_FILE() \ - init_test_file(__FILE__, __func__) +#define INIT_TEST_FILE() \ + INDENTED_PRINT("%s:%s\n", __FILE__, __func__) /** * @def INIT_TEST_FUNCTION() @@ -188,13 +210,14 @@ * @endcode */ #define INIT_TEST_FUNCTION() \ - init_test_function(__func__) + INDENTED_PRINT("%s()\n", __func__); #define DEFERRED_FILE_ERROR(nb_error) \ - printf("========== Deferred Error : %d\n", nb_error); + INDENTED_PRINT("|_Deferred Error : %u\n",nb_error); +//INDENTED_PRINT("Deferred Error in %s: %d\n",__FILE__, nb_error); #define DEFERRED_FUNCTION_ERROR(nb_error) \ - printf(" | Deferred Error : %d\n", nb_error); + INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); #define FMT_NULL(string) \ string = string ? string : "NULL" @@ -252,65 +275,51 @@ char *uint64_t_format(char *buffer, uint64_t *value) return buffer; } -void init_test_file(const char *file, const char *function) -{ - printf("========== TEST in %s -> %s()\n", file, function); -} - -void init_test_function(const char *function) -{ - printf("|=> %s()\n", function); -} - -int test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) +int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, Comparator *compare, Formatter *format) { + __indentation_level++; static char buffer_result[1000]; static char buffer_expected[1000]; int is_equal = compare(result, expected); - char c_result = is_equal ? 'V' : 'X'; - printf("[%c] | %s:%d: ", c_result, file, line); + char *fmt_result = format(buffer_result, expected); + char *fmt_expected = format(buffer_expected, result); if (!is_equal) { - printf("failed, expected %s, got %s\n", - format(buffer_result, expected), - format(buffer_expected, result) - ); - } else { - printf("passed\n"); + INDENTED_PRINT("%s:%d: failed, expected %s, got %s\n", file, line, fmt_expected, fmt_result); } return !is_equal; } -int test_str(char *file, int line, char *result, char *expected) +int test_str(char *file, int line,unsigned int __indentation_level, char *result, char *expected) { Comparator *compare = (Comparator *) string_compare; Formatter *format = (Formatter *) string_format; - return test(file, line, result, expected, compare, format); + return test(file, line, __indentation_level, result, expected, compare, format); } -int test_boolean(char *file, int line, bool *result, bool *expected) +int test_boolean(char *file, int line, unsigned int __indentation_level, bool *result, bool *expected) { Comparator *compare = (Comparator *) boolean_compare; Formatter *format = (Formatter *) boolean_format; - return test(file, line, (int *) result, (void *) expected, compare, format); + return test(file, line, __indentation_level, (int *) result, (void *) expected, compare, format); } -int test_ptr(char *file, int line, void *result, void *expected) +int test_ptr(char *file, int line, unsigned int __indentation_level, void *result, void *expected) { Comparator *compare = (Comparator *) ptr_compare; Formatter *format = (Formatter *) ptr_format; - return test(file, line, result, expected, compare, format); + return test(file, line, __indentation_level, result, expected, compare, format); } -int test_uint64_t(char *file, int line, void *result, void *expected) +int test_uint64_t(char *file, int line, unsigned int __indentation_level, void *result, void *expected) { Comparator *compare = (Comparator *) uint64_t_compare; Formatter *format = (Formatter *) uint64_t_format; - return test(file, line, (uint64_t *)result, (uint64_t *)expected, compare, format); + return test(file, line, __indentation_level, (uint64_t *)result, (uint64_t *)expected, compare, format); } #endif -- GitLab From 823f32036b8e94e1543336d6a4045ac4d493f5ca Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 4 Feb 2023 15:18:26 +0000 Subject: [PATCH 086/125] format --- src/amd_rapl.c | 136 +++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 0d2ed29..2f20ea2 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -25,8 +25,6 @@ #include <string.h> #include <errno.h> #include <stdlib.h> -#include <assert.h> -#include <math.h> #include "info_reader.h" #include "util.h" @@ -38,59 +36,66 @@ static const uint64_t amd_energy_mask = 0xFFFFFFFF; static const uint64_t amd_energy_unit_mask = 0x01F00; static const uint64_t msr_rapl_power_unit = 0xC0010299; static const uint64_t energy_core_msr = 0xC001029A; -static const uint64_t energy_pkg_msr = 0xC001029B; // ------------------------------FILE_PATHS static const char *base_str = "/dev/cpu/%d/msr"; struct cpu_sensor_t { - size_t cpu_id; - size_t package_id; - char *name; + unsigned int cpu_id; + unsigned int package_id; + unsigned int core_id; + char *name; int fd; + unsigned int energy_units; uint64_t core_energy; - uint64_t pkg_energy; }; typedef struct cpu_sensor_t cpu_sensor_t; struct _amd_rapl_t { cpu_sensor_t *sensors; - unsigned int nb; + unsigned int sensor_count; }; typedef struct _amd_rapl_t _amd_rapl_t; // -----------------------------INFO_READER #ifdef __READ_CPUINFO__ - #warning "Must be modified before release" #define MAX_CPUS 64 -#define NB_KEYS 2 +#define NB_KEYS 3 static const char *cpuinfo = "/proc/cpuinfo"; -static GenericPointer _size_t_allocator(char *s) + +static GenericPointer uint_allocator(char *s) { - size_t value = atoi(s); + unsigned int value = atoi(s); return (GenericPointer) value; } static void _set_cpu_id(GenericPointer storage, GenericPointer data) { cpu_sensor_t *cpu = (cpu_sensor_t *) storage; - cpu->cpu_id = (size_t) data; + cpu->cpu_id = (unsigned int) data; } static void _set_package_id(GenericPointer storage, GenericPointer data) { cpu_sensor_t *cpu = (cpu_sensor_t *) storage; - cpu->package_id = (size_t) data; + cpu->package_id = (unsigned int) data; +} + +static void _set_core_id(GenericPointer storage, GenericPointer data) +{ + cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + cpu->core_id = (unsigned int) data; } static KeyFinder keys[NB_KEYS] = { - {"processor", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_cpu_id}, - {"physical id", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_package_id} + {"processor", ": ", uint_allocator, _set_cpu_id}, + {"physical id", ": ", uint_allocator, _set_package_id}, + {"core id", ": ", uint_allocator, _set_core_id} }; #endif @@ -119,13 +124,20 @@ uint64_t read_raw_core_energy(int fd) return energy & amd_energy_mask; } +// -------------------------READ_PKG_ENERGY + +#ifdef __READ_PKG_ENERGY__ +// TODO: Verify if these functions are still useful (the package energy can be calculed) + +static const uint64_t energy_pkg_msr = 0xC001029B; uint64_t read_raw_pkg_energy(int fd) { uint64_t energy = read_msr(fd, energy_pkg_msr); return energy & amd_energy_mask; } +#endif -// ---------------------------------ENERGY +// ----------------------------------ENERGY uint64_t raw_to_microjoule(uint64_t raw, unsigned int unit) { @@ -147,20 +159,19 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(cpu_sensor_t *sensor) { //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %d, core_energy: %ld, pkg_energy: %ld\n", + printf("cpu_id : %d, package_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", sensor->cpu_id, sensor->package_id, sensor->name, sensor->fd, sensor->energy_units, sensor->core_energy, - sensor->pkg_energy ); } void debug_print_amd_rapl(_amd_rapl_t *rapl) { - for (unsigned int i = 0; i < rapl->nb; i++) { + for (unsigned int i = 0; i < rapl->sensor_count; i++) { debug_print_sensor(&rapl->sensors[i]); } } @@ -186,57 +197,46 @@ unsigned int get_nb_cpu() return n_cpu; } -char *get_name(size_t cpu_id) +char *get_name(unsigned int cpu_id) { - static const char *base_name = "core%ld"; + static const char *base_name = "core%d"; static const size_t max_lenght = 20; char *name = (char *)calloc(max_lenght, sizeof(char)); snprintf(name, max_lenght, base_name, cpu_id); return name; } -void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) +void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) { + sensor->energy_units = read_unit(sensor->fd); + uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); + uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); + + *energy_consumed = modulo_substraction(core_energy, sensor->core_energy); + sensor->core_energy = core_energy; +} + +unsigned int init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id, unsigned char *cpus_map, unsigned int max_cpus) +{ + if (cpus_map[sensor->core_id * max_cpus + sensor->package_id] > 0) { + return 0; + } + cpus_map[sensor->core_id * max_cpus + sensor->package_id] += 1; + static char filename[BUFFER_SIZE]; sprintf(filename, base_str, cpu_id); int fd = open(filename, O_RDONLY); if (fd < 0) { - fprintf(stderr, "open("); fprintf(stderr, base_str, cpu_id); - perror(")"); + perror(":open()"); exit(127); } - uint64_t raw_core_energy = read_raw_core_energy(fd); - uint64_t raw_pkg_energy = read_raw_pkg_energy(fd); - sensor->cpu_id = cpu_id; sensor->name = get_name(cpu_id); sensor->fd = fd; - sensor->energy_units = read_unit(fd); - sensor->core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - sensor->pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); -} - -uint64_t get_core_energy(cpu_sensor_t *sensor) -{ - uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); - uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - - uint64_t energy_consumed = modulo_substraction(core_energy, sensor->core_energy); - sensor->core_energy = core_energy; - return energy_consumed; -} - -uint64_t get_pkg_energy(cpu_sensor_t *sensor) -{ - uint64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); - uint64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); - - uint64_t energy_consumed = modulo_substraction(pkg_energy, sensor->pkg_energy); - sensor->pkg_energy = pkg_energy; - return energy_consumed; + return 1; } void clean_cpu_sensor(cpu_sensor_t *sensor) @@ -258,41 +258,42 @@ unsigned int init_amd_rapl(char *none, void **ptr) UNUSED(none); _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); - unsigned int nb_cpu = get_nb_cpu(); - if (nb_cpu == 0) { - fprintf(stderr, "open("); - fprintf(stderr, base_str,0); - perror(")"); + unsigned int max_cpus = get_nb_cpu(); + if (max_cpus == 0) { + fprintf(stderr, base_str, 0); + perror(":open()"); exit(127); } - cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(nb_cpu, sizeof(cpu_sensor_t)); - - rapl->nb = nb_cpu; + unsigned char *cpus_map = calloc(max_cpus * max_cpus, sizeof(unsigned char)); + cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); rapl->sensors = cpus; - for (unsigned int i = 0; i < nb_cpu; i++) { - init_cpu_sensor(&rapl->sensors[i], i); + unsigned int nb_cpu = 0; + for (unsigned int i = 0; i < max_cpus; i++) { + nb_cpu += init_cpu_sensor(&rapl->sensors[nb_cpu], i, cpus_map, max_cpus); } + rapl->sensor_count = nb_cpu; *ptr = (void *) rapl; - return rapl->nb; + free(cpus_map); + return rapl->sensor_count; } unsigned int get_amd_rapl(uint64_t *results, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; i++) { - results[i] = get_core_energy(&rapl->sensors[i]); + for (unsigned int i = 0; i < rapl->sensor_count; i++) { + update_cpu_sensor(&rapl->sensors[i], &results[i]); } - return rapl->nb; + return rapl->sensor_count; } void label_amd_rapl(char **labels, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; i++) { + for (unsigned int i = 0; i < rapl->sensor_count; i++) { labels[i] = rapl->sensors[i].name; } } @@ -301,9 +302,10 @@ void clean_amd_rapl(void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; ++i) { + for (unsigned int i = 0; i < rapl->sensor_count; ++i) { clean_cpu_sensor(&rapl->sensors[i]); } free(rapl->sensors); free(rapl); } + -- GitLab From 213b5d9bd64122321164ec70d75b328cdce9dd77 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:28:32 +0000 Subject: [PATCH 087/125] format --- tests/info_reader.c | 157 ++++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 51 deletions(-) diff --git a/tests/info_reader.c b/tests/info_reader.c index 9504631..32734c9 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -1,54 +1,117 @@ #include "small_test.h" TFUNCTION(test_replace_first, { - char test1[] = "This is my string"; - replace_first(test1, 'i', 'I'); - TEST_STR(test1, "ThIs is my string"); + // useful variables : + char result[100]; + char expected[100]; - char test2[] = "This is my string"; - replace_first(test2, 'x', 'X'); - TEST_STR(test2, "This is my string"); + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "ThIs is my string"); + // -- Run + replace_first(result, 'i', 'I'); + // -- Verification + TEST_STR(result, expected); + + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This is my string"); + // -- Run + replace_first(result, 'x', 'X'); + // -- Verification + TEST_STR(result, expected); + + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This_is my string"); + // -- Run + replace_first(result, ' ', '_'); + // -- Verification + TEST_STR(result, expected); + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This_is my string"); + // -- Run + replace_first(result, ' ', '_'); + // -- Verification + TEST_STR(result, expected); - char test3[] = "This is my string"; - replace_first(test3, ' ', '_'); - TEST_STR(test3, "This_is my string"); + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This is my string"); + // -- Run + replace_first(result, 'T', 'T'); + // -- Verification + TEST_STR(result, expected); }) TFUNCTION(test_split_on_delimiter, { - char test4[] = "key:value"; - char *key; - char *value; - - split_on_delimiter(test4, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test5[] = "key: value"; - split_on_delimiter(test5, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value"); - - char test6[] = "key:value"; - replace_first(test6, ':', ' '); - split_on_delimiter(test6, " ", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test7[] = ""; - split_on_delimiter(test7, ":", &key, &value); - TEST_STR(key, NULL); - TEST_STR(value, NULL); - - char test9[] = "key:value:extra"; - split_on_delimiter(test9, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value:extra"); - - char test10[] = "key: value :extra"; - split_on_delimiter(test10, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value :extra"); + // Useful variables + char string[100]; + char *result_key; + char *result_value; + char expected_key[100]; + char expected_value[100]; + + // Setup + strcpy(string, "key:value"); + strcpy(expected_key, "key"); + strcpy(expected_value, "value"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, "key: value"); + strcpy(expected_key, "key"); + strcpy(expected_value, " value"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, "key:value"); + strcpy(expected_key, "key"); + strcpy(expected_value, "value"); + replace_first(string, ':', ' '); + // Run + split_on_delimiter(string, " ", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, ""); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, NULL); + TEST_STR(result_value, NULL); + + // Setup + strcpy(string, "key:value:extra"); + strcpy(expected_key, "key"); + strcpy(expected_value, "value:extra"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, "key: value :extra"); + strcpy(expected_key, "key"); + strcpy(expected_value, " value :extra"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); }) TFUNCTION(test_start_with, { @@ -110,7 +173,7 @@ TFUNCTION(test_start_with, { TFUNCTION(test_match, { - // usefull variable : + // useful variables : bool _true = true; bool _false = false; KeyFinder keys[10]; @@ -198,11 +261,3 @@ TFILE_ENTRY_POINT(test_info_reader, { CALL_TFUNCTION(test_match); }) -#ifdef __TESTING_INFO_READER__ -int main() -{ - test_info_reader(); - return 0; -} -#endif - -- GitLab From bf96f133e149a083b6145a72a9781bf4cec6d73e Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:28:47 +0000 Subject: [PATCH 088/125] print format --- tests/small_test.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/small_test.h b/tests/small_test.h index 357479a..d1aae8a 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -285,7 +285,7 @@ int test(char *file, int line, unsigned int __indentation_level, void *result, v char *fmt_result = format(buffer_result, expected); char *fmt_expected = format(buffer_expected, result); if (!is_equal) { - INDENTED_PRINT("%s:%d: failed, expected %s, got %s\n", file, line, fmt_expected, fmt_result); + INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); } return !is_equal; } -- GitLab From 2742736d4fa0aa50202f4431863c8a0e34bcea84 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:35:26 +0000 Subject: [PATCH 089/125] remove the gcc dependence --- tests/small_test.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index d1aae8a..9ac572c 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -7,10 +7,9 @@ #include <stdint.h> #include <stdio.h> -// ---------------------------API_INTERFACE - - +#include "../src/util.h" +// ---------------------------API_INTERFACE #define TMAIN(code) \ int main() \ { \ @@ -236,9 +235,10 @@ int string_compare(char *string1, char *string2) } } -char *string_format(__attribute__((unused)) char *buffer, char *string) +char *string_format(char *buffer, char *string) { - return FMT_NULL(string); + UNUSED(buffer); + return FMT_NULL(string); } @@ -247,8 +247,9 @@ int boolean_compare(bool *boolean1, bool *boolean2) return *boolean1 == *boolean2; } -char *boolean_format(__attribute__((unused)) char *buffer, bool *boolean) +char *boolean_format(char *buffer, bool *boolean) { + UNUSED(buffer); return *boolean ? "True" : "False"; } -- GitLab From 356d49ed556835d24998f561e10fc447365505b0 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:39:10 +0000 Subject: [PATCH 090/125] example of how to use src/nfo_reader.c --- .../info_reader_ex.c | 43 ++++++------------- 1 file changed, 12 insertions(+), 31 deletions(-) rename tests/example_info_reader.c => doc/info_reader_ex.c (76%) diff --git a/tests/example_info_reader.c b/doc/info_reader_ex.c similarity index 76% rename from tests/example_info_reader.c rename to doc/info_reader_ex.c index 1dd6464..38d948a 100644 --- a/tests/example_info_reader.c +++ b/doc/info_reader_ex.c @@ -1,23 +1,20 @@ #include "info_reader.h" #include <stdint.h> -#ifdef DEBUG -#warning "PTR_TO_TPTR hide a cast warning" -#endif - #define MAX_PROCS 2 +#define NB_KEYS 6 typedef struct { - size_t processor; + unsigned int processor; char *vendor_id; - size_t family; - size_t core_id; - size_t physical_id; + unsigned int family; + unsigned int core_id; + unsigned int physical_id; char *model_name; } Cpu; GenericPointer int_allocator(char *s) { - size_t value = atoi(s); + unsigned int value = atoi(s); return (GenericPointer) value; } @@ -59,19 +56,6 @@ void set_model_name(GenericPointer storage, GenericPointer data) cpu->model_name = (char *) data; } -struct cpu_sensor_t { - //TODO: check the reset of the msr registers -#warning "Check the reset of the msr registers" - size_t cpu_id; - size_t package_id; - char *name; - - int *fd; - uint64_t energy_units; - uint64_t core_energy; - uint64_t pkg_energy; -}; - int main(int argc, char const *argv[]) { Cpu cpus[MAX_PROCS]; @@ -91,7 +75,7 @@ int main(int argc, char const *argv[]) .capacity = MAX_PROCS, .storage_struct_size = sizeof(Cpu), .keys = keys, - .nb_keys = 6, + .nb_keys = NB_KEYS, .file = fopen("/proc/cpuinfo", "r") }; @@ -99,19 +83,16 @@ int main(int argc, char const *argv[]) for (unsigned int i = 0; i < parser.nb_stored; ++i) { printf("========== PROC[%d] ==========\n", i); - printf("Processor: %ld\n", cpus[i].processor); + printf("Processor: %u\n", cpus[i].processor); printf("Vendor ID: %s\n", cpus[i].vendor_id); - printf("Family: %ld\n", cpus[i].family); - printf("Core ID: %ld\n", cpus[i].core_id); - printf("Physical ID: %ld\n", cpus[i].physical_id); + printf("Family: %u\n", cpus[i].family); + printf("Core ID: %u\n", cpus[i].core_id); + printf("Physical ID: %u\n", cpus[i].physical_id); printf("Model Name: %s\n", cpus[i].model_name); - printf("==============================\n"); free(cpus[i].vendor_id); free(cpus[i].model_name); } - - printf("size = %ld\n", sizeof (struct cpu_sensor_t)); - + printf("==============================\n"); return 0; } -- GitLab From 3ce5385641cc8028ae457ad87c302cfe65fbcad2 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:39:44 +0000 Subject: [PATCH 091/125] format --- doc/info_reader_ex.c | 2 +- tests/small_test.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 38d948a..6b284a5 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -92,7 +92,7 @@ int main(int argc, char const *argv[]) free(cpus[i].vendor_id); free(cpus[i].model_name); } - printf("==============================\n"); + printf("==============================\n"); return 0; } diff --git a/tests/small_test.h b/tests/small_test.h index 9ac572c..33c34c6 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -237,8 +237,8 @@ int string_compare(char *string1, char *string2) char *string_format(char *buffer, char *string) { - UNUSED(buffer); - return FMT_NULL(string); + UNUSED(buffer); + return FMT_NULL(string); } -- GitLab From 97a59e920a7b8df268c7419eed3dae6f8082c791 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 09:00:30 +0000 Subject: [PATCH 092/125] cleanup --- doc/info_reader_ex.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 6b284a5..23ee7d5 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -1,8 +1,30 @@ -#include "info_reader.h" -#include <stdint.h> +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + + +// ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex +#include "./../src/info_reader.h" #define MAX_PROCS 2 #define NB_KEYS 6 + typedef struct { unsigned int processor; char *vendor_id; @@ -56,7 +78,7 @@ void set_model_name(GenericPointer storage, GenericPointer data) cpu->model_name = (char *) data; } -int main(int argc, char const *argv[]) +int main() { Cpu cpus[MAX_PROCS]; KeyFinder keys[] = { -- GitLab From a71438bff16c46aa926086065929c51c119ccd86 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:14:21 +0000 Subject: [PATCH 093/125] add test example --- doc/test_file_ex.c | 112 +++++++++++++++++++++++++++++++++++++++++++++ doc/test_main_ex | Bin 0 -> 17416 bytes doc/test_main_ex.c | 35 ++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 doc/test_file_ex.c create mode 100755 doc/test_main_ex create mode 100644 doc/test_main_ex.c diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c new file mode 100644 index 0000000..44ebc2c --- /dev/null +++ b/doc/test_file_ex.c @@ -0,0 +1,112 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + +// Include of the test library +#include "./../tests/small_test.h" + +// -- A simple function that should pass +TFUNCTION(test_should_pass, { + char *result = "It's going to pass"; + char *expected = "It's going to pass"; + TEST_STR(result, expected); +}) + +// -- A simple function that should fail +TFUNCTION(test_should_fail, { + char *result = "a fail"; + char *expected = "a nice fail"; + TEST_STR(result, expected); +}) + +// -- Add a new type in the test framework + +typedef struct { + int simple_int; + char simple_str[20]; +} UserType; + + +// -- Implemet the interface +int usertype_compare(void *ptr1, void *ptr2) +{ + return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; +} + +char *usertype_format(char buffer[1000], void *ptr) +{ + UserType *x = (UserType *) ptr; + sprintf(buffer, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); + return buffer; +} + +// Create a variable which contains the functions +static const TestInterface usertype_interface = { + .compare = usertype_compare, + .format = usertype_format +}; + +// -- Create the test macro to call +#define TEST_USER_TYPE(__result, __expected) \ + TEST_INTERFACE(__result, __expected, &usertype_interface); + +// -- Create a macro setter +#define DUMMY_USER_TYPE(__user, __simple_int, __simple_str) \ + do { \ + __user = (UserType) { \ + .simple_int = __simple_int, \ + .simple_str = __simple_str \ + }; \ +} while (0); + +// -- Compare two usertype +TFUNCTION(test_user_type, { + UserType x1; + UserType x2; + + DUMMY_USER_TYPE(x1, 1, "John Doe"); + DUMMY_USER_TYPE(x2, 1, "John Doe"); + + TEST_USER_TYPE(&x1, &x2); +}) + + +// -- Compare an array of usetype +TFUNCTION(test_array_user_type, { + UserType *results[1]; + UserType *expecteds[1]; + + UserType x1; + UserType x2; + DUMMY_USER_TYPE(x1, 1, "John Doe"); + DUMMY_USER_TYPE(x2, 1, "John Doe"); + + results[0] = &x1; + expecteds[0] = &x2; + + TEST_T_ARRAY(TEST_USER_TYPE, 1, (void **)results, (void **)expecteds); +}) + +// Define the entry point of a test file +TFILE_ENTRY_POINT(test_file_ex, { + CALL_TFUNCTION(test_should_pass); + CALL_TFUNCTION(test_should_fail); + CALL_TFUNCTION(test_user_type); + CALL_TFUNCTION(test_array_user_type); +}) diff --git a/doc/test_main_ex b/doc/test_main_ex new file mode 100755 index 0000000000000000000000000000000000000000..0ab7870283c6ba20a50b3761a1c009eb89f3ac20 GIT binary patch literal 17416 zcmb<-^>JfjWMqH=W(GS35buEiM8p9?F>u&G84L^z4h$9yybKNu3JmfLYzzzxEMPH+ zJWM@|zQF_$htV7mE(0@Ep9F}(z`%e`%Rtq^XpoygLLeGsABc?&8$d09(F{<3fb_9~ zG(h<<aTx8&4U%MFfYC5<kUp?|3J`e)G+G2~C<6nGM%D)k8wXv8J_lP=8WtWexFF&% zeW2h1>01ERw*aaSMt=Y~h=G9tMnk;|jsuW8Eui6vP8&e2fzjytGNAg<X&0zI7!9%m zBozF#Bn8Aqw+F_D*#o0t_60!o^(cZ&VPHU~_dtXhU^K`MkWk>$k`z$5fY`)fSTqMg z?ZXuh2S5SNz`y{bp~1_bpOcwnW}=^yqMMVMS6ZQ4VPU3gW};V|uV)0d9^@`iQUFE2 zyI&{+69dBmkQg)=8JHR%e3*G4IS~d1aJmPnpJ)5Nb?@T%=MPt`vFmpAvMSud+Xhkt zayLj1NDas$ka<uig18`i7(ht|qy`cmjbL$*7>IE(^;|B9#)U!V3t^EgVPJqKZDeT+ z1_lOf>J4#-YvK@B!XZ8ZhrOV5gU#OgIMjo}17ruX+rjMk_~eSj__WNt#GK5kREGHY zoXn);_~MepqLTRB#LPT~;*z4|+yaK&)Lal%Tu_vmSCYmM4^onx9iN<$9iNt%nZp3m z28w<&26rD%C+B!0JtI9+INJoyGB#m|_YCokPf0CGP0uVYNi7QTb<WApOASd($^qG* zo|~TsGQ6lHJ|3bJt3n0_1||kZ24)5pFl1z4VSr#}22TbCSaHEnDwW9zDuIKcVj`KD zyr5JT59M!}IE@WtQYJVs7#LvX5G+3)5QIp0K+74Jcmq^C08RWPR6GJr+yoj~325R; zQ1J{j@mWyu0yOdSQ1J>h@%K>i1~hREVTk)X(8Lp=;uFxsW5poqXP}8shKh4QD=t_# z!1w}a;{QRJpMinlf<44MP+kP3K?sk5;Rcd8a{hgQB+d>~%)r3#0!f?`N&EwnI4qBY zq*p-2L1uu;2#^>EZ$J_Ul_wxE5Z-|#4l1)iVjz3~NgU({kQfM`KoW<A1xS1pkA}c# z2#kinXb6mkz-R~z{Sf%fFZau%`3;9hH|s@x1_qDT10_uVFL*Q`;W!NT+<(&|eFlb4 z|5c0i85sEG89?eYKr)|RKK%dx{{%1})bRQA@*<oMYVdq|c@WMAHBdgi+z97`8YZ7! zE`;$v{Z~x|o9@B@HviLqRbDhcD;oc=9>_Ha^<UBWZ;|<iZ#_FN#(8u;@@RhYAt1!n z@POe-k6znoP6memqNnv37`~+G@yoY>e8u3=Ys&}<hhElSdJGI6mOn~FJ-S)ff!M7F zN;v;N;FoUzDLf3NJ$h{~f+TxQPk|`Se;%D5JPy9I_c-{2*@N+z$HjjoA|BnWwIIpX z10@{)AEfciyD%`o^n=2$!FH-10|P^;cBn_QZ4`*<(fPE5$D`XeO^<=$#m#^J|G!B2 z|Ns9n)?7UX2FBRK{PHOJUzY#>{~u&fs7L2hkLEWD9-Xx>JUUAscyznI@aS~?;L+{+ zz@yXkhevbm2ZmBUkLKDR45jQlK+*Qv04!L-4if}<?zOZ>cjym~Zr2YUo!2}%kH47q z@BjbS1N>7C@NYYC@-W;ggf%eZe=wA=d33w}c+Kw7&ALICfgu)~YE(ycyMEx`CIHgK zzm37-5X2U&`XIJ+yZ+$c#?W%0gwvy!)rXgX;WfKQFRKSHnq@ycI!i%5|KVZn`T@hx z<~IT!owZOkp%8VwyqvrY3?7~5JUWl>0ENSgb$|c=2RRI@pD}#l(GB*6M>m6qC8jq} z;|1;&h^7}Fy}bQAsFoW-EPsJydGnh9kIvc~ouyYgLoaxA`kwIVbUonH>AR!Z^#Y?u zx9bj%ZVr#`&;uUbt|uT-_y1z2>l=tn0Eb7n>j96>V;;S%t~wyQj{m;|O&&Wuy1~*X zAku0E2<acqwQm?ogO0nt00qfw36EaZm)u}!NEk)^`TxJ!^#x<M>kDhw3q=n+x<SG2 z`=dMbibuEW4bRRG5HoinYf=Sis(r%%i5C<f8g$m)Iqv!dZdnbozPG<YmOWwYc70;) zdZ*}tM=z@vIM_g*YCu+b`1k++$6eomjPdAY%?3-ke(>mJO@J_ecy#;z@aPWx(CvE1 zr<d17gMq=b^Mps|#m+<fKph^BURF=A%HuC;|NZ~Z==ugZ1fFvtg+K(@QP2>$Q}m$Q z^$j?Xr6Bqt!DRgV|Nm~+H+a1|5!qBGu&F3stp^(j^6FG%l{bDNdv!Nh3hdSG5GI;e zBh`_-%Fn>S;L*z(2UdCf#iYL&Uj4&~<kj3?pzz1^sy;+N#H${^FujVD+kC;fZI=Yd zW^i76q5cbN@q#PI^m?#>G9@^-z3}KYeSqx3-#@`w7B$x-bk?p(@#tnz)c{-S`or+R zan~)Nv;j`flE?;h{RDY&3uCwI7Hiiv;3Osw_8lnPWsy}T`~-zNc%<^U>j6+{>aoKs zKO;}UB|mi+$Z(HN*CQUCp=XY}UIB5ByFLIb>U4eL(HZ*Yxa${?s7J5w1CQR&1KqA` ze0q8Rs3JuUXpF+6m-QeAI0jyP{SAtoJ;z<a!3=hJJVXjC@Z!P`kjr;4cDwEXyS&?V z4>%o8LRPf;2Pks(fC~5&4{Z@}h?KCtX!-H~KXTeU($HDkgArsiKn@05{EQv!CWyu1 zV2fukcDv57cI^QN84Ea|Ktc8jS*7j|P>{_58ADN!fyy!06&}6ddTqmT*99OGU)y%O zF7W8~Il2K%ha6qe?b_qh%ez7aDNKDqDWI1%7vicH3x9#abWXGD0><Xr1q>y7kGn1b zn*}Q87$J%vo-Fzf3f(1)-L6Z(p6qs=0}fpiWJSK;L7_VbJ#^K+qlWGqh0a=7{DXsY zIvY}Oa)536!r1Nl#oF}^I5^LOEji@T%en=u5)`n)U@>S-b>$l<VE=%e-tGFP`2b_* z@fXX%e)|LGH-Xa+f`9uD$nOaLKXB&%bKLa@$QZD@{<9*vtKb_b1b#4fyZ!*XtK0Pt zI0Pnwodk7=_cu@o{6S7jZv>!59(Vl!H+d<t$zouWKQMN?ez11^0rv3=u%RFydxBXY zA1i`cP>UXYMe^|vh>vH1OX@$+oCWrQEwVl9zJh!J4cQ-{k{aTJ^T>)izoPp9-cWG; z;i2vNA@(q&oeFL@!&}NApN-<t5Eu=C(GVCqA;1WpQAD^mq^LBN!7VYTIF&)QfI&5< zl%YmJK|z5*wb)8E#YzD*6_%Q!qmWurkeXbQnxbH%T5PAIke*)xW^pm77Hep7F?g1! z7b~RaXXd3Vl;kTEBo-Gl=;@cF7MH}QW#**Dr&j1CGt|Vpq^6}76{V&qxE2-V7b#dN zsHSi+B!cZ=NL0wnOiqQcL9PoePAv+lEJ#(TF3!v?$VrXQ%qszD&{2T$i%W{E6jY0A z!7eT4!fJde7X#Q4pm{%tBm6>rd_cy-F<8DhBfm5!B_8Z<xD14WEDs6{h$sWZ+|uII zqWF@^f>f9&R6Mb$D6ujgMHXxhG%y%I?qOhHV3cOI2DLRnQ&Cgi{r?Z@ynK20|Gx+$ z0|U$Z|NnIu85ly||NjqaOxk|<|KEj?fnmjm|Nm1M85pj8`2W9!k%58l<NyCl7#SFx zKmPxJgpq+E`Q!ipPZ${(=6wABpM{Bm;p)f#|5cb67$iUa|L?-Y!0`Li|NkjW3=Gdc z|Nq~@#K3Uz%m4pNm>3w?zyAM!go%N{|Lgz%PnZ}On!f%2&%(^W@ZkIZ|0>K34Cj9Q z|L?-gz%b$G|Nkk>3=E*TZIG`StAZF9D+Cy&dDuB7FhayZYd9+2{r|59QsBZ4nu2Cf zVPIe|VPIfb@b>@z1duqNfE%BL7e9A7M+1Ysl$DmT3V1pfWNr)t1H+BC|NnzEg48lV z%mvL^UwHffe*jbrM1kz;VPIhR`0oGzY><E}pFkUvGcOxc5)V5E0|Q8Y4Fdy%&HMlV zK_e{;F!@xlG+6!&0|SHC`~UwzbKh|Je1tqGUXtGb|8I(HehxyOhmnDy{QZB(6d}y~ zaD+T49zpV!$odNq@;;0V3=`h}|Bp*PhmnC{<@^8t!D}*L=2s*1_b@UroPGcQ|087c znQnp=fc?+Nz|jBU|Nqx0@{i#1XBZh6qCVo5f5XVYp!(_me=}tLxnS+!@Z(`(V6gu5 z|Gx*ad_6*5hlzn9`P2XZ#-QF1%>B$-j35;t_xUg}FqD1%|33~zJ`^sW!^FU_<;(y7 z?~u)BdJ57Gw!a6IUcdhTe+Wf>CtQ9F69a?FxBvg8kmUox(jbvhJQ@O{Aut*OqaiRF z0;3@?8UlDj0JeS(wq6dlJ`T1X4z~Ucw%!f4z74jX4Yqy_wq6akJ`J`W4b%hzIRLcg z4@C2T2oQ!ghIv731_lNTX$V6SLc!PhL4_GWQyL&CaGM7-1PU5kW`MMZLE<p^umAq% zgZLXjbG8f&46wCg4?uIa3=9mgHDWiQ@~|~&J3*Ql7#N_-s2M<``ye4v5P^iD+88E4 z*O!5&ib2v9AOhO12QfkG+Ca28h+tq~*Z~!QQVbuU4uiS-1T>&vYv*A0%R%+S)cyVs z@gE}tBuM^2`5U0-{fF|Q#xZ<=@@GNie?s|uP;;qG!Pa@Bn`;1#ZwDwH0HqV4bODq` z*GDWLw$2gKX<=Y+cXqZ?&<IT`%_}KYFf`ON)-%vGECq87>x_)_3`{hk!uV|fg(C~Y z$N%W6K=A}x&)Ne`5YXk644`G3*wlmKk%>WoK>)h`6lNYsA4uE*P289PwCYuW0hTXe z>OuL4kwKb40lJ<O<UWvGD5(F<AjSY&2MZDd;TotpuzU^@1K|#^dQo^j1Brp~a`3(e zO#f~JtCwOxUq^ZnEH2IfTW1T4#`92d*m_!+_&umNY~3tO9MmUeWDsY7t&fF?{{pL* zW^jP|_XRY(L48zEI5>bikqitlaT!Ji21W)U1_9{$d|0rmL&Xiy#Ern>;ta5LwlI5L z!Qw&;9#Hk5c}7t91VF_TpyIIdAsQ-P0TqXpYiUsNR;V~M8!{Av#ze5BD_rTP0&I>5 zgMcc?6{r|ndTRr#mta88kNw~TBMjfS05fS3SiK~?T!V>&7Fh@}2r$6PdvKqgfq~&L zBWPW{00XStheiX#Ij}fPH-di6h<$y29ur7h3bZK)p_qYzft?9rKCHe0<r9zsVJ6Vp zaVZ7~XnFvNfv^-vJ(D239s!AgumVUN#6ZJg%pmj81Q{3@tikF97;>N$5x9>Is&Am; zMbHQbk3BFjFhqjIG0g$>@dX$#{Z)xWJ*dwQ^CPlpvzZte1ev55VC5T3ZUsmjw6g)K z30l1|YzLb!zyPbi!DB=W3=D^$;;{N1JhsHZz;F&6p3)2&;K2@<=?n~)q3Umg2J;vg z7{Fs43=9lKP;uD)D)5*X0|Ub&s5q?NhZ*+?Dh_KWz|zk@sJ-a%$OVoU0fs1OMGqbW zVPIh3hl<16A>gqq1_lOcs5q?M0Upy~U|`UJit|A$Qt(&|0|SF2R9ptyuz*^_5DFGY z_#ei~WQK%4x;sn3>IE2J?IZA58v_GF6Ei41!*nC)IZ*ZOpaDS!1_oIAS<B4803Ikr zC<U`lfYdYbfD${H4<pWj#2Ew_mVycjP`JY+f|H9%4E6FE;^PyOGUH1U(;1SBN{UNL z)6(>k84#N};!ASllR?`#iW%bLQ}W}}bMliCbK+A<@{5Y&6H6-?lJh~s(<P}XdIs24 zfcBzf#zTgLQ}arSDjCv>5_41IQ%ZAlD;eVBk$CZ$d6^|BO2Na%py6W3@O5!XQG8x$ zPL7@hXd4S?OgyzHEipNjAt^sU2Z>uyQiQ}SH8VltC6%V7r544*M)dW}8K5FXsl}x^ zC3<EcH<jik$H(iLBA6x&py6!LST~YU@$qR8g~kYlMhK=Mf@#1|T9TQgm&_0!?-u0f z>l*Ls=Mo>!5bqM{=jiL{%n%>%?iU*G>H(GYa0z0FclYska`cJ!cXJDN4T%qNbn<bH zX8`#uEx#x?v4jESEhrOXmyZK%(++{{IUwUeF_>7C$`GHLl30?+0FEz={XlR7O&~-6 zu%Uc#1VQHy!1Du;eMNBPpiM*Z@gRdCdw@XkmYiFFCXc#DC_be)KRzQdF9o!J$kRW* zxFjVr4>X;S0@581^)o0fAe^3;0&y28mLO9SAQm{jpz1-v1y>)RR9p;o5GZv)(hp2w zacU7*BTO~ekB|fmG8AHbZhlH>PJVoGX;N`XQDSmQW_}(6bTbv2=R$m)q0tRar7%;$ zyQZ*ig#z0L4O8%(4C<aPRO3Ne2JCeP2EF3S+>*p32EF2vA_$!UV`b)*q!tx0=;h^? zr0S*TmFg7~<rjdwi6oR%nwgWLo0$R?a&+?41r-Zm<r#^^84P+Um3hULxe&Ufhyg59 zmReK{@;fpozKB7uC^aV$qyfq*$SGma1G`nPAg4qxJ->tj%qUJxX3#51ttes8OUum5 zWY8<h2PGB;z0?e7$&is!gy2EUhzCaoL<fuw(gm_quP7hvz{K3lWClHuD1%-SXg)4E zKQ}iu4>X4YD*`E@LDd1MX$0%f;o8p&vje0S#s<;Kpf(G*tqtNaFu?Ya!e|4CFr0+- z=U@V$dJEJygxQb2j}<iE1XBy5Vf8(T4Z@&)0kVErzXV1@n+YJLV2rLmoPmMi+yDRh zF#BQsXBZ8$AJ%_HcYh+Z?+nuq>tDlY4rqXZ+z4XA^h2v>2GIUKP}3f!AJ$)o(XjqG z*zw>#0gMHq3mF&~Kz(1Bepr7OMnju1@cutc9gMDHU|<0CrD1$ne;P)^nw#kEhuF@* z&<pN2f%<F^5m^5oM#K8|=-~(R|8%H+Cx~|VcmZtOpaLom(hq8yqKDr?XqbTH!AfBr z87K`(-(Yblfgb;$C2gR1f$3L(>VwhXIZmiv5CxTn@8bmZ8<F)lKo!7fC>Nv^jA48j zy#dYr6QB|>8hMTsWB^neZa*k}AlnaXpTg)c*gy|RGjwk$lnJKxquCD|kAl&#{v22_ zG_GK55PcM?AC`XLn~|XzuM6ZjkU}VixgW}9IE$tq*S>O?di40aji%oN+NgxlXW$Nl zm;g&Z5FP`=Qw9bG(3lV?4}!#C`)pzR&e7Gw_%Qk-sErQY9}dzF8;9_Ko&x|=2a*F} z7#~Leg}NVRKWsc90IDBX{DaH_VJ=3<*d9zjtltYehX8io04V>0)WhtB#lvbe`(fjI z6ZAo<85qEOMj%Wu3DXawg~9!2(9UJBG@?HXE%;&i94ZSLyn}HV7#Jj>19~v`!^U?c zp!zvr7D4qulNFT5z#s>;AF3QK4%4p<7lANf$q|`GOCn%}9#8`hKnn)YI2LFq1Lho< zzc`WN9;^{caF|0Fmth`*aKUGEK$&0)G){x21T22r3QRG8#%~}j2nlmHgvY=D0FOXj A`~Uy| literal 0 HcmV?d00001 diff --git a/doc/test_main_ex.c b/doc/test_main_ex.c new file mode 100644 index 0000000..0aa86b9 --- /dev/null +++ b/doc/test_main_ex.c @@ -0,0 +1,35 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + +// ~/mojitos/doc$ gcc -Wall -Wextra -Wpedantic -o test_main_ex test_main_ex.c ./../src/util.c +// Include of the test library +#include "./../tests/small_test.h" + +// Include the *.c files that contain the tests +#include "./test_file_ex.c" +// #include "./test_another_test_file.c" + +// Define the entry point of the programme +TMAIN({ + // Must contain the call to the entry point functions of each file + // USE CALL_TFUNCTION(my_function) instead of my_function() + CALL_TFUNCTION(test_file_ex); + // CALL_TFUNCTION(another_file_entry_point_function); +}) -- GitLab From 852c1ba361755510cb83e1e13b5aad5158c58458 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:14:43 +0000 Subject: [PATCH 094/125] add licence --- src/amd_rapl.c | 2 +- src/amd_rapl.h | 2 +- tests/amd_rapl.c | 20 ++++ tests/info_reader.c | 40 ++++++-- tests/main.c | 20 ++++ tests/small_test.h | 216 +++++++++++++++++++++++++------------------- tests/util.c | 20 ++++ 7 files changed, 215 insertions(+), 105 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 2f20ea2..51df298 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 4f375b9..f16ed4f 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 262c1f8..39214fc 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #include "small_test.h" #include "../src/amd_rapl.c" diff --git a/tests/info_reader.c b/tests/info_reader.c index 32734c9..b2a8c6f 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #include "small_test.h" TFUNCTION(test_replace_first, { @@ -124,27 +144,27 @@ TFUNCTION(test_start_with, { prefix = "Hello"; string = "Hello World"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); prefix = "Goodbye"; string = "Hello World"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); prefix = "Hello World"; string = "Hello"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); prefix = "Hello"; string = "Hello"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); prefix = NULL; string = "Hello World"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); }) #define NONE 0 @@ -193,7 +213,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); TEST_PTR(found_key_finder, &keys[0]); TEST_STR(raw_value, "value"); @@ -207,7 +227,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); TEST_PTR(found_key_finder, NULL); TEST_STR(raw_value, NULL); @@ -221,7 +241,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); TEST_PTR(found_key_finder, NULL); TEST_STR(raw_value, NULL); @@ -236,7 +256,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); TEST_PTR(found_key_finder, &keys[1]); TEST_STR(raw_value, "value"); @@ -249,7 +269,7 @@ TFUNCTION(test_match, { raw_value = NULL; // -- Run result = match(&parser, line, &found_key_finder, &raw_value); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); TEST_PTR(found_key_finder, NULL); TEST_STR(raw_value, NULL); }) diff --git a/tests/main.c b/tests/main.c index e48b56a..3246f04 100644 --- a/tests/main.c +++ b/tests/main.c @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #include "util.c" #include "amd_rapl.c" #include "info_reader.c" diff --git a/tests/small_test.h b/tests/small_test.h index 33c34c6..9f6a6d9 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #ifndef __SMALL_TEST_H #define __SMALL_TEST_H @@ -77,49 +97,48 @@ * @param function_name The name of the test function to be called. */ #define CALL_TFUNCTION(function_name) \ - __error_counter__ += function_name(__indentation_level + 1) - + do {__error_counter__ += function_name(__indentation_level + 1);} while(0) /** * @def TEST_STR(result, expected) * @brief Test strings - * This macro is used to test strings. It takes two arguments: `result`, which is the string to be tested, and `expected`, which is the expected value of the string. + * This macro is used to test strings. It takes two arguments: `__result`, which is the string to be tested, and `__expected`, which is the expected value of the string. * The macro uses the `test_str()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the string to be tested - * @param expected the expected value of the string + * @param __result the string to be tested + * @param __expected the expected value of the string * * @code * TEST_STR("Hello", "Hello"); * @endcode */ -#define TEST_STR(result, expected) \ - __error_counter__ += test_str(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_STR(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &str_interface);} while(0) /** - * @def TEST_BOOLEAN(result, expected) - * @brief Test booleans - * This macro is used to test booleans. It takes two arguments: `result`, which is the boolean to be tested, and `expected`, which is the expected value of the boolean. - * The macro uses the `test_boolean()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. + * @def TEST_BOOL(__result, __expected) + * @brief Test bools + * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to be tested, and `__expected`, which is the expected value of the bool. + * The macro uses the `test_bool()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the boolean to be tested - * @param expected the expected value of the boolean + * @param __result the bool to be tested + * @param __expected the expected value of the bool * * @code - * TEST_BOOLEAN(1 == 1, true); + * TEST_BOOL(1 == 1, true); * @endcode */ -#define TEST_BOOLEAN(result, expected) \ - __error_counter__ += test_boolean(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_BOOL(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &bool_interface);} while (0) /** - * @def TEST_PTR(result, expected) + * @def TEST_PTR(__result, __expected) * @brief Test pointers - * This macro is used to test pointers. It takes two arguments: `result`, which is the pointer to be tested, and `expected`, which is the expected value of the pointer. + * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to be tested, and `__expected`, which is the expected value of the pointer. * The macro uses the `test_ptr()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the pointer to be tested - * @param expected the expected value of the pointer + * @param __result the pointer to be tested + * @param __expected the expected value of the pointer * * @code * int x = 5; @@ -127,47 +146,48 @@ * TEST_PTR(ptr, &x); * @endcode */ -#define TEST_PTR(result, expected) \ - __error_counter__ += test_ptr(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_PTR(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &ptr_interface);} while(0) /** - * @def TEST_UINT64_T(result, expected) + * @def TEST_UINT64_T(__result, __expected) * @brief Test 64-bit unsigned integers - * This macro is used to test 64-bit unsigned integers. It takes two arguments: `result`, which is the integer to be tested, and `expected`, which is the expected value of the integer. + * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, which is the integer to be tested, and `__expected`, which is the expected value of the integer. * The macro uses the `test_uint64_t()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the integer to be tested - * @param expected the expected value of the integer + * @param __result the integer to be tested + * @param __expected the expected value of the integer * * @code * TEST_UINT64_T(5, 5); * @endcode */ -#define TEST_UINT64_T(result, expected) \ - __error_counter__ += test_uint64_t(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_UINT64_T(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) + +#define TEST_INTERFACE(__result, __expected, __interface) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) * @brief Test arrays of data - * The macro uses a for loop to iterate through the array and apply the test function to each element, - * adding any errors to the nb_error variable. + * The macro uses a for loop to iterate through the array and apply the test function to each element. * - * @param function the test function to be used on each element of the array - * @param nb_error the number of errors encountered during the test - * @param size the number of elements in the array - * @param results the array of elements to be tested - * @param expecteds the array of expected values + * @param __test_macro the test function to be used on each element of the array + * @param __array_size the number of elements in the array + * @param __results the array of elements to be tested + * @param __expecteds the array of expected values * @code * int results[3] = {1, 2, 3}; * int expecteds[3] = {1, 2, 3}; - * TEST_T_ARRAY(TEST_INT, errors, 3, results, expecteds); + * TEST_T_ARRAY(TEST_INT, 3, results, expecteds); * @endcode */ -#define TEST_T_ARRAY(function, size, results, expecteds) \ - for (unsigned int i = 0; i < size; i++) { \ - function(results[i], expecteds[i]); \ +#define TEST_T_ARRAY(__test_macro, __array_size, __results, __expecteds) \ + for (unsigned int i = 0; i < __array_size; i++) { \ + __test_macro(__results[i], __expecteds[i]); \ } @@ -213,46 +233,71 @@ #define DEFERRED_FILE_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %u\n",nb_error); -//INDENTED_PRINT("Deferred Error in %s: %d\n",__FILE__, nb_error); #define DEFERRED_FUNCTION_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); -#define FMT_NULL(string) \ - string = string ? string : "NULL" - typedef int (Comparator) (void *, void *); typedef char *(Formatter) (char *, void *); -int string_compare(char *string1, char *string2) +typedef struct { + Comparator *compare; + Formatter *format; +} TestInterface; + +// ---------------------------str_interface + +int str_compare(void *ptr1, void *ptr2) { - if (string1 == NULL && string2 == NULL) { + char *str1 = (char *) ptr1; + char *str2 = (char *) ptr2; + + if (str1 == NULL && str2 == NULL) { return 1; - } else if (string1 == NULL || string2 == NULL) { + } else if (str1 == NULL || str2 == NULL) { return 0; } else { - return (strcmp(string1, string2) == 0); + return (strcmp(str1, str2) == 0); } } -char *string_format(char *buffer, char *string) +char *str_format(char *buffer, void *ptr) { UNUSED(buffer); - return FMT_NULL(string); + static char *str_null = "NULL"; + char *str = (char *) ptr; + return str ? str : str_null; } +static const TestInterface str_interface = { + .compare = str_compare, + .format = str_format +}; + +// --------------------------bool_interface -int boolean_compare(bool *boolean1, bool *boolean2) + +int bool_compare(void *ptr1, void *ptr2) { - return *boolean1 == *boolean2; + bool *bool1 = (bool *) ptr1; + bool *bool2 = (bool *) ptr2; + return *bool1 == *bool2; } -char *boolean_format(char *buffer, bool *boolean) +char *bool_format(char *buffer, void *ptr) { UNUSED(buffer); - return *boolean ? "True" : "False"; + bool *_bool = (bool *) ptr; + return *_bool ? "True" : "False"; } +static const TestInterface bool_interface = { + .compare = bool_compare, + .format = bool_format +}; + +// ---------------------------ptr_interface + int ptr_compare(void *ptr1, void *ptr2) { return ptr1 == ptr2; @@ -264,63 +309,48 @@ char *ptr_format(char *buffer, void *ptr) return buffer; } +static const TestInterface ptr_interface = { + .compare = ptr_compare, + .format = ptr_format +}; + +// ---------------------------u64_interface -int uint64_t_compare(uint64_t *value1, uint64_t *value2) +int u64_compare(void *ptr1, void *ptr2) { - return *value1 == *value2; + uint64_t *v1 = (uint64_t *) ptr1; + uint64_t *v2 = (uint64_t *) ptr2; + return *v1 == *v2; } -char *uint64_t_format(char *buffer, uint64_t *value) +char *u64_format(char *buffer, void *ptr) { - sprintf(buffer, "%"PRIu64"", *value); + uint64_t *v = (uint64_t *) ptr; + sprintf(buffer, "%"PRIu64"", *v); return buffer; } -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, Comparator *compare, Formatter *format) +static const TestInterface u64_interface = { + .compare = u64_compare, + .format = u64_format +}; + +// ---------------------------test_function + +int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) { - __indentation_level++; + __indentation_level += 1; static char buffer_result[1000]; static char buffer_expected[1000]; - int is_equal = compare(result, expected); + int is_equal = interface->compare(result, expected); - char *fmt_result = format(buffer_result, expected); - char *fmt_expected = format(buffer_expected, result); + char *fmt_result = interface->format(buffer_expected, expected); + char *fmt_expected = interface->format(buffer_result, result); if (!is_equal) { INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); } return !is_equal; } -int test_str(char *file, int line,unsigned int __indentation_level, char *result, char *expected) -{ - Comparator *compare = (Comparator *) string_compare; - Formatter *format = (Formatter *) string_format; - - return test(file, line, __indentation_level, result, expected, compare, format); -} - -int test_boolean(char *file, int line, unsigned int __indentation_level, bool *result, bool *expected) -{ - Comparator *compare = (Comparator *) boolean_compare; - Formatter *format = (Formatter *) boolean_format; - - return test(file, line, __indentation_level, (int *) result, (void *) expected, compare, format); -} - -int test_ptr(char *file, int line, unsigned int __indentation_level, void *result, void *expected) -{ - Comparator *compare = (Comparator *) ptr_compare; - Formatter *format = (Formatter *) ptr_format; - - return test(file, line, __indentation_level, result, expected, compare, format); -} - -int test_uint64_t(char *file, int line, unsigned int __indentation_level, void *result, void *expected) -{ - Comparator *compare = (Comparator *) uint64_t_compare; - Formatter *format = (Formatter *) uint64_t_format; - - return test(file, line, __indentation_level, (uint64_t *)result, (uint64_t *)expected, compare, format); -} #endif diff --git a/tests/util.c b/tests/util.c index a91c58f..69941bf 100644 --- a/tests/util.c +++ b/tests/util.c @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + #include "../src/util.h" #include "small_test.h" -- GitLab From 84c35c0d19b073bd1be75b9b7f899b873a7887c5 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:26:23 +0000 Subject: [PATCH 095/125] add informations --- tests/small_test.h | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index 9f6a6d9..aedc685 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -30,6 +30,11 @@ #include "../src/util.h" // ---------------------------API_INTERFACE +/** + * @brief Define the entry point of the tests + * It initializes each useful variables. + */ + #define TMAIN(code) \ int main() \ { \ @@ -169,6 +174,7 @@ #define TEST_INTERFACE(__result, __expected, __interface) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) + /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) * @brief Test arrays of data @@ -192,6 +198,7 @@ // --------------------------------API_CODE +// These functions should not be used, only use the previous macros. #define INDENTED_PRINT(__fmt, ...) \ @@ -202,32 +209,10 @@ printf(__fmt, ##__VA_ARGS__); \ } while(0) -/** - * @def INIT_TEST_FILE() - * @brief Initialize the test file - * This macro is used to initialize the test file. It takes the `__FILE__` and `__func__` preprocessor macros as arguments, which provide the name of the current file and the current function, respectively. - * - * @param __FILE__ preprocessor macro that provides the name of the current file - * @param __func__ preprocessor macro that provides the name of the current function - * - * @code - * INIT_TEST_FILE(); - * @endcode - */ + #define INIT_TEST_FILE() \ INDENTED_PRINT("%s:%s\n", __FILE__, __func__) -/** - * @def INIT_TEST_FUNCTION() - * @brief Initialize the test function - * This macro is used to initialize the test function. It takes the `__func__` preprocessor macro as an argument, which provides the name of the current function. - * - * @param __func__ preprocessor macro that provides the name of the current function - * - * @code - * INIT_TEST_FUNCTION(); - * @endcode - */ #define INIT_TEST_FUNCTION() \ INDENTED_PRINT("%s()\n", __func__); -- GitLab From 467b5b929468cf768471dad5ea1808aaa79b805d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:27:51 +0000 Subject: [PATCH 096/125] remove bin --- doc/test_main_ex | Bin 17416 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 doc/test_main_ex diff --git a/doc/test_main_ex b/doc/test_main_ex deleted file mode 100755 index 0ab7870283c6ba20a50b3761a1c009eb89f3ac20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17416 zcmb<-^>JfjWMqH=W(GS35buEiM8p9?F>u&G84L^z4h$9yybKNu3JmfLYzzzxEMPH+ zJWM@|zQF_$htV7mE(0@Ep9F}(z`%e`%Rtq^XpoygLLeGsABc?&8$d09(F{<3fb_9~ zG(h<<aTx8&4U%MFfYC5<kUp?|3J`e)G+G2~C<6nGM%D)k8wXv8J_lP=8WtWexFF&% zeW2h1>01ERw*aaSMt=Y~h=G9tMnk;|jsuW8Eui6vP8&e2fzjytGNAg<X&0zI7!9%m zBozF#Bn8Aqw+F_D*#o0t_60!o^(cZ&VPHU~_dtXhU^K`MkWk>$k`z$5fY`)fSTqMg z?ZXuh2S5SNz`y{bp~1_bpOcwnW}=^yqMMVMS6ZQ4VPU3gW};V|uV)0d9^@`iQUFE2 zyI&{+69dBmkQg)=8JHR%e3*G4IS~d1aJmPnpJ)5Nb?@T%=MPt`vFmpAvMSud+Xhkt zayLj1NDas$ka<uig18`i7(ht|qy`cmjbL$*7>IE(^;|B9#)U!V3t^EgVPJqKZDeT+ z1_lOf>J4#-YvK@B!XZ8ZhrOV5gU#OgIMjo}17ruX+rjMk_~eSj__WNt#GK5kREGHY zoXn);_~MepqLTRB#LPT~;*z4|+yaK&)Lal%Tu_vmSCYmM4^onx9iN<$9iNt%nZp3m z28w<&26rD%C+B!0JtI9+INJoyGB#m|_YCokPf0CGP0uVYNi7QTb<WApOASd($^qG* zo|~TsGQ6lHJ|3bJt3n0_1||kZ24)5pFl1z4VSr#}22TbCSaHEnDwW9zDuIKcVj`KD zyr5JT59M!}IE@WtQYJVs7#LvX5G+3)5QIp0K+74Jcmq^C08RWPR6GJr+yoj~325R; zQ1J{j@mWyu0yOdSQ1J>h@%K>i1~hREVTk)X(8Lp=;uFxsW5poqXP}8shKh4QD=t_# z!1w}a;{QRJpMinlf<44MP+kP3K?sk5;Rcd8a{hgQB+d>~%)r3#0!f?`N&EwnI4qBY zq*p-2L1uu;2#^>EZ$J_Ul_wxE5Z-|#4l1)iVjz3~NgU({kQfM`KoW<A1xS1pkA}c# z2#kinXb6mkz-R~z{Sf%fFZau%`3;9hH|s@x1_qDT10_uVFL*Q`;W!NT+<(&|eFlb4 z|5c0i85sEG89?eYKr)|RKK%dx{{%1})bRQA@*<oMYVdq|c@WMAHBdgi+z97`8YZ7! zE`;$v{Z~x|o9@B@HviLqRbDhcD;oc=9>_Ha^<UBWZ;|<iZ#_FN#(8u;@@RhYAt1!n z@POe-k6znoP6memqNnv37`~+G@yoY>e8u3=Ys&}<hhElSdJGI6mOn~FJ-S)ff!M7F zN;v;N;FoUzDLf3NJ$h{~f+TxQPk|`Se;%D5JPy9I_c-{2*@N+z$HjjoA|BnWwIIpX z10@{)AEfciyD%`o^n=2$!FH-10|P^;cBn_QZ4`*<(fPE5$D`XeO^<=$#m#^J|G!B2 z|Ns9n)?7UX2FBRK{PHOJUzY#>{~u&fs7L2hkLEWD9-Xx>JUUAscyznI@aS~?;L+{+ zz@yXkhevbm2ZmBUkLKDR45jQlK+*Qv04!L-4if}<?zOZ>cjym~Zr2YUo!2}%kH47q z@BjbS1N>7C@NYYC@-W;ggf%eZe=wA=d33w}c+Kw7&ALICfgu)~YE(ycyMEx`CIHgK zzm37-5X2U&`XIJ+yZ+$c#?W%0gwvy!)rXgX;WfKQFRKSHnq@ycI!i%5|KVZn`T@hx z<~IT!owZOkp%8VwyqvrY3?7~5JUWl>0ENSgb$|c=2RRI@pD}#l(GB*6M>m6qC8jq} z;|1;&h^7}Fy}bQAsFoW-EPsJydGnh9kIvc~ouyYgLoaxA`kwIVbUonH>AR!Z^#Y?u zx9bj%ZVr#`&;uUbt|uT-_y1z2>l=tn0Eb7n>j96>V;;S%t~wyQj{m;|O&&Wuy1~*X zAku0E2<acqwQm?ogO0nt00qfw36EaZm)u}!NEk)^`TxJ!^#x<M>kDhw3q=n+x<SG2 z`=dMbibuEW4bRRG5HoinYf=Sis(r%%i5C<f8g$m)Iqv!dZdnbozPG<YmOWwYc70;) zdZ*}tM=z@vIM_g*YCu+b`1k++$6eomjPdAY%?3-ke(>mJO@J_ecy#;z@aPWx(CvE1 zr<d17gMq=b^Mps|#m+<fKph^BURF=A%HuC;|NZ~Z==ugZ1fFvtg+K(@QP2>$Q}m$Q z^$j?Xr6Bqt!DRgV|Nm~+H+a1|5!qBGu&F3stp^(j^6FG%l{bDNdv!Nh3hdSG5GI;e zBh`_-%Fn>S;L*z(2UdCf#iYL&Uj4&~<kj3?pzz1^sy;+N#H${^FujVD+kC;fZI=Yd zW^i76q5cbN@q#PI^m?#>G9@^-z3}KYeSqx3-#@`w7B$x-bk?p(@#tnz)c{-S`or+R zan~)Nv;j`flE?;h{RDY&3uCwI7Hiiv;3Osw_8lnPWsy}T`~-zNc%<^U>j6+{>aoKs zKO;}UB|mi+$Z(HN*CQUCp=XY}UIB5ByFLIb>U4eL(HZ*Yxa${?s7J5w1CQR&1KqA` ze0q8Rs3JuUXpF+6m-QeAI0jyP{SAtoJ;z<a!3=hJJVXjC@Z!P`kjr;4cDwEXyS&?V z4>%o8LRPf;2Pks(fC~5&4{Z@}h?KCtX!-H~KXTeU($HDkgArsiKn@05{EQv!CWyu1 zV2fukcDv57cI^QN84Ea|Ktc8jS*7j|P>{_58ADN!fyy!06&}6ddTqmT*99OGU)y%O zF7W8~Il2K%ha6qe?b_qh%ez7aDNKDqDWI1%7vicH3x9#abWXGD0><Xr1q>y7kGn1b zn*}Q87$J%vo-Fzf3f(1)-L6Z(p6qs=0}fpiWJSK;L7_VbJ#^K+qlWGqh0a=7{DXsY zIvY}Oa)536!r1Nl#oF}^I5^LOEji@T%en=u5)`n)U@>S-b>$l<VE=%e-tGFP`2b_* z@fXX%e)|LGH-Xa+f`9uD$nOaLKXB&%bKLa@$QZD@{<9*vtKb_b1b#4fyZ!*XtK0Pt zI0Pnwodk7=_cu@o{6S7jZv>!59(Vl!H+d<t$zouWKQMN?ez11^0rv3=u%RFydxBXY zA1i`cP>UXYMe^|vh>vH1OX@$+oCWrQEwVl9zJh!J4cQ-{k{aTJ^T>)izoPp9-cWG; z;i2vNA@(q&oeFL@!&}NApN-<t5Eu=C(GVCqA;1WpQAD^mq^LBN!7VYTIF&)QfI&5< zl%YmJK|z5*wb)8E#YzD*6_%Q!qmWurkeXbQnxbH%T5PAIke*)xW^pm77Hep7F?g1! z7b~RaXXd3Vl;kTEBo-Gl=;@cF7MH}QW#**Dr&j1CGt|Vpq^6}76{V&qxE2-V7b#dN zsHSi+B!cZ=NL0wnOiqQcL9PoePAv+lEJ#(TF3!v?$VrXQ%qszD&{2T$i%W{E6jY0A z!7eT4!fJde7X#Q4pm{%tBm6>rd_cy-F<8DhBfm5!B_8Z<xD14WEDs6{h$sWZ+|uII zqWF@^f>f9&R6Mb$D6ujgMHXxhG%y%I?qOhHV3cOI2DLRnQ&Cgi{r?Z@ynK20|Gx+$ z0|U$Z|NnIu85ly||NjqaOxk|<|KEj?fnmjm|Nm1M85pj8`2W9!k%58l<NyCl7#SFx zKmPxJgpq+E`Q!ipPZ${(=6wABpM{Bm;p)f#|5cb67$iUa|L?-Y!0`Li|NkjW3=Gdc z|Nq~@#K3Uz%m4pNm>3w?zyAM!go%N{|Lgz%PnZ}On!f%2&%(^W@ZkIZ|0>K34Cj9Q z|L?-gz%b$G|Nkk>3=E*TZIG`StAZF9D+Cy&dDuB7FhayZYd9+2{r|59QsBZ4nu2Cf zVPIe|VPIfb@b>@z1duqNfE%BL7e9A7M+1Ysl$DmT3V1pfWNr)t1H+BC|NnzEg48lV z%mvL^UwHffe*jbrM1kz;VPIhR`0oGzY><E}pFkUvGcOxc5)V5E0|Q8Y4Fdy%&HMlV zK_e{;F!@xlG+6!&0|SHC`~UwzbKh|Je1tqGUXtGb|8I(HehxyOhmnDy{QZB(6d}y~ zaD+T49zpV!$odNq@;;0V3=`h}|Bp*PhmnC{<@^8t!D}*L=2s*1_b@UroPGcQ|087c znQnp=fc?+Nz|jBU|Nqx0@{i#1XBZh6qCVo5f5XVYp!(_me=}tLxnS+!@Z(`(V6gu5 z|Gx*ad_6*5hlzn9`P2XZ#-QF1%>B$-j35;t_xUg}FqD1%|33~zJ`^sW!^FU_<;(y7 z?~u)BdJ57Gw!a6IUcdhTe+Wf>CtQ9F69a?FxBvg8kmUox(jbvhJQ@O{Aut*OqaiRF z0;3@?8UlDj0JeS(wq6dlJ`T1X4z~Ucw%!f4z74jX4Yqy_wq6akJ`J`W4b%hzIRLcg z4@C2T2oQ!ghIv731_lNTX$V6SLc!PhL4_GWQyL&CaGM7-1PU5kW`MMZLE<p^umAq% zgZLXjbG8f&46wCg4?uIa3=9mgHDWiQ@~|~&J3*Ql7#N_-s2M<``ye4v5P^iD+88E4 z*O!5&ib2v9AOhO12QfkG+Ca28h+tq~*Z~!QQVbuU4uiS-1T>&vYv*A0%R%+S)cyVs z@gE}tBuM^2`5U0-{fF|Q#xZ<=@@GNie?s|uP;;qG!Pa@Bn`;1#ZwDwH0HqV4bODq` z*GDWLw$2gKX<=Y+cXqZ?&<IT`%_}KYFf`ON)-%vGECq87>x_)_3`{hk!uV|fg(C~Y z$N%W6K=A}x&)Ne`5YXk644`G3*wlmKk%>WoK>)h`6lNYsA4uE*P289PwCYuW0hTXe z>OuL4kwKb40lJ<O<UWvGD5(F<AjSY&2MZDd;TotpuzU^@1K|#^dQo^j1Brp~a`3(e zO#f~JtCwOxUq^ZnEH2IfTW1T4#`92d*m_!+_&umNY~3tO9MmUeWDsY7t&fF?{{pL* zW^jP|_XRY(L48zEI5>bikqitlaT!Ji21W)U1_9{$d|0rmL&Xiy#Ern>;ta5LwlI5L z!Qw&;9#Hk5c}7t91VF_TpyIIdAsQ-P0TqXpYiUsNR;V~M8!{Av#ze5BD_rTP0&I>5 zgMcc?6{r|ndTRr#mta88kNw~TBMjfS05fS3SiK~?T!V>&7Fh@}2r$6PdvKqgfq~&L zBWPW{00XStheiX#Ij}fPH-di6h<$y29ur7h3bZK)p_qYzft?9rKCHe0<r9zsVJ6Vp zaVZ7~XnFvNfv^-vJ(D239s!AgumVUN#6ZJg%pmj81Q{3@tikF97;>N$5x9>Is&Am; zMbHQbk3BFjFhqjIG0g$>@dX$#{Z)xWJ*dwQ^CPlpvzZte1ev55VC5T3ZUsmjw6g)K z30l1|YzLb!zyPbi!DB=W3=D^$;;{N1JhsHZz;F&6p3)2&;K2@<=?n~)q3Umg2J;vg z7{Fs43=9lKP;uD)D)5*X0|Ub&s5q?NhZ*+?Dh_KWz|zk@sJ-a%$OVoU0fs1OMGqbW zVPIh3hl<16A>gqq1_lOcs5q?M0Upy~U|`UJit|A$Qt(&|0|SF2R9ptyuz*^_5DFGY z_#ei~WQK%4x;sn3>IE2J?IZA58v_GF6Ei41!*nC)IZ*ZOpaDS!1_oIAS<B4803Ikr zC<U`lfYdYbfD${H4<pWj#2Ew_mVycjP`JY+f|H9%4E6FE;^PyOGUH1U(;1SBN{UNL z)6(>k84#N};!ASllR?`#iW%bLQ}W}}bMliCbK+A<@{5Y&6H6-?lJh~s(<P}XdIs24 zfcBzf#zTgLQ}arSDjCv>5_41IQ%ZAlD;eVBk$CZ$d6^|BO2Na%py6W3@O5!XQG8x$ zPL7@hXd4S?OgyzHEipNjAt^sU2Z>uyQiQ}SH8VltC6%V7r544*M)dW}8K5FXsl}x^ zC3<EcH<jik$H(iLBA6x&py6!LST~YU@$qR8g~kYlMhK=Mf@#1|T9TQgm&_0!?-u0f z>l*Ls=Mo>!5bqM{=jiL{%n%>%?iU*G>H(GYa0z0FclYska`cJ!cXJDN4T%qNbn<bH zX8`#uEx#x?v4jESEhrOXmyZK%(++{{IUwUeF_>7C$`GHLl30?+0FEz={XlR7O&~-6 zu%Uc#1VQHy!1Du;eMNBPpiM*Z@gRdCdw@XkmYiFFCXc#DC_be)KRzQdF9o!J$kRW* zxFjVr4>X;S0@581^)o0fAe^3;0&y28mLO9SAQm{jpz1-v1y>)RR9p;o5GZv)(hp2w zacU7*BTO~ekB|fmG8AHbZhlH>PJVoGX;N`XQDSmQW_}(6bTbv2=R$m)q0tRar7%;$ zyQZ*ig#z0L4O8%(4C<aPRO3Ne2JCeP2EF3S+>*p32EF2vA_$!UV`b)*q!tx0=;h^? zr0S*TmFg7~<rjdwi6oR%nwgWLo0$R?a&+?41r-Zm<r#^^84P+Um3hULxe&Ufhyg59 zmReK{@;fpozKB7uC^aV$qyfq*$SGma1G`nPAg4qxJ->tj%qUJxX3#51ttes8OUum5 zWY8<h2PGB;z0?e7$&is!gy2EUhzCaoL<fuw(gm_quP7hvz{K3lWClHuD1%-SXg)4E zKQ}iu4>X4YD*`E@LDd1MX$0%f;o8p&vje0S#s<;Kpf(G*tqtNaFu?Ya!e|4CFr0+- z=U@V$dJEJygxQb2j}<iE1XBy5Vf8(T4Z@&)0kVErzXV1@n+YJLV2rLmoPmMi+yDRh zF#BQsXBZ8$AJ%_HcYh+Z?+nuq>tDlY4rqXZ+z4XA^h2v>2GIUKP}3f!AJ$)o(XjqG z*zw>#0gMHq3mF&~Kz(1Bepr7OMnju1@cutc9gMDHU|<0CrD1$ne;P)^nw#kEhuF@* z&<pN2f%<F^5m^5oM#K8|=-~(R|8%H+Cx~|VcmZtOpaLom(hq8yqKDr?XqbTH!AfBr z87K`(-(Yblfgb;$C2gR1f$3L(>VwhXIZmiv5CxTn@8bmZ8<F)lKo!7fC>Nv^jA48j zy#dYr6QB|>8hMTsWB^neZa*k}AlnaXpTg)c*gy|RGjwk$lnJKxquCD|kAl&#{v22_ zG_GK55PcM?AC`XLn~|XzuM6ZjkU}VixgW}9IE$tq*S>O?di40aji%oN+NgxlXW$Nl zm;g&Z5FP`=Qw9bG(3lV?4}!#C`)pzR&e7Gw_%Qk-sErQY9}dzF8;9_Ko&x|=2a*F} z7#~Leg}NVRKWsc90IDBX{DaH_VJ=3<*d9zjtltYehX8io04V>0)WhtB#lvbe`(fjI z6ZAo<85qEOMj%Wu3DXawg~9!2(9UJBG@?HXE%;&i94ZSLyn}HV7#Jj>19~v`!^U?c zp!zvr7D4qulNFT5z#s>;AF3QK4%4p<7lANf$q|`GOCn%}9#8`hKnn)YI2LFq1Lho< zzc`WN9;^{caF|0Fmth`*aKUGEK$&0)G){x21T22r3QRG8#%~}j2nlmHgvY=D0FOXj A`~Uy| -- GitLab From 3cea2c76469572799d4055b594ab75f5304e0a91 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:29:11 +0000 Subject: [PATCH 097/125] ignore new bin --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8110229..dd136f4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ obj *.swp *.swo .vscode +doc/test_main_ex +doc/info_reader_ex -- GitLab From 178fe4489ae2b09c831b4066f9059818c540db48 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 6 Feb 2023 10:43:08 +0100 Subject: [PATCH 098/125] small changes --- lib/optparse.h | 2 +- makefile | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/optparse.h b/lib/optparse.h index 1925d73..ee7dcb6 100644 --- a/lib/optparse.h +++ b/lib/optparse.h @@ -73,7 +73,7 @@ struct optparse_long { enum optparse_argtype argtype; char *usage_arg; char *usage_msg; - void *(*fn)(void *, size_t); + void *(*fn)(void *, size_t); /* SUBJECT TO CHANGE */ }; /** diff --git a/makefile b/makefile index d5d2d23..950028c 100644 --- a/makefile +++ b/makefile @@ -55,14 +55,14 @@ tests: $(TESTS_DIR)/run format: - $(ASTYLE) $(SRC_DIR)/*.[ch] - $(ASTYLE) $(DOC_DIR)/*.[ch] - $(ASTYLE) $(TESTS_DIR)/*.[ch] + $(ASTYLE) $(SRC_DIR)/*.[ch] \ + $(DOC_DIR)/*.[ch] \ + $(TESTS_DIR)/*.[ch] clean: - \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* - \rm -f $(SRC_DIR)/counters_option.h - \rm -f $(TESTS_DIR)/run + \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \ + $(SRC_DIR)/counters_option.h \ + $(TESTS_DIR)/run readme: $(BIN) sh ./tools/update-readme-usage.sh -- GitLab From a4e986e16dbd6df538feffafb379a83fc54ed8ea Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 10:04:56 +0000 Subject: [PATCH 099/125] fix: NB_MAX cpu --- doc/info_reader_ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 23ee7d5..5cfa5f4 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -22,7 +22,7 @@ // ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex #include "./../src/info_reader.h" -#define MAX_PROCS 2 +#define MAX_PROCS 64 #define NB_KEYS 6 typedef struct { -- GitLab From c0fa12bc47039fdeeebcda32f042c5d493f6b62c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 10:05:38 +0000 Subject: [PATCH 100/125] core: amd_rapl.c --- src/amd_rapl.c | 92 ++++++++++++++++++++++++++++++++++++------------ tests/amd_rapl.c | 34 +++--------------- 2 files changed, 74 insertions(+), 52 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 51df298..f6eff43 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -30,6 +30,7 @@ #include "util.h" #define BUFFER_SIZE 64 +#define __READ_CPUINFO__ // ---------------------------MSR_REGISTERS static const uint64_t amd_energy_mask = 0xFFFFFFFF; @@ -62,11 +63,9 @@ typedef struct _amd_rapl_t _amd_rapl_t; // -----------------------------INFO_READER #ifdef __READ_CPUINFO__ -#warning "Must be modified before release" -#define MAX_CPUS 64 #define NB_KEYS 3 -static const char *cpuinfo = "/proc/cpuinfo"; +static char *cpuinfo = "/proc/cpuinfo"; static GenericPointer uint_allocator(char *s) { @@ -97,6 +96,21 @@ static KeyFinder keys[NB_KEYS] = { {"physical id", ": ", uint_allocator, _set_package_id}, {"core id", ": ", uint_allocator, _set_core_id} }; + + +static unsigned int parse_cpuinfo(cpu_sensor_t* storage, unsigned int capacity) { + Parser parser = { + .storage = (GenericPointer) storage, + .nb_stored = 0, + .capacity = capacity, + .storage_struct_size = sizeof(cpu_sensor_t), + .keys = keys, + .nb_keys = NB_KEYS, + .file = fopen(cpuinfo, "r") + }; + return parse(&parser); +} + #endif // --------------------------------READ_MSR @@ -159,13 +173,14 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(cpu_sensor_t *sensor) { //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %d, package_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", + printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", sensor->cpu_id, sensor->package_id, + sensor->core_id, sensor->name, sensor->fd, sensor->energy_units, - sensor->core_energy, + sensor->core_energy ); } @@ -197,6 +212,22 @@ unsigned int get_nb_cpu() return n_cpu; } +void get_arch(unsigned int *ret_nb_package, unsigned int *ret_nb_core, cpu_sensor_t *sensors, unsigned int nb_sensor) +{ + unsigned int nb_package = 0; + unsigned int nb_core = 0; + for (unsigned int i = 0; i < nb_sensor; i++) { + if (sensors[i].package_id > nb_package) { + nb_package = sensors[i].package_id; + } + if (sensors[i].core_id > nb_core) { + nb_core = sensors[i].core_id; + } + } + *ret_nb_package = nb_package + 1; + *ret_nb_core = nb_core + 1; +} + char *get_name(unsigned int cpu_id) { static const char *base_name = "core%d"; @@ -216,27 +247,29 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id, unsigned char *cpus_map, unsigned int max_cpus) -{ - if (cpus_map[sensor->core_id * max_cpus + sensor->package_id] > 0) { - return 0; +unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) { + if (map[sensor->core_id * nb_core + sensor->package_id]) { + return 1; } - cpus_map[sensor->core_id * max_cpus + sensor->package_id] += 1; + map[sensor->core_id * nb_core + sensor->package_id] += 1; + return 0; +} +void init_cpu_sensor(cpu_sensor_t *sensor, cpu_sensor_t *cpu_info) +{ static char filename[BUFFER_SIZE]; - sprintf(filename, base_str, cpu_id); + snprintf(filename,BUFFER_SIZE, base_str, cpu_info->cpu_id); int fd = open(filename, O_RDONLY); if (fd < 0) { - fprintf(stderr, base_str, cpu_id); + fprintf(stderr, base_str, cpu_info->cpu_id); perror(":open()"); exit(127); } - sensor->cpu_id = cpu_id; - sensor->name = get_name(cpu_id); + memcpy(sensor, cpu_info, sizeof(cpu_sensor_t)); + sensor->name = get_name(sensor->cpu_id); sensor->fd = fd; - return 1; } void clean_cpu_sensor(cpu_sensor_t *sensor) @@ -256,7 +289,6 @@ void free_amd_rapl(_amd_rapl_t *rapl) unsigned int init_amd_rapl(char *none, void **ptr) { UNUSED(none); - _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); unsigned int max_cpus = get_nb_cpu(); if (max_cpus == 0) { @@ -265,18 +297,32 @@ unsigned int init_amd_rapl(char *none, void **ptr) exit(127); } - unsigned char *cpus_map = calloc(max_cpus * max_cpus, sizeof(unsigned char)); - cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); - rapl->sensors = cpus; + cpu_sensor_t *cpu_information = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); + if (parse_cpuinfo(cpu_information, max_cpus)) { + free(cpu_information); + PANIC(1, "cpuinfo"); + } - unsigned int nb_cpu = 0; + unsigned int nb_package; + unsigned int nb_core; + get_arch(&nb_package, &nb_core, cpu_information, max_cpus); + + unsigned char *cpu_map = (unsigned char*) calloc(nb_core * nb_package, sizeof(unsigned char)); + cpu_sensor_t *sensors = (cpu_sensor_t*) calloc(max_cpus, sizeof(cpu_sensor_t)); + + unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - nb_cpu += init_cpu_sensor(&rapl->sensors[nb_cpu], i, cpus_map, max_cpus); + if (!is_duplicate(cpu_information, cpu_map, nb_core)) { + init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); + sensor_count += 1; + } } - rapl->sensor_count = nb_cpu; + free(cpu_information); + _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); + rapl->sensors = sensors; + rapl->sensor_count = sensor_count; *ptr = (void *) rapl; - free(cpus_map); return rapl->sensor_count; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 39214fc..2425287 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -179,48 +179,24 @@ TFUNCTION(test_label_amd_rapl, { TEST_T_ARRAY(TEST_STR, nb, results, expecteds); }) -TFUNCTION(test_init_cpu_sensor, { - static const unsigned int max_cpus = 10; - unsigned char cpus_map[max_cpus * max_cpus]; - cpu_sensor_t sensor_t1; - unsigned int result; - unsigned int expected; - - // Test 1: - // -- Setup - memset(cpus_map, 0, max_cpus *max_cpus * sizeof(unsigned char)); - result = 0; - expected = 1; - memset(&sensor_t1, 0, sizeof(cpu_sensor_t)); - sensor_t1.cpu_id = 1; - sensor_t1.core_id = 0; - sensor_t1.package_id = 0; - // -- Run - result = init_cpu_sensor(&sensor_t1, 0, cpus_map, max_cpus); - // -- Verification - TEST_UINT64_T(&result, &expected); -}) - TFILE_ENTRY_POINT(test_amd_rapl, { CALL_TFUNCTION(test_raw_to_microjoule); CALL_TFUNCTION(test_get_name); CALL_TFUNCTION(test_label_amd_rapl); - // CALL_TFUNCTION(test_init_cpu_sensor); }) #ifdef __TESTING__AMD__ int main() { - test_amd_rapl(); static const unsigned int time = 10; _amd_rapl_t *rapl = NULL; - unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); - uint64_t results[nb_cpu]; - char *labels[nb_cpu]; + unsigned int count_cpu = init_amd_rapl(NULL, (void **) &rapl); + uint64_t results[count_cpu]; + char *labels[count_cpu]; label_amd_rapl(labels, (void *) rapl); - for (unsigned int i = 0; i < rapl->nb; ++i) { + for (unsigned int i = 0; i < rapl->sensor_count; ++i) { printf("%s ", labels[i]); } printf("\n"); @@ -231,7 +207,7 @@ int main() sleep(1); get_amd_rapl(results, (void *)rapl); - for (unsigned int j = 0; j < rapl->nb; ++j) { + for (unsigned int j = 0; j < rapl->sensor_count; ++j) { printf("%ld ", results[j]); } printf("\n"); -- GitLab From 49e40f735fa71393d1102a73df6c782fbacc9dbb Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 11:47:35 +0000 Subject: [PATCH 101/125] core: small_test modification of the api --- doc/info_reader_ex.c | 2 +- doc/test_file_ex.c | 31 ++++++++---- src/amd_rapl.c | 14 +++--- tests/amd_rapl.c | 116 ++++++++++++++++++++++++++++++++++++++---- tests/small_test.h | 117 +++++++++++++++++++++++++++++++++++-------- 5 files changed, 231 insertions(+), 49 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 5cfa5f4..f672d98 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -22,7 +22,7 @@ // ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex #include "./../src/info_reader.h" -#define MAX_PROCS 64 +#define MAX_PROCS 64 #define NB_KEYS 6 typedef struct { diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 44ebc2c..4e3a093 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -35,6 +35,20 @@ TFUNCTION(test_should_fail, { TEST_STR(result, expected); }) +// -- A simple test of array +TFUNCTION(test_array, { + static unsigned int size = 10; + int array[10]; + TEST_ARRAY(TEST_INT, size, array, array); +}) + +// -- A simple test of array of pointer +TFUNCTION(test_ptr_array, { + static unsigned int size = 10; + void *array[10]; + TEST_PTR_ARRAY(TEST_PTR, size, array, array); +}) + // -- Add a new type in the test framework typedef struct { @@ -89,24 +103,21 @@ TFUNCTION(test_user_type, { // -- Compare an array of usetype TFUNCTION(test_array_user_type, { - UserType *results[1]; - UserType *expecteds[1]; - - UserType x1; - UserType x2; - DUMMY_USER_TYPE(x1, 1, "John Doe"); - DUMMY_USER_TYPE(x2, 1, "John Doe"); + UserType results[1]; + UserType expecteds[1]; - results[0] = &x1; - expecteds[0] = &x2; + DUMMY_USER_TYPE(results[0], 1, "John Doe"); + DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - TEST_T_ARRAY(TEST_USER_TYPE, 1, (void **)results, (void **)expecteds); + TEST_ARRAY(TEST_USER_TYPE, 1, results, expecteds); }) // Define the entry point of a test file TFILE_ENTRY_POINT(test_file_ex, { CALL_TFUNCTION(test_should_pass); CALL_TFUNCTION(test_should_fail); + CALL_TFUNCTION(test_array); + CALL_TFUNCTION(test_ptr_array); CALL_TFUNCTION(test_user_type); CALL_TFUNCTION(test_array_user_type); }) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index f6eff43..1d9bc37 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -98,7 +98,8 @@ static KeyFinder keys[NB_KEYS] = { }; -static unsigned int parse_cpuinfo(cpu_sensor_t* storage, unsigned int capacity) { +static unsigned int parse_cpuinfo(cpu_sensor_t *storage, unsigned int capacity) +{ Parser parser = { .storage = (GenericPointer) storage, .nb_stored = 0, @@ -247,12 +248,13 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) { +unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) +{ if (map[sensor->core_id * nb_core + sensor->package_id]) { - return 1; + return 0; } map[sensor->core_id * nb_core + sensor->package_id] += 1; - return 0; + return 1; } void init_cpu_sensor(cpu_sensor_t *sensor, cpu_sensor_t *cpu_info) @@ -307,8 +309,8 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int nb_core; get_arch(&nb_package, &nb_core, cpu_information, max_cpus); - unsigned char *cpu_map = (unsigned char*) calloc(nb_core * nb_package, sizeof(unsigned char)); - cpu_sensor_t *sensors = (cpu_sensor_t*) calloc(max_cpus, sizeof(cpu_sensor_t)); + unsigned char *cpu_map = (unsigned char *) calloc(nb_core * nb_package, sizeof(unsigned char)); + cpu_sensor_t *sensors = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 2425287..1857a6a 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -116,15 +116,15 @@ do { \ .energy_units = NONE, \ .core_energy = NONE, \ }; \ - } while(0); +} while(0); #define DUMMY_RAPL(__rapl, __sensors, __sensors_count) \ - do { \ - __rapl = (_amd_rapl_t) { \ - .sensors = __sensors, \ - .sensor_count = __sensors_count \ - }; \ - } while(0); +do { \ + __rapl = (_amd_rapl_t) { \ + .sensors = __sensors, \ + .sensor_count = __sensors_count \ + }; \ +} while(0); TFUNCTION(test_label_amd_rapl, { cpu_sensor_t sensors[100]; @@ -142,7 +142,7 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); // Test 2: // -- Setup @@ -159,7 +159,7 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); // Test 3: // -- Setup @@ -176,13 +176,109 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); }) + +#define DUMMY_CPUINFO(__sensor, __cpu_id, __package_id, __core_id) \ +do { \ + __sensor = (cpu_sensor_t) { \ + .cpu_id = __cpu_id, \ + .package_id = __package_id, \ + .core_id = __core_id, \ + .name = NULL, \ + .fd = NONE, \ + .energy_units = NONE, \ + .core_energy = NONE \ + }; \ +} while (0); + +TFUNCTION(test_is_duplicate, { + static const unsigned int nb_core = 4; + static const unsigned int nb_package = 2; + static const unsigned int max_cpu = 10; + + unsigned char map[nb_core * nb_package]; + cpu_sensor_t cpu_information[max_cpu]; + unsigned int results[2]; + unsigned int expecteds[2]; + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + expecteds[0] = 1; + expecteds[1] = 0; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[0], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 1, 1); + expecteds[0] = 1; + expecteds[1] = 0; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 0, 0); + expecteds[0] = 1; + expecteds[1] = 1; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 1, 0); + expecteds[0] = 1; + expecteds[1] = 1; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); + expecteds[0] = 1; + expecteds[1] = 1; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); +}) + + TFILE_ENTRY_POINT(test_amd_rapl, { CALL_TFUNCTION(test_raw_to_microjoule); CALL_TFUNCTION(test_get_name); CALL_TFUNCTION(test_label_amd_rapl); + CALL_TFUNCTION(test_is_duplicate); }) #ifdef __TESTING__AMD__ diff --git a/tests/small_test.h b/tests/small_test.h index aedc685..ef9d90b 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -33,15 +33,17 @@ /** * @brief Define the entry point of the tests * It initializes each useful variables. + * + * @param __code The code that contains the calls to the test functions */ -#define TMAIN(code) \ +#define TMAIN(__code) \ int main() \ { \ unsigned int __indentation_level = 0; \ INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ unsigned int __error_counter__ = 0; \ - do code while (0); \ + do __code while (0); \ DEFERRED_FILE_ERROR(__error_counter__); \ return __error_counter__; \ } @@ -108,7 +110,6 @@ * @def TEST_STR(result, expected) * @brief Test strings * This macro is used to test strings. It takes two arguments: `__result`, which is the string to be tested, and `__expected`, which is the expected value of the string. - * The macro uses the `test_str()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * * @param __result the string to be tested * @param __expected the expected value of the string @@ -124,23 +125,43 @@ * @def TEST_BOOL(__result, __expected) * @brief Test bools * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to be tested, and `__expected`, which is the expected value of the bool. - * The macro uses the `test_bool()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param __result the bool to be tested - * @param __expected the expected value of the bool + * @param __result the pointer to bool to be tested + * @param __expected the pointer to the expected value of the bool * * @code - * TEST_BOOL(1 == 1, true); + * bool x = true; + * bool y = false; + * TEST_BOOL(&x, &y); * @endcode */ #define TEST_BOOL(__result, __expected) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &bool_interface);} while (0) +/** + * @def TEST_INT(__result, __expected) + * @brief Test ints + * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be tested, and `__expected`, which is the expected value of the int. + * + * @param __result the pointer to int to be tested + * @param __expected the pointer to expected value of the int + * + * @code + * int x = 1; + * int y = 1; + * TEST_INT(&x, &y) + * @endcode + */ +#define TEST_INT(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &int_interface);} while (0) + + + + /** * @def TEST_PTR(__result, __expected) * @brief Test pointers * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to be tested, and `__expected`, which is the expected value of the pointer. - * The macro uses the `test_ptr()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * * @param __result the pointer to be tested * @param __expected the expected value of the pointer @@ -159,24 +180,38 @@ * @def TEST_UINT64_T(__result, __expected) * @brief Test 64-bit unsigned integers * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, which is the integer to be tested, and `__expected`, which is the expected value of the integer. - * The macro uses the `test_uint64_t()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param __result the integer to be tested - * @param __expected the expected value of the integer + * @param __result the pointer to integer to be tested + * @param __expected the pointer to expected value of the integer * * @code - * TEST_UINT64_T(5, 5); + * uint64_t x = 5; + * uint64_t y = 5; + * TEST_UINT64_T(&x, &y); * @endcode */ #define TEST_UINT64_T(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) +/** + * @def TEST_INTERFACE(__result, __expected, __interface) + * @brief Define a macro on a usertype with the given __interface + * This macro is used by the user to define a new test macro on a usertype. + * + * @param __result + * @param __expected + * @param __interface the usertype interface + * + * @code + * #define TEST_USERTYPE(__result, __expected) + * TEST_INTERFACE(__result, __expected, usertype_interface) + * @endcode + */ #define TEST_INTERFACE(__result, __expected, __interface) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) - + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) /** - * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) + * @def TEST_T_ARRAY(__test_macro, __size, __results, __expecteds) * @brief Test arrays of data * The macro uses a for loop to iterate through the array and apply the test function to each element. * @@ -188,15 +223,33 @@ * @code * int results[3] = {1, 2, 3}; * int expecteds[3] = {1, 2, 3}; - * TEST_T_ARRAY(TEST_INT, 3, results, expecteds); + * TEST_ARRAY(TEST_INT, 3, results, expecteds); * @endcode */ -#define TEST_T_ARRAY(__test_macro, __array_size, __results, __expecteds) \ - for (unsigned int i = 0; i < __array_size; i++) { \ - __test_macro(__results[i], __expecteds[i]); \ - } +#define TEST_ARRAY(__test_macro, __array_size, __results, __expecteds) \ + for (unsigned i = 0; i < __array_size; i++) { \ + __test_macro(&__results[i], &__expecteds[i]); \ + } +/** + * @def TEST_T_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) + * @brief Test arrays of pointer + * The macro uses a for loop to iterate through the array and apply the test function to each element. + * + * @param __test_macro the test function to be used on each element of the array + * @param __array_size the number of elements in the array + * @param __results the array of elements to be tested + * @param __expecteds the array of expected values + * @code + * void* array[3]; + * TEST_PTR_ARRAY(TEST_PTR, 3, array, array); + * @endcode +*/ +#define TEST_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) \ + for (unsigned int i = 0; i < __array_size; i++) { \ + __test_macro(__results[i], __expecteds[i]); \ + } // --------------------------------API_CODE // These functions should not be used, only use the previous macros. @@ -261,7 +314,6 @@ static const TestInterface str_interface = { // --------------------------bool_interface - int bool_compare(void *ptr1, void *ptr2) { bool *bool1 = (bool *) ptr1; @@ -281,6 +333,27 @@ static const TestInterface bool_interface = { .format = bool_format }; +// ---------------------------int_interface + +int int_compare(void *ptr1, void *ptr2) +{ + int *int1 = (int *) ptr1; + int *int2 = (int *) ptr2; + return *int1 == *int2; +} + +char *int_format(char buffer[1000], void *ptr) +{ + int *_int = (int *) ptr; + snprintf(buffer, 1000, "%d", *_int); + return buffer; +} + +static const TestInterface int_interface = { + .compare = int_compare, + .format = int_format +}; + // ---------------------------ptr_interface int ptr_compare(void *ptr1, void *ptr2) -- GitLab From 1616952d1be622d88232b46a90cd9bc97583d5fe Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 12:09:00 +0000 Subject: [PATCH 102/125] fix: is_duplicate --- src/amd_rapl.c | 2 +- tests/amd_rapl.c | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 1d9bc37..0c363af 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -314,7 +314,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - if (!is_duplicate(cpu_information, cpu_map, nb_core)) { + if (is_duplicate(cpu_information, cpu_map, nb_core) == 1) { init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); sensor_count += 1; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 1857a6a..f2d13ef 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -200,8 +200,8 @@ TFUNCTION(test_is_duplicate, { unsigned char map[nb_core * nb_package]; cpu_sensor_t cpu_information[max_cpu]; - unsigned int results[2]; - unsigned int expecteds[2]; + unsigned int results[max_cpu]; + unsigned int expecteds[max_cpu]; // -- Setup memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); @@ -271,6 +271,26 @@ TFUNCTION(test_is_duplicate, { // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 0, 0); + DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); + DUMMY_CPUINFO(cpu_information[2], 0, 1, 0); + DUMMY_CPUINFO(cpu_information[3], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[4], 0, 0, 0); + DUMMY_CPUINFO(cpu_information[5], 0, 0, 1); + DUMMY_CPUINFO(cpu_information[6], 0, 1, 0); + DUMMY_CPUINFO(cpu_information[7], 0, 1, 1); + memset(expecteds, 1, sizeof(unsigned int) * 4); + memset(&expecteds[4], 0, sizeof(unsigned int) * 4); + // -- Run + for (unsigned int i = 0; i < 8; i++) { + results[i] = is_duplicate(&cpu_information[i], map, nb_core); + } + // -- Verification + TEST_ARRAY(TEST_BOOL, 8, results, expecteds); }) -- GitLab From a0b7dafae59bbbecb53dac6976c350cb77e3c739 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 12:15:20 +0000 Subject: [PATCH 103/125] fix: init_amd_rapl --- src/amd_rapl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 0c363af..888df5a 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -314,7 +314,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - if (is_duplicate(cpu_information, cpu_map, nb_core) == 1) { + if (is_duplicate(&cpu_information[i], cpu_map, nb_core) == 1) { init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); sensor_count += 1; } -- GitLab From f05faa31487b1c86ae104331a02e157e0410a3db Mon Sep 17 00:00:00 2001 From: Floreal Risso <frisso@grue-2.nancy.grid5000.fr> Date: Mon, 6 Feb 2023 13:54:44 +0100 Subject: [PATCH 104/125] fix is_duplicate --- src/amd_rapl.c | 11 ++++++----- tests/amd_rapl.c | 36 ++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 888df5a..805e698 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -248,12 +248,12 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) +unsigned int is_duplicate(cpu_sensor_t *sensor,unsigned int nb_core, unsigned int nb_package, unsigned char map[nb_core][nb_package]) { - if (map[sensor->core_id * nb_core + sensor->package_id]) { + if (map[sensor->core_id][sensor->package_id] == 1) { return 0; } - map[sensor->core_id * nb_core + sensor->package_id] += 1; + map[sensor->core_id][sensor->package_id] += 1; return 1; } @@ -309,12 +309,13 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int nb_core; get_arch(&nb_package, &nb_core, cpu_information, max_cpus); - unsigned char *cpu_map = (unsigned char *) calloc(nb_core * nb_package, sizeof(unsigned char)); + unsigned char cpu_map[nb_core][nb_package]; + memset(cpu_map, 0, sizeof(cpu_map)); cpu_sensor_t *sensors = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - if (is_duplicate(&cpu_information[i], cpu_map, nb_core) == 1) { + if (is_duplicate(&cpu_information[i], nb_core, nb_package, cpu_map) == 1) { init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); sensor_count += 1; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index f2d13ef..09ac0d9 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -198,82 +198,82 @@ TFUNCTION(test_is_duplicate, { static const unsigned int nb_package = 2; static const unsigned int max_cpu = 10; - unsigned char map[nb_core * nb_package]; + unsigned char map[nb_core][nb_package]; cpu_sensor_t cpu_information[max_cpu]; unsigned int results[max_cpu]; unsigned int expecteds[max_cpu]; // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); expecteds[0] = 1; expecteds[1] = 0; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[0], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package,map); + results[1] = is_duplicate(&cpu_information[0], nb_core, nb_package,map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 1, 1); expecteds[0] = 1; expecteds[1] = 0; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 0, 0); expecteds[0] = 1; expecteds[1] = 1; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 1, 0); expecteds[0] = 1; expecteds[1] = 1; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); expecteds[0] = 1; expecteds[1] = 1; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 0, 0); DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); @@ -287,7 +287,7 @@ TFUNCTION(test_is_duplicate, { memset(&expecteds[4], 0, sizeof(unsigned int) * 4); // -- Run for (unsigned int i = 0; i < 8; i++) { - results[i] = is_duplicate(&cpu_information[i], map, nb_core); + results[i] = is_duplicate(&cpu_information[i], nb_core, nb_package, map ); } // -- Verification TEST_ARRAY(TEST_BOOL, 8, results, expecteds); -- GitLab From 60dee1581ae9b8b5e15fbe6f8428b9f72d4c4fe5 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 16:39:07 +0000 Subject: [PATCH 105/125] fix: add ifndef --- src/info_reader.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/info_reader.h b/src/info_reader.h index 1696ede..e83b2c3 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -1,3 +1,26 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + +#ifndef _INFO_READER_H +#define _INFO_READER_ + #include <string.h> #include <stdbool.h> #include <stdio.h> @@ -216,3 +239,5 @@ static bool start_with(const char *prefix, const char *string) } } +#endif + -- GitLab From d68b9ca54bae21fce331367b6195517b541eb01c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 16:49:39 +0000 Subject: [PATCH 106/125] fix: add safety --- doc/test_file_ex.c | 4 ++-- tests/small_test.h | 24 +++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 4e3a093..13e1f48 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -63,10 +63,10 @@ int usertype_compare(void *ptr1, void *ptr2) return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; } -char *usertype_format(char buffer[1000], void *ptr) +char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UserType *x = (UserType *) ptr; - sprintf(buffer, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); + snprintf(buffer, FMT_BUFFER_SIZE, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); return buffer; } diff --git a/tests/small_test.h b/tests/small_test.h index ef9d90b..eddbdb0 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -29,6 +29,8 @@ #include "../src/util.h" +#define FMT_BUFFER_SIZE 1000 + // ---------------------------API_INTERFACE /** * @brief Define the entry point of the tests @@ -276,7 +278,7 @@ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); typedef int (Comparator) (void *, void *); -typedef char *(Formatter) (char *, void *); +typedef char *(Formatter) (char[FMT_BUFFER_SIZE], void *); typedef struct { Comparator *compare; @@ -299,7 +301,7 @@ int str_compare(void *ptr1, void *ptr2) } } -char *str_format(char *buffer, void *ptr) +char *str_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UNUSED(buffer); static char *str_null = "NULL"; @@ -321,7 +323,7 @@ int bool_compare(void *ptr1, void *ptr2) return *bool1 == *bool2; } -char *bool_format(char *buffer, void *ptr) +char *bool_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UNUSED(buffer); bool *_bool = (bool *) ptr; @@ -342,10 +344,10 @@ int int_compare(void *ptr1, void *ptr2) return *int1 == *int2; } -char *int_format(char buffer[1000], void *ptr) +char *int_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { int *_int = (int *) ptr; - snprintf(buffer, 1000, "%d", *_int); + snprintf(buffer, FMT_BUFFER_SIZE, "%d", *_int); return buffer; } @@ -361,9 +363,9 @@ int ptr_compare(void *ptr1, void *ptr2) return ptr1 == ptr2; } -char *ptr_format(char *buffer, void *ptr) +char *ptr_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { - sprintf(buffer, "%p", ptr); + snprintf(buffer, FMT_BUFFER_SIZE, "%p", ptr); return buffer; } @@ -381,10 +383,10 @@ int u64_compare(void *ptr1, void *ptr2) return *v1 == *v2; } -char *u64_format(char *buffer, void *ptr) +char *u64_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { uint64_t *v = (uint64_t *) ptr; - sprintf(buffer, "%"PRIu64"", *v); + snprintf(buffer, FMT_BUFFER_SIZE, "%"PRIu64"", *v); return buffer; } @@ -398,8 +400,8 @@ static const TestInterface u64_interface = { int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) { __indentation_level += 1; - static char buffer_result[1000]; - static char buffer_expected[1000]; + static char buffer_result[FMT_BUFFER_SIZE]; + static char buffer_expected[FMT_BUFFER_SIZE]; int is_equal = interface->compare(result, expected); char *fmt_result = interface->format(buffer_expected, expected); -- GitLab From 864213f5cfb7b9bfb3baedc31f572aa94baaac9c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 07:55:33 +0000 Subject: [PATCH 107/125] fix: documentation --- doc/test_file_ex.c | 93 +++++++++++++++-------- doc/test_main_ex.c | 3 +- tests/amd_rapl.c | 26 +++++-- tests/small_test.h | 183 +++++++++++++++++++-------------------------- 4 files changed, 163 insertions(+), 142 deletions(-) diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 13e1f48..95baaa7 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -20,49 +20,70 @@ // Include of the test library #include "./../tests/small_test.h" +// Include the file that contains the function you want to test +// #include "a_file.c" -// -- A simple function that should pass +// This example is divided into three parts: +// 1. SOME SIMPLE EXAMPLES +// 2. A MORE COMPLEX EXAMPLE +// 3. FILE ENTRY POINT + +// -----------------1. SOME SIMPLE EXAMPLES + +// A simple function that should pass +// test_should_pass is the name of the function +// {} is the function code +// Use one of the define TEST_XXX defined in small_test.h TFUNCTION(test_should_pass, { - char *result = "It's going to pass"; - char *expected = "It's going to pass"; - TEST_STR(result, expected); + int result = 42; + int expected = 42; + TEST_INT(&result, &expected); }) -// -- A simple function that should fail +// A simple function that should pass +// test_should_fail is the name of the function +// {} is the function code +// Use one of the define TEST_XXX defined in small_test.h TFUNCTION(test_should_fail, { char *result = "a fail"; char *expected = "a nice fail"; TEST_STR(result, expected); }) -// -- A simple test of array +// A simple test on an array +// test_array is the name of the function +// {} is the function code +// Use one of the define TEST_XXX defined in small_test.h TFUNCTION(test_array, { static unsigned int size = 10; - int array[10]; - TEST_ARRAY(TEST_INT, size, array, array); + int results[10] = {0}; + int expecteds[10] = {0}; + for (unsigned int i = 0; i < size; i++) { + TEST_INT(&results[i], &expecteds[i]); + } }) -// -- A simple test of array of pointer -TFUNCTION(test_ptr_array, { - static unsigned int size = 10; - void *array[10]; - TEST_PTR_ARRAY(TEST_PTR, size, array, array); -}) +// See "TFILE_ENTRY_POINT" for how to call these functions. -// -- Add a new type in the test framework +// ------------2. THE MORE COMPLEX EXAMPLE +// This example shows how to add a new type to the framework +// The type that you want to add : typedef struct { int simple_int; char simple_str[20]; } UserType; -// -- Implemet the interface +// The test framework needs two functions : + +// A function that compares two values. int usertype_compare(void *ptr1, void *ptr2) { return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; } +// A function to format a value. char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UserType *x = (UserType *) ptr; @@ -70,17 +91,18 @@ char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) return buffer; } -// Create a variable which contains the functions +// Store the functions in the interface type. static const TestInterface usertype_interface = { .compare = usertype_compare, .format = usertype_format }; -// -- Create the test macro to call +// Create a macro that implements the interface by passing the interface created to the TEST_INTERFACE macro. #define TEST_USER_TYPE(__result, __expected) \ - TEST_INTERFACE(__result, __expected, &usertype_interface); + TEST_INTERFACE(__result, __expected, &usertype_interface) -// -- Create a macro setter + +// Creating a constructor is recommended (C can have problems parsing macros where "," is used). #define DUMMY_USER_TYPE(__user, __simple_int, __simple_str) \ do { \ __user = (UserType) { \ @@ -89,19 +111,22 @@ static const TestInterface usertype_interface = { }; \ } while (0); -// -- Compare two usertype +// Now you can write test for your new type +// all you have to do is call the macro that implements "TEST_INTERFACE". +// here it's "TEST_USERTYPE" TFUNCTION(test_user_type, { - UserType x1; - UserType x2; + UserType result; + UserType expected; - DUMMY_USER_TYPE(x1, 1, "John Doe"); - DUMMY_USER_TYPE(x2, 1, "John Doe"); + DUMMY_USER_TYPE(result, 1, "John Doe"); + DUMMY_USER_TYPE(expected, 1, "John Doe"); - TEST_USER_TYPE(&x1, &x2); + TEST_USER_TYPE(&result, &expected); }) - -// -- Compare an array of usetype +// Now you can write test for your new type +// all you have to do is call the macro that implements "TEST_INTERFACE". +// here it's "TEST_USERTYPE" TFUNCTION(test_array_user_type, { UserType results[1]; UserType expecteds[1]; @@ -109,15 +134,23 @@ TFUNCTION(test_array_user_type, { DUMMY_USER_TYPE(results[0], 1, "John Doe"); DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - TEST_ARRAY(TEST_USER_TYPE, 1, results, expecteds); + for (unsigned int i = 0; i < 1; i++) { + TEST_USER_TYPE(&results[i], &expecteds[i]); + } }) +// ---------------------3. FILE ENTRY POINT + // Define the entry point of a test file +// Use the macro "CALL_TFUNCTION" where the name of a function is defined with the macro "TFUNCTION". TFILE_ENTRY_POINT(test_file_ex, { + // Call the simple examples CALL_TFUNCTION(test_should_pass); CALL_TFUNCTION(test_should_fail); CALL_TFUNCTION(test_array); - CALL_TFUNCTION(test_ptr_array); + + // Call the more complex example CALL_TFUNCTION(test_user_type); CALL_TFUNCTION(test_array_user_type); }) + diff --git a/doc/test_main_ex.c b/doc/test_main_ex.c index 0aa86b9..a5e7841 100644 --- a/doc/test_main_ex.c +++ b/doc/test_main_ex.c @@ -22,7 +22,7 @@ // Include of the test library #include "./../tests/small_test.h" -// Include the *.c files that contain the tests +// Include the *.c files containing the tests #include "./test_file_ex.c" // #include "./test_another_test_file.c" @@ -33,3 +33,4 @@ TMAIN({ CALL_TFUNCTION(test_file_ex); // CALL_TFUNCTION(another_file_entry_point_function); }) + diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 09ac0d9..0485099 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -142,7 +142,10 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); + for(unsigned int i = 0; i < nb; i++) + { + TEST_STR(results[i], expecteds[i]); + } // Test 2: // -- Setup @@ -159,8 +162,10 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); - + for(unsigned int i = 0; i < nb; i++) + { + TEST_STR(results[i], expecteds[i]); + } // Test 3: // -- Setup nb = 4; @@ -176,7 +181,10 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); + for(unsigned int i = 0; i < nb; i++) + { + TEST_STR(results[i], expecteds[i]); + } }) @@ -271,7 +279,7 @@ TFUNCTION(test_is_duplicate, { // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); - + // -- Setup memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); @@ -286,11 +294,15 @@ TFUNCTION(test_is_duplicate, { memset(expecteds, 1, sizeof(unsigned int) * 4); memset(&expecteds[4], 0, sizeof(unsigned int) * 4); // -- Run - for (unsigned int i = 0; i < 8; i++) { + for (unsigned int i = 0; i < 8; i++) + { results[i] = is_duplicate(&cpu_information[i], nb_core, nb_package, map ); } // -- Verification - TEST_ARRAY(TEST_BOOL, 8, results, expecteds); + for(unsigned int i = 0; i < 8; i++) + { + TEST_BOOL(&results[i], &expecteds[i]); + } }) diff --git a/tests/small_test.h b/tests/small_test.h index eddbdb0..abae768 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -33,10 +33,10 @@ // ---------------------------API_INTERFACE /** - * @brief Define the entry point of the tests - * It initializes each useful variables. + * @brief Define the entry point for the tests. + * It initialises any useful variables and acts as the main one. * - * @param __code The code that contains the calls to the test functions + * @param __code The code that contains the calls to the test functions. */ #define TMAIN(__code) \ @@ -46,22 +46,24 @@ INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ unsigned int __error_counter__ = 0; \ do __code while (0); \ - DEFERRED_FILE_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } /** + * @def TFILE_ENTRY_POINT(__filename, __code) + * * @brief Define the entry point of a test file. * This macro is used to define the entry point of a test file. * It defines a function with the specified __filename that contains the test code specified in code. * - * When the function is called, it initializes the test file using the INIT_TEST_FILE macro, + * When the function is called, it initialises the test file using the INIT_TEST_FILE macro, * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. * The function returns the value of __error_counter__, * which indicates the number of errors encountered during the tests. * - * @param __filename The name of the function that serves as the entry point for the test file. + * @param __filename The name of the function to be used as an entry point for the test file. * @param __code The test code to be executed in the function. */ #define TFILE_ENTRY_POINT(__filename, __code) \ @@ -70,16 +72,18 @@ INIT_TEST_FILE(); \ int __error_counter__ = 0; \ do __code while(0); \ - DEFERRED_FILE_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } /** + * @def TFUNCTION(__function_name, __code) + * * @brief Define a test function within a test file. * This macro is used to define a test function within a test file. - * It defines a function with the specified function_name that contains the test code specified in code. + * It defines a function with the given __function_name containing the test code specified in __code. * - * When the function is called, it initializes the test function using the INIT_TEST_FUNCTION macro, + * When the function is called, it initialises the test function using the INIT_TEST_FUNCTION macro, * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. * The function returns the value of __error_counter__, which indicates the number of errors encountered during the tests. @@ -93,28 +97,32 @@ INIT_TEST_FUNCTION(); \ int __error_counter__ = 0; \ do __code while(0); \ - DEFERRED_FUNCTION_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } /** + * @def CALL_TFUNCTION(__function_name) + * * @brief Call a test function within a test file. * This macro is used to call a test function within a test file. - * It calls the function specified by function_name and adds the return value to the __error_counter__ variable. + * It calls the function specified by __function_name and adds the return value to the __error_counter__ variable. * This allows multiple test functions to be executed and their error count to be accumulated. * - * @param function_name The name of the test function to be called. + * @param __function_name The name of the test function to be called. */ -#define CALL_TFUNCTION(function_name) \ - do {__error_counter__ += function_name(__indentation_level + 1);} while(0) +#define CALL_TFUNCTION(__function_name) \ + do {__error_counter__ += __function_name(__indentation_level + 1);} while(0) /** - * @def TEST_STR(result, expected) + * @def TEST_STR(__result, __expected) + * * @brief Test strings - * This macro is used to test strings. It takes two arguments: `__result`, which is the string to be tested, and `__expected`, which is the expected value of the string. + * This macro is used to test strings. It takes two arguments: `__result`, which is the string to test, and `__expected`, + * which is the expected value of the string. * - * @param __result the string to be tested - * @param __expected the expected value of the string + * @param __result the string to test. + * @param __expected the expected value of the string. * * @code * TEST_STR("Hello", "Hello"); @@ -125,15 +133,17 @@ /** * @def TEST_BOOL(__result, __expected) + * * @brief Test bools - * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to be tested, and `__expected`, which is the expected value of the bool. + * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to test, and `__expected`, + * which is the expected value of the bool. * - * @param __result the pointer to bool to be tested - * @param __expected the pointer to the expected value of the bool + * @param __result the pointer to bool to test. + * @param __expected the pointer to the expected value of the bool. * * @code * bool x = true; - * bool y = false; + * bool y = true; * TEST_BOOL(&x, &y); * @endcode */ @@ -142,11 +152,13 @@ /** * @def TEST_INT(__result, __expected) + * * @brief Test ints - * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be tested, and `__expected`, which is the expected value of the int. + * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be test, and `__expected`, + * which is the expected value of the int. * - * @param __result the pointer to int to be tested - * @param __expected the pointer to expected value of the int + * @param __result the pointer to int to test. + * @param __expected the pointer to expected value of the int. * * @code * int x = 1; @@ -157,16 +169,15 @@ #define TEST_INT(__result, __expected) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &int_interface);} while (0) - - - /** * @def TEST_PTR(__result, __expected) + * * @brief Test pointers - * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to be tested, and `__expected`, which is the expected value of the pointer. + * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to test, and `__expected`, + * which is the expected value of the pointer. * - * @param __result the pointer to be tested - * @param __expected the expected value of the pointer + * @param __result the pointer to test. + * @param __expected the expected value of the pointer. * * @code * int x = 5; @@ -180,11 +191,13 @@ /** * @def TEST_UINT64_T(__result, __expected) + * * @brief Test 64-bit unsigned integers - * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, which is the integer to be tested, and `__expected`, which is the expected value of the integer. + * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, + * which is the integer to test, and `__expected`, which is the expected value of the integer. * - * @param __result the pointer to integer to be tested - * @param __expected the pointer to expected value of the integer + * @param __result the pointer to integer to test. + * @param __expected the pointer to expected value of the integer. * * @code * uint64_t x = 5; @@ -197,64 +210,28 @@ /** * @def TEST_INTERFACE(__result, __expected, __interface) - * @brief Define a macro on a usertype with the given __interface + * + * @brief Define a macro on a usertype with the given __interface. * This macro is used by the user to define a new test macro on a usertype. * * @param __result * @param __expected - * @param __interface the usertype interface + * @param __interface the interface of the usertype. * * @code - * #define TEST_USERTYPE(__result, __expected) - * TEST_INTERFACE(__result, __expected, usertype_interface) + * TestInterface usertype_interface = {.compare = ..., .format = ...}; + * #define TEST_USERTYPE(__result, __expected) \ + * TEST_INTERFACE(__result, __expected, &usertype_interface) * @endcode */ #define TEST_INTERFACE(__result, __expected, __interface) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) -/** - * @def TEST_T_ARRAY(__test_macro, __size, __results, __expecteds) - * @brief Test arrays of data - * The macro uses a for loop to iterate through the array and apply the test function to each element. - * - * @param __test_macro the test function to be used on each element of the array - * @param __array_size the number of elements in the array - * @param __results the array of elements to be tested - * @param __expecteds the array of expected values - - * @code - * int results[3] = {1, 2, 3}; - * int expecteds[3] = {1, 2, 3}; - * TEST_ARRAY(TEST_INT, 3, results, expecteds); - * @endcode -*/ -#define TEST_ARRAY(__test_macro, __array_size, __results, __expecteds) \ - for (unsigned i = 0; i < __array_size; i++) { \ - __test_macro(&__results[i], &__expecteds[i]); \ - } -/** - * @def TEST_T_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) - * @brief Test arrays of pointer - * The macro uses a for loop to iterate through the array and apply the test function to each element. - * - * @param __test_macro the test function to be used on each element of the array - * @param __array_size the number of elements in the array - * @param __results the array of elements to be tested - * @param __expecteds the array of expected values - * @code - * void* array[3]; - * TEST_PTR_ARRAY(TEST_PTR, 3, array, array); - * @endcode -*/ -#define TEST_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) \ - for (unsigned int i = 0; i < __array_size; i++) { \ - __test_macro(__results[i], __expecteds[i]); \ - } -// --------------------------------API_CODE -// These functions should not be used, only use the previous macros. +// ------------------------------------CODE +// These functions should not be in use, only the previous macros should be in use. #define INDENTED_PRINT(__fmt, ...) \ do { \ @@ -271,10 +248,7 @@ #define INIT_TEST_FUNCTION() \ INDENTED_PRINT("%s()\n", __func__); -#define DEFERRED_FILE_ERROR(nb_error) \ - INDENTED_PRINT("|_Deferred Error : %u\n",nb_error); - -#define DEFERRED_FUNCTION_ERROR(nb_error) \ +#define DEFERRED_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); typedef int (Comparator) (void *, void *); @@ -285,8 +259,26 @@ typedef struct { Formatter *format; } TestInterface; -// ---------------------------str_interface +// ---------------------------TEST FUNCTION + +int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) +{ + __indentation_level += 1; + static char buffer_result[FMT_BUFFER_SIZE]; + static char buffer_expected[FMT_BUFFER_SIZE]; + int is_equal = interface->compare(result, expected); + + char *fmt_result = interface->format(buffer_expected, expected); + char *fmt_expected = interface->format(buffer_result, result); + if (!is_equal) { + INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); + } + return !is_equal; +} + +// ------------------------------INTERFACES +// -- str_interface int str_compare(void *ptr1, void *ptr2) { char *str1 = (char *) ptr1; @@ -314,7 +306,7 @@ static const TestInterface str_interface = { .format = str_format }; -// --------------------------bool_interface +// -- bool_interface int bool_compare(void *ptr1, void *ptr2) { @@ -335,7 +327,7 @@ static const TestInterface bool_interface = { .format = bool_format }; -// ---------------------------int_interface +// -- int_interface int int_compare(void *ptr1, void *ptr2) { @@ -356,7 +348,7 @@ static const TestInterface int_interface = { .format = int_format }; -// ---------------------------ptr_interface +// -- ptr_interface int ptr_compare(void *ptr1, void *ptr2) { @@ -374,7 +366,7 @@ static const TestInterface ptr_interface = { .format = ptr_format }; -// ---------------------------u64_interface +// -- u64_interface int u64_compare(void *ptr1, void *ptr2) { @@ -395,22 +387,5 @@ static const TestInterface u64_interface = { .format = u64_format }; -// ---------------------------test_function - -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) -{ - __indentation_level += 1; - static char buffer_result[FMT_BUFFER_SIZE]; - static char buffer_expected[FMT_BUFFER_SIZE]; - int is_equal = interface->compare(result, expected); - - char *fmt_result = interface->format(buffer_expected, expected); - char *fmt_expected = interface->format(buffer_result, result); - if (!is_equal) { - INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); - } - return !is_equal; -} - #endif -- GitLab From 7c42bf0b1a5816d231182b8f5ba5e6394252188d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 07:58:49 +0000 Subject: [PATCH 108/125] format --- doc/test_file_ex.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 95baaa7..0595e9a 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -20,7 +20,7 @@ // Include of the test library #include "./../tests/small_test.h" -// Include the file that contains the function you want to test +// Include the file that contains the function you want to test // #include "a_file.c" // This example is divided into three parts: @@ -58,7 +58,8 @@ TFUNCTION(test_array, { static unsigned int size = 10; int results[10] = {0}; int expecteds[10] = {0}; - for (unsigned int i = 0; i < size; i++) { + for (unsigned int i = 0; i < size; i++) + { TEST_INT(&results[i], &expecteds[i]); } }) @@ -134,7 +135,8 @@ TFUNCTION(test_array_user_type, { DUMMY_USER_TYPE(results[0], 1, "John Doe"); DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - for (unsigned int i = 0; i < 1; i++) { + for (unsigned int i = 0; i < 1; i++) + { TEST_USER_TYPE(&results[i], &expecteds[i]); } }) -- GitLab From dae6da3cbd9951709bb3a2a4a294b13bc1224ea1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 07:59:19 +0000 Subject: [PATCH 109/125] fix: use a const --- src/load.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/load.c b/src/load.c index 6dcf2b0..1c049ce 100644 --- a/src/load.c +++ b/src/load.c @@ -26,11 +26,12 @@ #include "util.h" #define LOAD_BUFFER_SIZE 1024 +#define LOAD_VALUES_SIZE 10 char buffer[LOAD_BUFFER_SIZE]; static int load_fid = -1; -static uint64_t load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static uint64_t tmp_load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static uint64_t load_values[LOAD_VALUES_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static uint64_t tmp_load_values[LOAD_VALUES_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static char *stat = "/proc/stat"; void _get_load(uint64_t *results) @@ -46,8 +47,8 @@ void _get_load(uint64_t *results) pos++; } - for (int i = 0; i < 10; i++) { - results[i] = strtoull(buffer + pos, NULL, 10); + for (int i = 0; i < LOAD_VALUES_SIZE; i++) { + results[i] = strtoull(buffer + pos, NULL, LOAD_VALUES_SIZE); while (buffer[pos] <= '9' && buffer[pos] >= '0') { pos++; @@ -71,7 +72,7 @@ unsigned int init_load(char *argument, void **state) } _get_load(load_values); - return 10; + return LOAD_VALUES_SIZE; } unsigned int get_load(uint64_t *results, void *state) @@ -79,12 +80,12 @@ unsigned int get_load(uint64_t *results, void *state) UNUSED(state); _get_load(tmp_load_values); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < LOAD_VALUES_SIZE; i++) { results[i] = tmp_load_values[i] - load_values[i]; } memcpy(load_values, tmp_load_values, sizeof(load_values)); - return 10; + return LOAD_VALUES_SIZE; } void clean_load(void *state) @@ -93,14 +94,15 @@ void clean_load(void *state) close(load_fid); } -char *_labels[10] = {"user", "nice", "system", "idle", "iowait", "irq", - "softirq", "steal", "guest", "guest_nice" - }; +char *_labels[LOAD_VALUES_SIZE] = { + "user", "nice", "system", "idle", "iowait", "irq", + "softirq", "steal", "guest", "guest_nice" +}; void label_load(char **labels, void *none) { UNUSED(none); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < LOAD_VALUES_SIZE; i++) { labels[i] = _labels[i]; } } -- GitLab From 189f9fc703b62d4ccfe7233bd0ee3271d696ceb0 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:17:33 +0000 Subject: [PATCH 110/125] cleanup --- doc/info_reader_ex.c | 54 ++++++++++++++++++++++++++++++-------------- src/info_reader.h | 8 +++---- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index f672d98..2e76251 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -23,8 +23,8 @@ #include "./../src/info_reader.h" #define MAX_PROCS 64 -#define NB_KEYS 6 +// -----------------------------The storage typedef struct { unsigned int processor; char *vendor_id; @@ -34,12 +34,16 @@ typedef struct { char *model_name; } Cpu; +// --------------IMPLEMENTING THE INTERFACE + +// -- Define the behaviour if the attempted value is an int GenericPointer int_allocator(char *s) { unsigned int value = atoi(s); return (GenericPointer) value; } +// -- Define the behaviour if the attempted value is a string GenericPointer string_allocator(char *s) { char *value = malloc(strlen(s) + 1); @@ -47,31 +51,42 @@ GenericPointer string_allocator(char *s) return (GenericPointer) value; } +// -- Define the processor setter void set_processor(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->processor = data; } + +// -- Define the vendor_id setter void set_vendor_id(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->vendor_id = (char *) data; } + +// -- Define the family setter void set_family(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->family = data; } + +// -- Define the core_id setter void set_core_id(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->core_id = data; } + +// -- Define the physical_id setter void set_physical_id(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->physical_id = data; } + +// -- Define the model_name setter void set_model_name(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; @@ -81,28 +96,33 @@ void set_model_name(GenericPointer storage, GenericPointer data) int main() { Cpu cpus[MAX_PROCS]; + + // -- Define the setter, the allocator for each key / separator. KeyFinder keys[] = { - {"processor", ": ", (CopyAllocator *) int_allocator, (Setter *)set_processor}, - {"vendor_id", ": ", (CopyAllocator *) string_allocator, (Setter *)set_vendor_id}, - {"cpu family", ": ", (CopyAllocator *) int_allocator, (Setter *)set_family}, - {"core id", ": ", (CopyAllocator *) int_allocator, (Setter *)set_core_id}, - {"physical id", ": ", (CopyAllocator *) int_allocator,(Setter *)set_physical_id}, - { - "model name", ": ", (CopyAllocator *) string_allocator, - (Setter *)set_model_name - } + {.key = "processor", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_processor}, + {.key = "vendor_id", .delimiter = ": ", .copy = (CopyAllocator *) string_allocator, .set = (Setter *)set_vendor_id}, + {.key = "cpu family", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_family}, + {.key = "core id", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_core_id}, + {.key = "physical id", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_physical_id}, + {.key = "model name", .delimiter = ": ", .copy = (CopyAllocator *) string_allocator, .set = (Setter *)set_model_name} }; - Parser parser = {.storage = (GenericPointer) cpus, - .capacity = MAX_PROCS, - .storage_struct_size = sizeof(Cpu), - .keys = keys, - .nb_keys = NB_KEYS, - .file = fopen("/proc/cpuinfo", "r") - }; + size_t nb_keys = sizeof(keys)/sizeof(KeyFinder); + + // -- Init the parser + Parser parser = { + .storage = (GenericPointer) cpus, + .capacity = MAX_PROCS, + .storage_struct_size = sizeof(Cpu), + .keys = keys, + .nb_keys = nb_keys, + .file = fopen("/proc/cpuinfo", "r") + }; + // -- Parse the file parse(&parser); + // Print and free the results for (unsigned int i = 0; i < parser.nb_stored; ++i) { printf("========== PROC[%d] ==========\n", i); printf("Processor: %u\n", cpus[i].processor); diff --git a/src/info_reader.h b/src/info_reader.h index e83b2c3..0d694d3 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -96,10 +96,10 @@ static bool start_with(const char *prefix, const char *string); /** * @brief Matches a line of text to a key in the parser's list of keys. * - * @param parser Pointer to the Parser struct. - * @param line Line of text to match. - * @param key_finder Pointer to a KeyFinder pointer where the matched key will be stored. - * @param raw_value Pointer to a char pointer where the value associated with the matched key will be stored. + * @param[in] parser Pointer to the Parser struct. + * @param[in] line Line of text to match. + * @param[out] key_finder Pointer to a KeyFinder pointer where the matched key will be stored. + * @param[out] raw_value Pointer to a char pointer where the value associated with the matched key will be stored. * * @return Returns 1 if a key is matched, 0 otherwise. */ -- GitLab From 0c9216eda1457ada2805f1cdf023c26dbfd2aeed Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:25:30 +0000 Subject: [PATCH 111/125] format --- tests/small_test.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index abae768..bf0ca10 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -39,15 +39,15 @@ * @param __code The code that contains the calls to the test functions. */ -#define TMAIN(__code) \ - int main() \ -{ \ - unsigned int __indentation_level = 0; \ - INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ - unsigned int __error_counter__ = 0; \ - do __code while (0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ +#define TMAIN(__code) \ + int main() \ +{ \ + unsigned int __indentation_level = 0; \ + INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ + unsigned int __error_counter__ = 0; \ + do __code while (0); \ + DEFERRED_ERROR(__error_counter__); \ + return __error_counter__; \ } /** @@ -72,7 +72,7 @@ INIT_TEST_FILE(); \ int __error_counter__ = 0; \ do __code while(0); \ - DEFERRED_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } @@ -91,14 +91,14 @@ * @param __function_name The name of the test function. * @param __code The test code to be executed in the function. */ -#define TFUNCTION(__function_name, __code) \ +#define TFUNCTION(__function_name, __code) \ int __function_name(unsigned int __indentation_level) \ -{ \ - INIT_TEST_FUNCTION(); \ - int __error_counter__ = 0; \ - do __code while(0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ +{ \ + INIT_TEST_FUNCTION(); \ + int __error_counter__ = 0; \ + do __code while(0); \ + DEFERRED_ERROR(__error_counter__); \ + return __error_counter__; \ } /** @@ -236,13 +236,13 @@ #define INDENTED_PRINT(__fmt, ...) \ do { \ for(unsigned int i = 0; i < __indentation_level; i++) { \ - printf("| "); \ + printf("| "); \ } \ printf(__fmt, ##__VA_ARGS__); \ } while(0) -#define INIT_TEST_FILE() \ +#define INIT_TEST_FILE() \ INDENTED_PRINT("%s:%s\n", __FILE__, __func__) #define INIT_TEST_FUNCTION() \ -- GitLab From 971ab6da9ffc4fcb071df8ff7e50e1ed0f3cd743 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:26:24 +0000 Subject: [PATCH 112/125] doc --- tests/small_test.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/small_test.h b/tests/small_test.h index bf0ca10..66c4de9 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -33,6 +33,8 @@ // ---------------------------API_INTERFACE /** + * @def TMAIN(__code) + * * @brief Define the entry point for the tests. * It initialises any useful variables and acts as the main one. * -- GitLab From 644f97f5df56c63f9b5c0260e447c6bc2c599350 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:35:54 +0000 Subject: [PATCH 113/125] fix: header --- src/info_reader.h | 2 +- tests/info_reader.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/info_reader.h b/src/info_reader.h index 0d694d3..ec28db6 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -19,7 +19,7 @@ *******************************************************/ #ifndef _INFO_READER_H -#define _INFO_READER_ +#define _INFO_READER_H #include <string.h> #include <stdbool.h> diff --git a/tests/info_reader.c b/tests/info_reader.c index b2a8c6f..19d9c0a 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -19,6 +19,7 @@ *******************************************************/ #include "small_test.h" +#include "./../src/info_reader.h" TFUNCTION(test_replace_first, { // useful variables : -- GitLab From 10d6b8c4c1cffff4f52dca798cd6d7cba8eee1ee Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 7 Feb 2023 14:11:24 +0100 Subject: [PATCH 114/125] fix sensor example (doc) plus add build instructions (in doc/counter_ex.c) --- doc/counter_ex.c | 95 +++++++++++++++++++++++++++++++++++++++++++----- doc/counter_ex.h | 4 +- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/doc/counter_ex.c b/doc/counter_ex.c index 0dc6f29..e0d7023 100644 --- a/doc/counter_ex.c +++ b/doc/counter_ex.c @@ -1,26 +1,103 @@ +/* + * compilation: + * + +# normally, this part is done with `configure.sh`, but here we need to +# do this manually +cat <<EOF > src/sensors.h #include "counter_ex.h" -static int acc; +#define NB_SENSOR 1 +#define NB_SENSOR_OPT 1 + +void init_sensors(Optparse *opts, Sensor *sensors, size_t len, size_t offset, int *nb_defined) +{ + int opt_idx = offset; + for (int i = 0; i < counter_ex.nb_opt; i++) { + opts[opt_idx++] = counter_ex_opt[i]; + } + sensors[(*nb_defined)++] = counter_ex; + assert((offset + *nb_defined) <= len); +} +EOF + +# idem +echo 'CAPTOR_OBJ = doc/counters_ex.o' > sensors.mk + +# actual compilation here +gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/counter_ex.c -o obj/counter_ex.o +gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/util.c -o obj/util.o +gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/mojitos.c -o obj/mojitos.o +gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og obj/util.o obj/mojitos.o obj/counter_ex.o -o bin/mojitos -unsigned int init_acc(char *a, void **b) + * +**/ + +#include <stdint.h> +#include <stdlib.h> + +#include "util.h" + +#define NB_SENSOR 3 + +struct accumulator_t { + int v[NB_SENSOR]; +}; + +void _get_acc(int v[NB_SENSOR]) { - acc = 0; + for (int i = 0; i < NB_SENSOR; i++) { + v[i]++; + } } -unsigned int get_acc(uint64_t *results, void *none) +unsigned int init_acc(char *none, void **ptr) { + /* "none" refers to an optionnal command-line argument */ + /* there is none in this case, so this parameter is not used */ UNUSED(none); - return a++; + + struct accumulator_t *state = malloc(sizeof(struct accumulator_t)); + + for (int i = 0; i < NB_SENSOR; i++) { + state->v[i] = -1; + } + + *ptr = (void *)state; + _get_acc(state->v); + + return NB_SENSOR; +} + +unsigned int get_acc(uint64_t *results, void *ptr) +{ + struct accumulator_t *state = (struct accumulator_t *)ptr; + + _get_acc(state->v); + + for (int i = 0; i < NB_SENSOR; i++) { + results[i] = state->v[i]; + } + + return NB_SENSOR; } +char *_labels_accumulator[NB_SENSOR] = {"acc1", "acc2", "acc3"}; void label_acc(char **labels, void *none) { UNUSED(none); - labels[0] = "acc"; + for (int i = 0; i < NB_SENSOR; i++) { + labels[i] = _labels_accumulator[i]; + } } -void clean_acc(void *none) +void clean_acc(void *ptr) { - /* That's a no-op for this example */ - UNUSED(none); + struct accumulator_t *state = (struct accumulator_t *)ptr; + + if (state == NULL) { + return; + } + + free(state); } diff --git a/doc/counter_ex.h b/doc/counter_ex.h index 65fabf3..8d798fc 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -7,7 +7,7 @@ unsigned int get_acc(uint64_t *results, void *); void clean_acc(void *); void label_acc(char **labels, void *); -Sensor rapl = { +Sensor counter_ex = { .init = init_acc, .get = get_acc, .clean = clean_acc, @@ -15,7 +15,7 @@ Sensor rapl = { .nb_opt = 1, }; -Optparse rapl_opt[1] = { +Optparse counter_ex_opt[1] = { { .longname = "accumulator", .shortname = 'a', -- GitLab From 1aa72c5c628ab3b24718596e27792b1d6fddacc1 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 7 Feb 2023 14:15:49 +0100 Subject: [PATCH 115/125] rename counter_ex to sensor_ex --- doc/{counter_ex.c => sensor_ex.c} | 14 +++++++------- doc/{counter_ex.h => sensor_ex.h} | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) rename doc/{counter_ex.c => sensor_ex.c} (86%) rename doc/{counter_ex.h => sensor_ex.h} (83%) diff --git a/doc/counter_ex.c b/doc/sensor_ex.c similarity index 86% rename from doc/counter_ex.c rename to doc/sensor_ex.c index e0d7023..6b10076 100644 --- a/doc/counter_ex.c +++ b/doc/sensor_ex.c @@ -5,7 +5,7 @@ # normally, this part is done with `configure.sh`, but here we need to # do this manually cat <<EOF > src/sensors.h -#include "counter_ex.h" +#include "sensor_ex.h" #define NB_SENSOR 1 #define NB_SENSOR_OPT 1 @@ -13,22 +13,22 @@ cat <<EOF > src/sensors.h void init_sensors(Optparse *opts, Sensor *sensors, size_t len, size_t offset, int *nb_defined) { int opt_idx = offset; - for (int i = 0; i < counter_ex.nb_opt; i++) { - opts[opt_idx++] = counter_ex_opt[i]; + for (int i = 0; i < sensor_ex.nb_opt; i++) { + opts[opt_idx++] = sensor_ex_opt[i]; } - sensors[(*nb_defined)++] = counter_ex; + sensors[(*nb_defined)++] = sensor_ex; assert((offset + *nb_defined) <= len); } EOF # idem -echo 'CAPTOR_OBJ = doc/counters_ex.o' > sensors.mk +echo 'CAPTOR_OBJ = doc/sensor_ex.o' > sensors.mk # actual compilation here -gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/counter_ex.c -o obj/counter_ex.o +gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/sensor_ex.c -o obj/sensor_ex.o gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/util.c -o obj/util.o gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og -c doc/mojitos.c -o obj/mojitos.o -gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og obj/util.o obj/mojitos.o obj/counter_ex.o -o bin/mojitos +gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og obj/util.o obj/mojitos.o obj/sensor_ex.o -o bin/mojitos * **/ diff --git a/doc/counter_ex.h b/doc/sensor_ex.h similarity index 83% rename from doc/counter_ex.h rename to doc/sensor_ex.h index 8d798fc..a040558 100644 --- a/doc/counter_ex.h +++ b/doc/sensor_ex.h @@ -1,5 +1,5 @@ /* - * Example of a basic counter: an accumulator + * Example of a basic sensor: an accumulator **/ unsigned int init_acc(char *, void **); @@ -7,7 +7,7 @@ unsigned int get_acc(uint64_t *results, void *); void clean_acc(void *); void label_acc(char **labels, void *); -Sensor counter_ex = { +Sensor sensor_ex = { .init = init_acc, .get = get_acc, .clean = clean_acc, @@ -15,7 +15,7 @@ Sensor counter_ex = { .nb_opt = 1, }; -Optparse counter_ex_opt[1] = { +Optparse sensor_ex_opt[1] = { { .longname = "accumulator", .shortname = 'a', -- GitLab From 4510bf4f56001a8cc1b97d3cc898d857c494b946 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 14:08:42 +0000 Subject: [PATCH 116/125] fix: make tests --- tests/info_reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/info_reader.c b/tests/info_reader.c index 19d9c0a..5000f48 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -19,7 +19,7 @@ *******************************************************/ #include "small_test.h" -#include "./../src/info_reader.h" +#include "./../lib/info_reader.h" TFUNCTION(test_replace_first, { // useful variables : -- GitLab From cb334bb6906bdf513dfc09b635565e5832db09ab Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 13:26:09 +0000 Subject: [PATCH 117/125] update Copyright date --- configure.sh | 3 +++ doc/sensor_ex.c | 20 ++++++++++++++++++++ doc/sensor_ex.h | 20 ++++++++++++++++++++ src/counters.c | 2 +- src/counters.h | 2 +- src/counters_option.sh | 2 +- src/infiniband.c | 2 +- src/infiniband.h | 2 +- src/load.c | 2 +- src/load.h | 2 +- src/mojitos.c | 3 +-- src/network.c | 2 +- src/network.h | 2 +- src/temperature.c | 2 +- src/temperature.h | 2 +- src/util.h | 2 +- tools/update-readme-usage.sh | 3 +++ 17 files changed, 59 insertions(+), 14 deletions(-) diff --git a/configure.sh b/configure.sh index 62f297a..196aaf8 100755 --- a/configure.sh +++ b/configure.sh @@ -1,5 +1,8 @@ #!/bin/sh +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + try() { "$@" || die "cannot $*"; } die() { yell "$*"; exit 111; } yell() { echo "$0: $*" >&2; } diff --git a/doc/sensor_ex.c b/doc/sensor_ex.c index 6b10076..d37cbeb 100644 --- a/doc/sensor_ex.c +++ b/doc/sensor_ex.c @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + /* * compilation: * diff --git a/doc/sensor_ex.h b/doc/sensor_ex.h index a040558..9fd95d3 100644 --- a/doc/sensor_ex.h +++ b/doc/sensor_ex.h @@ -1,3 +1,23 @@ +/******************************************************* + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + /* * Example of a basic sensor: an accumulator **/ diff --git a/src/counters.c b/src/counters.c index d42ceae..1a7027e 100644 --- a/src/counters.c +++ b/src/counters.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/counters.h b/src/counters.h index 0304a07..4374cd1 100644 --- a/src/counters.h +++ b/src/counters.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/counters_option.sh b/src/counters_option.sh index 7c99eba..38cee08 100644 --- a/src/counters_option.sh +++ b/src/counters_option.sh @@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> +# Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> linux_include=/usr/include/linux/perf_event.h diff --git a/src/infiniband.c b/src/infiniband.c index 303795e..2314e1d 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/infiniband.h b/src/infiniband.h index fac05f8..e30d78b 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/load.c b/src/load.c index 1c049ce..64502e5 100644 --- a/src/load.c +++ b/src/load.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2019-2021 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2019-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/load.h b/src/load.h index 038b263..6d8d298 100644 --- a/src/load.h +++ b/src/load.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/mojitos.c b/src/mojitos.c index 3ecf111..4274b6a 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -1,6 +1,5 @@ /******************************************************* - - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/network.c b/src/network.c index 543a053..74d8bb9 100644 --- a/src/network.c +++ b/src/network.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/network.h b/src/network.h index 994651a..a158dbb 100644 --- a/src/network.h +++ b/src/network.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2019 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/temperature.c b/src/temperature.c index acc0702..bcddb22 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/temperature.h b/src/temperature.h index 8609dba..e70554d 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2018-2021 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/util.h b/src/util.h index 23978c1..e422d07 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/tools/update-readme-usage.sh b/tools/update-readme-usage.sh index b9f16de..ad2f88f 100755 --- a/tools/update-readme-usage.sh +++ b/tools/update-readme-usage.sh @@ -1,5 +1,8 @@ #!/bin/sh +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + die() { yell "$*"; exit 111; } try() { "$@" || die "cannot $*"; } yell() { echo "$0: $*" >&2; } -- GitLab From 285d4169ca478de59203f7dc70365d0c55028e7e Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 13:42:53 +0000 Subject: [PATCH 118/125] update option --- README.md | 2 +- src/amd_rapl.h | 2 +- src/rapl.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 10f5aaf..fddb2b1 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ SENSORS: system load -d|--net-dev <net_dev> network monitoring (if network_device is X, tries to detect it automatically) --r|--rapl +-r|--intel-rapl RAPL -c|--cpu-temp processor temperature diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 1a16db8..e58cc16 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -34,7 +34,7 @@ Sensor amd_rapl = { Optparse amd_rapl_opt[1] = { { .longname = "amd-rapl", - .shortname = 'a', + .shortname = 'r', .argtype = OPTPARSE_NONE, .usage_arg = NULL, .usage_msg = "AMD RAPL", diff --git a/src/rapl.h b/src/rapl.h index a02624d..7720f07 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -33,11 +33,11 @@ Sensor rapl = { Optparse rapl_opt[1] = { { - .longname = "rapl", + .longname = "intel-rapl", .shortname = 'r', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "RAPL", + .usage_msg = "INTEL RAPL", }, }; -- GitLab From bed45ca8c3fbc4c2b54590427c4e28ffc17dd684 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 14:19:14 +0000 Subject: [PATCH 119/125] standardise the names of structures --- README.md | 2 +- doc/info_reader_ex.c | 2 +- doc/sensor_ex.c | 9 ++++---- src/amd_rapl.c | 52 +++++++++++++++++++++--------------------- src/counters.c | 22 +++++++++--------- src/counters_option.sh | 6 ++--- src/infiniband.c | 6 +++-- src/network.c | 9 ++++---- src/rapl.c | 16 ++++++------- src/temperature.c | 13 ++++++----- tests/amd_rapl.c | 26 ++++++++++----------- 11 files changed, 84 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index fddb2b1..95b6d7e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ SENSORS: -d|--net-dev <net_dev> network monitoring (if network_device is X, tries to detect it automatically) -r|--intel-rapl - RAPL + INTEL RAPL -c|--cpu-temp processor temperature ``` diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 2e76251..f1e6d96 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -20,7 +20,7 @@ // ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex -#include "./../src/info_reader.h" +#include "./../lib/info_reader.h" #define MAX_PROCS 64 diff --git a/doc/sensor_ex.c b/doc/sensor_ex.c index d37cbeb..5fc8eeb 100644 --- a/doc/sensor_ex.c +++ b/doc/sensor_ex.c @@ -60,9 +60,10 @@ gcc -std=gnu99 -Wall -Wpedantic -I./lib -I./doc -I./src -g -Og obj/util.o obj/mo #define NB_SENSOR 3 -struct accumulator_t { +struct Accumulator { int v[NB_SENSOR]; }; +typedef struct Accumulator Accumulator; void _get_acc(int v[NB_SENSOR]) { @@ -77,7 +78,7 @@ unsigned int init_acc(char *none, void **ptr) /* there is none in this case, so this parameter is not used */ UNUSED(none); - struct accumulator_t *state = malloc(sizeof(struct accumulator_t)); + Accumulator *state = malloc(sizeof(Accumulator)); for (int i = 0; i < NB_SENSOR; i++) { state->v[i] = -1; @@ -91,7 +92,7 @@ unsigned int init_acc(char *none, void **ptr) unsigned int get_acc(uint64_t *results, void *ptr) { - struct accumulator_t *state = (struct accumulator_t *)ptr; + Accumulator *state = (Accumulator *)ptr; _get_acc(state->v); @@ -113,7 +114,7 @@ void label_acc(char **labels, void *none) void clean_acc(void *ptr) { - struct accumulator_t *state = (struct accumulator_t *)ptr; + Accumulator *state = (Accumulator *)ptr; if (state == NULL) { return; diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 805e698..34ccb47 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -41,7 +41,7 @@ static const uint64_t energy_core_msr = 0xC001029A; // ------------------------------FILE_PATHS static const char *base_str = "/dev/cpu/%d/msr"; -struct cpu_sensor_t { +struct CpuSensor { unsigned int cpu_id; unsigned int package_id; unsigned int core_id; @@ -52,13 +52,13 @@ struct cpu_sensor_t { unsigned int energy_units; uint64_t core_energy; }; -typedef struct cpu_sensor_t cpu_sensor_t; +typedef struct CpuSensor CpuSensor; -struct _amd_rapl_t { - cpu_sensor_t *sensors; +struct AmdRapl { + CpuSensor *sensors; unsigned int sensor_count; }; -typedef struct _amd_rapl_t _amd_rapl_t; +typedef struct AmdRapl AmdRapl; // -----------------------------INFO_READER @@ -75,19 +75,19 @@ static GenericPointer uint_allocator(char *s) static void _set_cpu_id(GenericPointer storage, GenericPointer data) { - cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + CpuSensor *cpu = (CpuSensor *) storage; cpu->cpu_id = (unsigned int) data; } static void _set_package_id(GenericPointer storage, GenericPointer data) { - cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + CpuSensor *cpu = (CpuSensor *) storage; cpu->package_id = (unsigned int) data; } static void _set_core_id(GenericPointer storage, GenericPointer data) { - cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + CpuSensor *cpu = (CpuSensor *) storage; cpu->core_id = (unsigned int) data; } @@ -98,13 +98,13 @@ static KeyFinder keys[NB_KEYS] = { }; -static unsigned int parse_cpuinfo(cpu_sensor_t *storage, unsigned int capacity) +static unsigned int parse_cpuinfo(CpuSensor *storage, unsigned int capacity) { Parser parser = { .storage = (GenericPointer) storage, .nb_stored = 0, .capacity = capacity, - .storage_struct_size = sizeof(cpu_sensor_t), + .storage_struct_size = sizeof(CpuSensor), .keys = keys, .nb_keys = NB_KEYS, .file = fopen(cpuinfo, "r") @@ -171,9 +171,9 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) // -----------------------------------DEBUG #ifdef DEBUG -void debug_print_sensor(cpu_sensor_t *sensor) +void debug_print_sensor(CpuSensor *sensor) { - //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); + //CASSERT(sizeof(CpuSensor) == 56, amd_rapl_c); printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", sensor->cpu_id, sensor->package_id, @@ -185,7 +185,7 @@ void debug_print_sensor(cpu_sensor_t *sensor) ); } -void debug_print_amd_rapl(_amd_rapl_t *rapl) +void debug_print_amd_rapl(AmdRapl *rapl) { for (unsigned int i = 0; i < rapl->sensor_count; i++) { debug_print_sensor(&rapl->sensors[i]); @@ -213,7 +213,7 @@ unsigned int get_nb_cpu() return n_cpu; } -void get_arch(unsigned int *ret_nb_package, unsigned int *ret_nb_core, cpu_sensor_t *sensors, unsigned int nb_sensor) +void get_arch(unsigned int *ret_nb_package, unsigned int *ret_nb_core, CpuSensor *sensors, unsigned int nb_sensor) { unsigned int nb_package = 0; unsigned int nb_core = 0; @@ -238,7 +238,7 @@ char *get_name(unsigned int cpu_id) return name; } -void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) +void update_cpu_sensor(CpuSensor *sensor, uint64_t *energy_consumed) { sensor->energy_units = read_unit(sensor->fd); uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); @@ -248,7 +248,7 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int is_duplicate(cpu_sensor_t *sensor,unsigned int nb_core, unsigned int nb_package, unsigned char map[nb_core][nb_package]) +unsigned int is_duplicate(CpuSensor *sensor,unsigned int nb_core, unsigned int nb_package, unsigned char map[nb_core][nb_package]) { if (map[sensor->core_id][sensor->package_id] == 1) { return 0; @@ -257,7 +257,7 @@ unsigned int is_duplicate(cpu_sensor_t *sensor,unsigned int nb_core, unsigned in return 1; } -void init_cpu_sensor(cpu_sensor_t *sensor, cpu_sensor_t *cpu_info) +void init_cpu_sensor(CpuSensor *sensor, CpuSensor *cpu_info) { static char filename[BUFFER_SIZE]; snprintf(filename,BUFFER_SIZE, base_str, cpu_info->cpu_id); @@ -269,18 +269,18 @@ void init_cpu_sensor(cpu_sensor_t *sensor, cpu_sensor_t *cpu_info) exit(127); } - memcpy(sensor, cpu_info, sizeof(cpu_sensor_t)); + memcpy(sensor, cpu_info, sizeof(CpuSensor)); sensor->name = get_name(sensor->cpu_id); sensor->fd = fd; } -void clean_cpu_sensor(cpu_sensor_t *sensor) +void clean_cpu_sensor(CpuSensor *sensor) { close(sensor->fd); free(sensor->name); } -void free_amd_rapl(_amd_rapl_t *rapl) +void free_amd_rapl(AmdRapl *rapl) { free(rapl->sensors); free(rapl); @@ -299,7 +299,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) exit(127); } - cpu_sensor_t *cpu_information = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); + CpuSensor *cpu_information = (CpuSensor *) calloc(max_cpus, sizeof(CpuSensor)); if (parse_cpuinfo(cpu_information, max_cpus)) { free(cpu_information); PANIC(1, "cpuinfo"); @@ -311,7 +311,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned char cpu_map[nb_core][nb_package]; memset(cpu_map, 0, sizeof(cpu_map)); - cpu_sensor_t *sensors = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); + CpuSensor *sensors = (CpuSensor *) calloc(max_cpus, sizeof(CpuSensor)); unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { @@ -322,7 +322,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) } free(cpu_information); - _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); + AmdRapl *rapl = (AmdRapl *) calloc(1, sizeof(AmdRapl)); rapl->sensors = sensors; rapl->sensor_count = sensor_count; *ptr = (void *) rapl; @@ -332,7 +332,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int get_amd_rapl(uint64_t *results, void *ptr) { - _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; + AmdRapl *rapl = (AmdRapl *) ptr; for (unsigned int i = 0; i < rapl->sensor_count; i++) { update_cpu_sensor(&rapl->sensors[i], &results[i]); } @@ -341,7 +341,7 @@ unsigned int get_amd_rapl(uint64_t *results, void *ptr) void label_amd_rapl(char **labels, void *ptr) { - _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; + AmdRapl *rapl = (AmdRapl *) ptr; for (unsigned int i = 0; i < rapl->sensor_count; i++) { labels[i] = rapl->sensors[i].name; } @@ -349,7 +349,7 @@ void label_amd_rapl(char **labels, void *ptr) void clean_amd_rapl(void *ptr) { - _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; + AmdRapl *rapl = (AmdRapl *) ptr; for (unsigned int i = 0; i < rapl->sensor_count; ++i) { clean_cpu_sensor(&rapl->sensors[i]); diff --git a/src/counters.c b/src/counters.c index 1a7027e..e809f88 100644 --- a/src/counters.c +++ b/src/counters.c @@ -30,7 +30,7 @@ #include "util.h" -struct _counter_t { +struct Counter { int nbcores; int nbperf; int **counters; @@ -40,7 +40,7 @@ struct _counter_t { int *perf_indexes; }; -typedef struct _counter_t *counter_t; +typedef struct Counter Counter; #include "counters_option.h" @@ -105,7 +105,7 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, return res; } -counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *names) +Counter *_init_counters(const int nb_perf, const __u32 *types, const __u64 *names) { struct perf_event_attr pe; unsigned int nbcores = sysconf(_SC_NPROCESSORS_ONLN); @@ -113,7 +113,7 @@ counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *nam pe.size = sizeof(struct perf_event_attr); pe.disabled = 1; - counter_t counters = malloc(sizeof(struct _counter_t)); + Counter *counters = malloc(sizeof(struct Counter)); counters->nbperf = nb_perf; counters->nbcores = nbcores; counters->counters = malloc(nb_perf * sizeof(int *)); @@ -133,7 +133,7 @@ counter_t _init_counters(const int nb_perf, const __u32 *types, const __u64 *nam void clean_counters(void *ptr) { - counter_t counters = (counter_t) ptr; + Counter *counters = (Counter *) ptr; for (int counter = 0; counter < counters->nbperf; counter++) { for (int core = 0; core < counters->nbcores; core++) { @@ -151,7 +151,7 @@ void clean_counters(void *ptr) free(counters); } -void start_counters(counter_t counters) +void start_counters(Counter *counters) { for (int counter = 0; counter < counters->nbperf; counter++) { for (int core = 0; core < counters->nbcores; core++) { @@ -160,7 +160,7 @@ void start_counters(counter_t counters) } } -void reset_counters(counter_t counters) +void reset_counters(Counter *counters) { for (int counter = 0; counter < counters->nbperf; counter++) { for (int core = 0; core < counters->nbcores; core++) { @@ -169,7 +169,7 @@ void reset_counters(counter_t counters) } } -void _get_counters(counter_t counters, uint64_t *values) +void _get_counters(Counter *counters, uint64_t *values) { for (int i = 0; i < counters->nbperf; i++) { uint64_t accu = 0; @@ -202,7 +202,7 @@ unsigned int init_counters(char *args, void **state) __u32 *perf_type; __u64 *perf_key; perf_type_key(&perf_type, &perf_key, perf_indexes, nb_perf); - counter_t fd = _init_counters(nb_perf, perf_type, perf_key); + Counter *fd = _init_counters(nb_perf, perf_type, perf_key); free(perf_type); free(perf_key); @@ -218,7 +218,7 @@ unsigned int init_counters(char *args, void **state) unsigned int get_counters(uint64_t *results, void *ptr) { - counter_t state = (counter_t) ptr; + Counter *state = (Counter *) ptr; _get_counters(state, state->tmp_counters_values); @@ -232,7 +232,7 @@ unsigned int get_counters(uint64_t *results, void *ptr) void label_counters(char **labels, void *ptr) { - counter_t state = (counter_t) ptr; + Counter *state = (Counter *) ptr; for (int i = 0; i < state->nbperf; i++) { labels[i] = perf_static_info[state->perf_indexes[i]].name; diff --git a/src/counters_option.sh b/src/counters_option.sh index 38cee08..76f9275 100644 --- a/src/counters_option.sh +++ b/src/counters_option.sh @@ -6,13 +6,13 @@ linux_include=/usr/include/linux/perf_event.h echo ' -typedef struct counter_option { +typedef struct CounterOption{ char *name; __u32 perf_type; __u64 perf_key; -} counter_option; +} CounterOption; -static counter_option perf_static_info[] = {' +static CounterOption perf_static_info[] = {' nb=0 diff --git a/src/infiniband.c b/src/infiniband.c index 2314e1d..bbc0fee 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -27,11 +27,13 @@ #define NB_SENSOR 4 -struct network_t { +struct Network { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; }; +typedef struct Network Network; + unsigned int _get_network(uint64_t *results, int *sources); @@ -60,7 +62,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) "%s/port_xmit_data" }; - struct network_t *state = malloc(sizeof(struct network_t)); + Network *state = malloc(sizeof(Network)); char buffer[1024]; for (int i = 0; i < NB_SENSOR; i++) { diff --git a/src/network.c b/src/network.c index 74d8bb9..d361d47 100644 --- a/src/network.c +++ b/src/network.c @@ -28,11 +28,12 @@ #define NB_SENSOR 4 static char *route = "/proc/net/route"; -struct network_t { +struct Network { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; }; +typedef struct Network Network; unsigned int _get_network(uint64_t *results, int *sources) { @@ -92,7 +93,7 @@ unsigned int init_network(char *dev, void **ptr) "/sys/class/net/%s/statistics/tx_bytes" }; - struct network_t *state = malloc(sizeof(struct network_t)); + Network *state = malloc(sizeof(Network)); char buffer2[256]; for (int i = 0; i < NB_SENSOR; i++) { @@ -108,7 +109,7 @@ unsigned int init_network(char *dev, void **ptr) unsigned int get_network(uint64_t *results, void *ptr) { - struct network_t *state = (struct network_t *) ptr; + Network *state = (Network *) ptr; _get_network(state->tmp_values, state->sources); for (int i = 0; i < NB_SENSOR; i++) { @@ -121,7 +122,7 @@ unsigned int get_network(uint64_t *results, void *ptr) void clean_network(void *ptr) { - struct network_t *state = (struct network_t *) ptr; + Network *state = (Network *) ptr; if (state == NULL) { return; diff --git a/src/rapl.c b/src/rapl.c index 8a04d31..5d7eca7 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -52,7 +52,7 @@ void test_append(char *name, int i) } -struct _rapl_t { +struct IntelRapl { unsigned int nb; char **names; int *fids; @@ -60,10 +60,10 @@ struct _rapl_t { uint64_t *tmp_values; }; -typedef struct _rapl_t _rapl_t; +typedef struct IntelRapl IntelRapl; -void add_rapl_source(_rapl_t *rapl, char *name, char *energy_uj) +void add_rapl_source(IntelRapl *rapl, char *name, char *energy_uj) { rapl->nb += 1; rapl->names = realloc(rapl->names, sizeof(char **)*rapl->nb); @@ -85,7 +85,7 @@ void add_rapl_source(_rapl_t *rapl, char *name, char *energy_uj) } -void _get_rapl(uint64_t *values, _rapl_t *rapl) +void _get_rapl(uint64_t *values, IntelRapl *rapl) { static char buffer[512]; @@ -104,7 +104,7 @@ void _get_rapl(uint64_t *values, _rapl_t *rapl) unsigned int init_rapl(char *none, void **ptr) { UNUSED(none); - _rapl_t *rapl = malloc(sizeof(_rapl_t)); + IntelRapl *rapl = malloc(sizeof(IntelRapl)); rapl->nb = 0; rapl->names = NULL; rapl->fids = NULL; @@ -161,7 +161,7 @@ unsigned int init_rapl(char *none, void **ptr) unsigned int get_rapl(uint64_t *results, void *ptr) { - _rapl_t *state = (_rapl_t *) ptr; + IntelRapl *state = (IntelRapl *) ptr; _get_rapl(state->tmp_values, state); for (unsigned int i = 0; i < state->nb; i++) { @@ -174,7 +174,7 @@ unsigned int get_rapl(uint64_t *results, void *ptr) void clean_rapl(void *ptr) { - _rapl_t *rapl = (_rapl_t *) ptr; + IntelRapl *rapl = (IntelRapl *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { free(rapl->names[i]); @@ -191,7 +191,7 @@ void clean_rapl(void *ptr) void label_rapl(char **labels, void *ptr) { - _rapl_t *rapl = (_rapl_t *) ptr; + IntelRapl *rapl = (IntelRapl *) ptr; for (unsigned int i = 0; i < rapl->nb; i++) { labels[i] = rapl->names[i]; diff --git a/src/temperature.c b/src/temperature.c index bcddb22..a9cf74b 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -26,11 +26,12 @@ #include <stdint.h> #include "util.h" -struct temperature_t { +struct Temperature { char **label_list; int *fid_list; int nb_elem; }; +typedef struct Temperature Temperature; int get_string(char *filename, char *buffer, int max_size) { @@ -61,7 +62,7 @@ void add_to_list(char ***list_name, char *source, int nb_elem) } -void add_temperature_sensor(int id_rep, struct temperature_t *state) +void add_temperature_sensor(int id_rep, Temperature *state) { static int key = 0; static char buffer_filename[512]; @@ -109,7 +110,7 @@ void add_temperature_sensor(int id_rep, struct temperature_t *state) unsigned int init_temperature(char *args, void **ptr) { UNUSED(args); - struct temperature_t *state = malloc(sizeof(struct temperature_t)); + Temperature *state = malloc(sizeof(Temperature)); state->nb_elem = 0; state->label_list = NULL; state->fid_list = NULL; @@ -136,7 +137,7 @@ unsigned int init_temperature(char *args, void **ptr) unsigned int get_temperature(uint64_t *results, void *ptr) { - struct temperature_t *state = (struct temperature_t *)ptr; + Temperature *state = (Temperature *)ptr; static char buffer[512]; for (int i = 0; i < state->nb_elem; i++) { @@ -152,7 +153,7 @@ unsigned int get_temperature(uint64_t *results, void *ptr) void clean_temperature(void *ptr) { - struct temperature_t *state = (struct temperature_t *)ptr; + Temperature *state = (Temperature *)ptr; for (int i = 0; i < state->nb_elem; i++) { free(state->label_list[i]); @@ -166,7 +167,7 @@ void clean_temperature(void *ptr) void label_temperature(char **labels, void *ptr) { - struct temperature_t *state = (struct temperature_t *)ptr; + Temperature *state = (Temperature *)ptr; for (int i = 0; i < state->nb_elem; i++) { labels[i] = state->label_list[i]; diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 0485099..7c05ab5 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -107,7 +107,7 @@ TFUNCTION(test_get_name, { #define NONE 0 #define DUMMY_SENSOR(__sensor, __cpu_id, __name) \ do { \ - __sensor = (cpu_sensor_t) { \ + __sensor = (CpuSensor) { \ .cpu_id = __cpu_id, \ .package_id = NONE, \ .core_id = NONE, \ @@ -120,15 +120,15 @@ do { \ #define DUMMY_RAPL(__rapl, __sensors, __sensors_count) \ do { \ - __rapl = (_amd_rapl_t) { \ + __rapl = (AmdRapl) { \ .sensors = __sensors, \ .sensor_count = __sensors_count \ }; \ } while(0); TFUNCTION(test_label_amd_rapl, { - cpu_sensor_t sensors[100]; - _amd_rapl_t rapl; + CpuSensor sensors[100]; + AmdRapl rapl; char *results[100]; char expecteds[10][100]; uint64_t nb = 0; @@ -190,7 +190,7 @@ TFUNCTION(test_label_amd_rapl, { #define DUMMY_CPUINFO(__sensor, __cpu_id, __package_id, __core_id) \ do { \ - __sensor = (cpu_sensor_t) { \ + __sensor = (CpuSensor) { \ .cpu_id = __cpu_id, \ .package_id = __package_id, \ .core_id = __core_id, \ @@ -207,13 +207,13 @@ TFUNCTION(test_is_duplicate, { static const unsigned int max_cpu = 10; unsigned char map[nb_core][nb_package]; - cpu_sensor_t cpu_information[max_cpu]; + CpuSensor cpu_information[max_cpu]; unsigned int results[max_cpu]; unsigned int expecteds[max_cpu]; // -- Setup memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); expecteds[0] = 1; expecteds[1] = 0; @@ -226,7 +226,7 @@ TFUNCTION(test_is_duplicate, { // -- Setup memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 1, 1); expecteds[0] = 1; @@ -240,7 +240,7 @@ TFUNCTION(test_is_duplicate, { // -- Setup memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 0, 0); expecteds[0] = 1; @@ -254,7 +254,7 @@ TFUNCTION(test_is_duplicate, { // -- Setup memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 1, 0); expecteds[0] = 1; @@ -268,7 +268,7 @@ TFUNCTION(test_is_duplicate, { // -- Setup memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); expecteds[0] = 1; @@ -282,7 +282,7 @@ TFUNCTION(test_is_duplicate, { // -- Setup memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 0, 0); DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); DUMMY_CPUINFO(cpu_information[2], 0, 1, 0); @@ -317,7 +317,7 @@ TFILE_ENTRY_POINT(test_amd_rapl, { int main() { static const unsigned int time = 10; - _amd_rapl_t *rapl = NULL; + AmdRapl *rapl = NULL; unsigned int count_cpu = init_amd_rapl(NULL, (void **) &rapl); uint64_t results[count_cpu]; char *labels[count_cpu]; -- GitLab From 5bea42ec1eac091535f61c68fbfac721408905f1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 14:46:28 +0000 Subject: [PATCH 120/125] sprintf -> snprintf --- src/amd_rapl.c | 3 ++- src/counters.c | 2 +- src/infiniband.c | 2 +- src/network.c | 2 +- src/rapl.c | 35 +++++++++++++++-------------------- src/temperature.c | 22 ++++++++++++---------- 6 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 34ccb47..1e08517 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -161,6 +161,7 @@ uint64_t raw_to_microjoule(uint64_t raw, unsigned int unit) // Joule * 1000000 -> uJoule return (uint64_t) (((double) raw * to_microjoule) / (double)(1U << unit)); } + uint64_t raw_to_joule(uint64_t raw, uint64_t unit) { // raw * (1 / (unit^2)) -> Joule @@ -202,7 +203,7 @@ unsigned int get_nb_cpu() unsigned int n_cpu = 0; for (;; n_cpu++) { - sprintf(filename, base_str, n_cpu); + snprintf(filename, BUFFER_SIZE, base_str, n_cpu); int fd = open(filename, O_RDONLY); if (fd < 0) { diff --git a/src/counters.c b/src/counters.c index e809f88..8013ff8 100644 --- a/src/counters.c +++ b/src/counters.c @@ -52,7 +52,7 @@ void *show_all_counters(void *none1, size_t none2) UNUSED(none1); UNUSED(none2); exit(EXIT_SUCCESS); - return NULL; /* not reached */ + return NULL; /* not reached */ } void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) diff --git a/src/infiniband.c b/src/infiniband.c index bbc0fee..aa4a8de 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -66,7 +66,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) char buffer[1024]; for (int i = 0; i < NB_SENSOR; i++) { - sprintf(buffer, filenames[i], infi_path); + snprintf(buffer, 1024, filenames[i], infi_path); state->sources[i] = open(buffer, O_RDONLY); } diff --git a/src/network.c b/src/network.c index d361d47..977b92e 100644 --- a/src/network.c +++ b/src/network.c @@ -97,7 +97,7 @@ unsigned int init_network(char *dev, void **ptr) char buffer2[256]; for (int i = 0; i < NB_SENSOR; i++) { - sprintf(buffer2, filenames[i], dev); + sprintf(buffer2, 256, filenames[i], dev); state->sources[i] = open(buffer2, O_RDONLY); } diff --git a/src/rapl.c b/src/rapl.c index 5d7eca7..eb88553 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -28,6 +28,7 @@ #include "util.h" #define MAX_HEADER 128 +#define BUFFER_SIZE 1024 char *get_rapl_string(const char *filename) { @@ -40,15 +41,16 @@ char *get_rapl_string(const char *filename) int nb = read(fd, result, MAX_HEADER); close(fd); result[nb - 1] = 0; - return (result); + return result; } -void test_append(char *name, int i) +void append(char *name, int i, size_t buffer_size) { - //char last = name[strlen(name)-1]; - //if (last>='0' && last <= '9') - // return; - sprintf(name + strlen(name), "%d", i); + size_t name_len = strlen(name); + char* ptr = name + name_len; + + size_t remaining_space = buffer_size - name_len; + snprintf(ptr, remaining_space, "%d", i); } @@ -109,40 +111,33 @@ unsigned int init_rapl(char *none, void **ptr) rapl->names = NULL; rapl->fids = NULL; - char buffer[1024]; + char buffer[BUFFER_SIZE]; char *name_base = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/%s"; char *name_sub = "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:%d/intel-rapl:%d:%d/%s"; for (unsigned int i = 0;; i++) { - sprintf(buffer, name_base, i, "name"); + snprintf(buffer, BUFFER_SIZE, name_base, i, "name"); char *tmp = get_rapl_string(buffer); if (tmp == NULL) { break; } - //printf("%s\n", tmp); - test_append(tmp, i); - //printf("%s -> %s\n", buffer, tmp); - - sprintf(buffer, name_base, i, "energy_uj"); + append(tmp, i, MAX_HEADER); + snprintf(buffer, BUFFER_SIZE, name_base, i, "energy_uj"); add_rapl_source(rapl, tmp, buffer); free(tmp); for (unsigned int j = 0;; j++) { - sprintf(buffer, name_sub, i, i, j, "name"); + snprintf(buffer, BUFFER_SIZE, name_sub, i, i, j, "name"); char *tmp_sub = get_rapl_string(buffer); if (tmp_sub == NULL) { break; } - //printf("%s\n", tmp_sub); - test_append(tmp_sub, i); - //printf("%s -> %s\n", buffer, tmp_sub); - - - sprintf(buffer, name_sub, i, i, j, "energy_uj"); + append(tmp_sub, i, MAX_HEADER); + snprintf(buffer, BUFFER_SIZE, name_sub, i, i, j, "energy_uj"); add_rapl_source(rapl, tmp_sub, buffer); free(tmp_sub); diff --git a/src/temperature.c b/src/temperature.c index a9cf74b..1dc1099 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -26,6 +26,8 @@ #include <stdint.h> #include "util.h" +#define BUFFER_SIZE 512 + struct Temperature { char **label_list; int *fid_list; @@ -65,13 +67,13 @@ void add_to_list(char ***list_name, char *source, int nb_elem) void add_temperature_sensor(int id_rep, Temperature *state) { static int key = 0; - static char buffer_filename[512]; - static char buffer_label[512]; + static char buffer_filename[BUFFER_SIZE]; + static char buffer_label[BUFFER_SIZE]; - int delta = sprintf(buffer_label, "Temp_%d_", key); + int delta = snprintf(buffer_label, BUFFER_SIZE, "Temp_%d_", key); for (int i = 1;; i++) { - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); + snprintf(buffer_filename, BUFFER_SIZE, "/sys/class/hwmon/hwmon%d/temp%d_label", id_rep, i); if (get_string(buffer_filename, buffer_label + delta, 100) == -1) { break; @@ -89,7 +91,7 @@ void add_temperature_sensor(int id_rep, Temperature *state) add_to_list(&state->label_list, buffer_label, state->nb_elem); - sprintf(buffer_filename, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); + snprintf(buffer_filename, BUFFER_SIZE, "/sys/class/hwmon/hwmon%d/temp%d_input", id_rep, i); state->fid_list = realloc(state->fid_list, (state->nb_elem + 1) * sizeof(int)); int fd = open(buffer_filename, O_RDONLY); @@ -116,11 +118,11 @@ unsigned int init_temperature(char *args, void **ptr) state->fid_list = NULL; char base_name[] = "/sys/class/hwmon/hwmon%d/name"; - static char name[512]; - static char buffer[512]; + static char name[BUFFER_SIZE]; + static char buffer[BUFFER_SIZE]; int i = 0; - sprintf(name, base_name, i); + snprintf(name, BUFFER_SIZE, base_name, i); while (get_string(name, buffer, 8) != -1) { if (strcmp(buffer, "coretemp") == 0) { @@ -128,7 +130,7 @@ unsigned int init_temperature(char *args, void **ptr) } i++; - sprintf(name, base_name, i); + snprintf(name, BUFFER_SIZE, base_name, i); } *ptr = (void *) state; @@ -138,7 +140,7 @@ unsigned int init_temperature(char *args, void **ptr) unsigned int get_temperature(uint64_t *results, void *ptr) { Temperature *state = (Temperature *)ptr; - static char buffer[512]; + static char buffer[BUFFER_SIZE]; for (int i = 0; i < state->nb_elem; i++) { if (pread(state->fid_list[i], buffer, 100, 0) < 0) { -- GitLab From b48e884b7ed6955647877134b5629036383c6879 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 15:05:13 +0000 Subject: [PATCH 121/125] format --- src/network.c | 2 +- src/rapl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network.c b/src/network.c index 977b92e..37d2373 100644 --- a/src/network.c +++ b/src/network.c @@ -97,7 +97,7 @@ unsigned int init_network(char *dev, void **ptr) char buffer2[256]; for (int i = 0; i < NB_SENSOR; i++) { - sprintf(buffer2, 256, filenames[i], dev); + snprintf(buffer2, 256, filenames[i], dev); state->sources[i] = open(buffer2, O_RDONLY); } diff --git a/src/rapl.c b/src/rapl.c index eb88553..3d13367 100644 --- a/src/rapl.c +++ b/src/rapl.c @@ -47,7 +47,7 @@ char *get_rapl_string(const char *filename) void append(char *name, int i, size_t buffer_size) { size_t name_len = strlen(name); - char* ptr = name + name_len; + char *ptr = name + name_len; size_t remaining_space = buffer_size - name_len; snprintf(ptr, remaining_space, "%d", i); -- GitLab From eae0b09492c7c7442a8c0d4bf241747f32789b53 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 15:06:47 +0000 Subject: [PATCH 122/125] add authors --- AUTHORS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 0bfc663..13ddd11 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,4 @@ -Georges Da Costa georges.da-costa@irit.fr \ No newline at end of file +Georges Da Costa georges.da-costa@irit.fr +Floréal Risso floreal.risso@univ-tlse3.fr +Alexis Paronnaud alexis.paronnaud@univ-tlse3.fr +Téo Tinarrage teo.tinarrage@univ-tlse3.fr -- GitLab From 290c3cfe5e58877f121c1e3050d29064a740d907 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 15:11:11 +0000 Subject: [PATCH 123/125] clear doc --- makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 950028c..646a015 100644 --- a/makefile +++ b/makefile @@ -62,7 +62,9 @@ format: clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \ $(SRC_DIR)/counters_option.h \ - $(TESTS_DIR)/run + $(TESTS_DIR)/run \ + $(DOC_DIR)/test_main_ex \ + $(DOC_DIR)/info_reader_ex readme: $(BIN) sh ./tools/update-readme-usage.sh -- GitLab From 8fd91e200ec7743c7fc87f88c6d279095dd40538 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 13 Feb 2023 15:20:17 +0000 Subject: [PATCH 124/125] Pull Request Originally the project was to be managed via releases, but recently there has been a change of organisation to an incremental mode, so in order to carry out the first pull request we start from the latest version of the development branch by removing the new modules that will be --- configure.sh | 6 - doc/info_reader_ex.c | 140 ------------- doc/test_file_ex.c | 158 -------------- doc/test_main_ex.c | 36 ---- lib/info_reader.h | 243 ---------------------- makefile | 14 +- src/amd_rapl.c | 361 -------------------------------- src/amd_rapl.h | 42 ---- tests/amd_rapl.c | 349 ------------------------------- tests/info_reader.c | 284 ------------------------- tests/main.c | 29 --- tests/small_test.h | 393 ----------------------------------- tests/util.c | 82 -------- tools/update-readme-usage.sh | 30 --- 14 files changed, 2 insertions(+), 2165 deletions(-) delete mode 100644 doc/info_reader_ex.c delete mode 100644 doc/test_file_ex.c delete mode 100644 doc/test_main_ex.c delete mode 100644 lib/info_reader.h delete mode 100644 src/amd_rapl.c delete mode 100644 src/amd_rapl.h delete mode 100644 tests/amd_rapl.c delete mode 100644 tests/info_reader.c delete mode 100644 tests/main.c delete mode 100644 tests/small_test.h delete mode 100644 tests/util.c delete mode 100755 tools/update-readme-usage.sh diff --git a/configure.sh b/configure.sh index 196aaf8..f67b644 100755 --- a/configure.sh +++ b/configure.sh @@ -120,12 +120,6 @@ detect_caps() { *intel*) hdr_whitelist="${hdr_whitelist}|rapl" ;; - *amd*) - family=$(awk '/cpu[ \t]*family/ {print $4; exit}' /proc/cpuinfo) - if isnum "$family"; then - [ $family -ge 17 ] && hdr_whitelist="${hdr_whitelist}|amd_rapl" - fi - ;; *) yell "unsupported processor vendor id: $vendor" ;; diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c deleted file mode 100644 index f1e6d96..0000000 --- a/doc/info_reader_ex.c +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - - -// ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex -#include "./../lib/info_reader.h" - -#define MAX_PROCS 64 - -// -----------------------------The storage -typedef struct { - unsigned int processor; - char *vendor_id; - unsigned int family; - unsigned int core_id; - unsigned int physical_id; - char *model_name; -} Cpu; - -// --------------IMPLEMENTING THE INTERFACE - -// -- Define the behaviour if the attempted value is an int -GenericPointer int_allocator(char *s) -{ - unsigned int value = atoi(s); - return (GenericPointer) value; -} - -// -- Define the behaviour if the attempted value is a string -GenericPointer string_allocator(char *s) -{ - char *value = malloc(strlen(s) + 1); - strcpy(value, s); - return (GenericPointer) value; -} - -// -- Define the processor setter -void set_processor(GenericPointer storage, GenericPointer data) -{ - Cpu *cpu = (Cpu *) storage; - cpu->processor = data; -} - -// -- Define the vendor_id setter -void set_vendor_id(GenericPointer storage, GenericPointer data) -{ - Cpu *cpu = (Cpu *) storage; - cpu->vendor_id = (char *) data; -} - -// -- Define the family setter -void set_family(GenericPointer storage, GenericPointer data) -{ - Cpu *cpu = (Cpu *) storage; - cpu->family = data; -} - -// -- Define the core_id setter -void set_core_id(GenericPointer storage, GenericPointer data) -{ - Cpu *cpu = (Cpu *) storage; - cpu->core_id = data; -} - -// -- Define the physical_id setter -void set_physical_id(GenericPointer storage, GenericPointer data) -{ - Cpu *cpu = (Cpu *) storage; - cpu->physical_id = data; -} - -// -- Define the model_name setter -void set_model_name(GenericPointer storage, GenericPointer data) -{ - Cpu *cpu = (Cpu *) storage; - cpu->model_name = (char *) data; -} - -int main() -{ - Cpu cpus[MAX_PROCS]; - - // -- Define the setter, the allocator for each key / separator. - KeyFinder keys[] = { - {.key = "processor", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_processor}, - {.key = "vendor_id", .delimiter = ": ", .copy = (CopyAllocator *) string_allocator, .set = (Setter *)set_vendor_id}, - {.key = "cpu family", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_family}, - {.key = "core id", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_core_id}, - {.key = "physical id", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_physical_id}, - {.key = "model name", .delimiter = ": ", .copy = (CopyAllocator *) string_allocator, .set = (Setter *)set_model_name} - }; - - size_t nb_keys = sizeof(keys)/sizeof(KeyFinder); - - // -- Init the parser - Parser parser = { - .storage = (GenericPointer) cpus, - .capacity = MAX_PROCS, - .storage_struct_size = sizeof(Cpu), - .keys = keys, - .nb_keys = nb_keys, - .file = fopen("/proc/cpuinfo", "r") - }; - - // -- Parse the file - parse(&parser); - - // Print and free the results - for (unsigned int i = 0; i < parser.nb_stored; ++i) { - printf("========== PROC[%d] ==========\n", i); - printf("Processor: %u\n", cpus[i].processor); - printf("Vendor ID: %s\n", cpus[i].vendor_id); - printf("Family: %u\n", cpus[i].family); - printf("Core ID: %u\n", cpus[i].core_id); - printf("Physical ID: %u\n", cpus[i].physical_id); - printf("Model Name: %s\n", cpus[i].model_name); - free(cpus[i].vendor_id); - free(cpus[i].model_name); - } - printf("==============================\n"); - return 0; -} - diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c deleted file mode 100644 index 0595e9a..0000000 --- a/doc/test_file_ex.c +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -// Include of the test library -#include "./../tests/small_test.h" -// Include the file that contains the function you want to test -// #include "a_file.c" - -// This example is divided into three parts: -// 1. SOME SIMPLE EXAMPLES -// 2. A MORE COMPLEX EXAMPLE -// 3. FILE ENTRY POINT - -// -----------------1. SOME SIMPLE EXAMPLES - -// A simple function that should pass -// test_should_pass is the name of the function -// {} is the function code -// Use one of the define TEST_XXX defined in small_test.h -TFUNCTION(test_should_pass, { - int result = 42; - int expected = 42; - TEST_INT(&result, &expected); -}) - -// A simple function that should pass -// test_should_fail is the name of the function -// {} is the function code -// Use one of the define TEST_XXX defined in small_test.h -TFUNCTION(test_should_fail, { - char *result = "a fail"; - char *expected = "a nice fail"; - TEST_STR(result, expected); -}) - -// A simple test on an array -// test_array is the name of the function -// {} is the function code -// Use one of the define TEST_XXX defined in small_test.h -TFUNCTION(test_array, { - static unsigned int size = 10; - int results[10] = {0}; - int expecteds[10] = {0}; - for (unsigned int i = 0; i < size; i++) - { - TEST_INT(&results[i], &expecteds[i]); - } -}) - -// See "TFILE_ENTRY_POINT" for how to call these functions. - -// ------------2. THE MORE COMPLEX EXAMPLE -// This example shows how to add a new type to the framework - -// The type that you want to add : -typedef struct { - int simple_int; - char simple_str[20]; -} UserType; - - -// The test framework needs two functions : - -// A function that compares two values. -int usertype_compare(void *ptr1, void *ptr2) -{ - return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; -} - -// A function to format a value. -char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) -{ - UserType *x = (UserType *) ptr; - snprintf(buffer, FMT_BUFFER_SIZE, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); - return buffer; -} - -// Store the functions in the interface type. -static const TestInterface usertype_interface = { - .compare = usertype_compare, - .format = usertype_format -}; - -// Create a macro that implements the interface by passing the interface created to the TEST_INTERFACE macro. -#define TEST_USER_TYPE(__result, __expected) \ - TEST_INTERFACE(__result, __expected, &usertype_interface) - - -// Creating a constructor is recommended (C can have problems parsing macros where "," is used). -#define DUMMY_USER_TYPE(__user, __simple_int, __simple_str) \ - do { \ - __user = (UserType) { \ - .simple_int = __simple_int, \ - .simple_str = __simple_str \ - }; \ -} while (0); - -// Now you can write test for your new type -// all you have to do is call the macro that implements "TEST_INTERFACE". -// here it's "TEST_USERTYPE" -TFUNCTION(test_user_type, { - UserType result; - UserType expected; - - DUMMY_USER_TYPE(result, 1, "John Doe"); - DUMMY_USER_TYPE(expected, 1, "John Doe"); - - TEST_USER_TYPE(&result, &expected); -}) - -// Now you can write test for your new type -// all you have to do is call the macro that implements "TEST_INTERFACE". -// here it's "TEST_USERTYPE" -TFUNCTION(test_array_user_type, { - UserType results[1]; - UserType expecteds[1]; - - DUMMY_USER_TYPE(results[0], 1, "John Doe"); - DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - - for (unsigned int i = 0; i < 1; i++) - { - TEST_USER_TYPE(&results[i], &expecteds[i]); - } -}) - -// ---------------------3. FILE ENTRY POINT - -// Define the entry point of a test file -// Use the macro "CALL_TFUNCTION" where the name of a function is defined with the macro "TFUNCTION". -TFILE_ENTRY_POINT(test_file_ex, { - // Call the simple examples - CALL_TFUNCTION(test_should_pass); - CALL_TFUNCTION(test_should_fail); - CALL_TFUNCTION(test_array); - - // Call the more complex example - CALL_TFUNCTION(test_user_type); - CALL_TFUNCTION(test_array_user_type); -}) - diff --git a/doc/test_main_ex.c b/doc/test_main_ex.c deleted file mode 100644 index a5e7841..0000000 --- a/doc/test_main_ex.c +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -// ~/mojitos/doc$ gcc -Wall -Wextra -Wpedantic -o test_main_ex test_main_ex.c ./../src/util.c -// Include of the test library -#include "./../tests/small_test.h" - -// Include the *.c files containing the tests -#include "./test_file_ex.c" -// #include "./test_another_test_file.c" - -// Define the entry point of the programme -TMAIN({ - // Must contain the call to the entry point functions of each file - // USE CALL_TFUNCTION(my_function) instead of my_function() - CALL_TFUNCTION(test_file_ex); - // CALL_TFUNCTION(another_file_entry_point_function); -}) - diff --git a/lib/info_reader.h b/lib/info_reader.h deleted file mode 100644 index ec28db6..0000000 --- a/lib/info_reader.h +++ /dev/null @@ -1,243 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#ifndef _INFO_READER_H -#define _INFO_READER_H - -#include <string.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> - -/** - * @struct Parser - * @brief The parser struct - * The struct containing all the necessary informations and functions to parse a file - * - * @var storage : GenericPointer : pointer to the storage where the parsed data will be stored - * @var nb_stored : unsigned int : the number of struct stored - * @var capacity : unsigned int : the maximum number of struct that can be stored - * @var storage_struct_size : size_t : the size of the struct stored in the storage - * @var keys : KeyFinder* : pointer to an array of KeyFinder containing the possible keys - * @var nb_keys : unsigned int : number of key finders - * @var file : FILE* : pointer to the file that will be parsed -*/ -typedef struct Parser Parser; - -/** - * @struct KeyFinder - * @brief The key finder struct - * The struct containing all the necessary informations and functions to find a key in a line of text - * - * @var key : char* : the key to be found - * @var delimiter : char* : the delimiter between the key and the value - * @var copy : CopyAllocator*: the function to use to make a copy of the value - * @var set : Setter*: the function to use to store the value in the storage -*/ -typedef struct KeyFinder KeyFinder; - -/** - * @brief Split a string into a key and value based on a specified delimiter. - * - * The function takes a string and splits it into two parts: a key and a value. - * The parts are determined by a specified delimiter. - * The key and value are returned through output parameters. - * If the delimiter is not found in the input string, the key and value pointers - * will be set to NULL. - * - * @param[in] string The input string to be split, the string is modified. - * @param[in] delimiter The delimiter string. - * @param[out] key A pointer to a char pointer where the key will be stored. - * @param[out] value A pointer to a char pointer where the value will be stored. - * @return None. - */ -static void split_on_delimiter(char *string, const char *delimiter, char **key, char **value); - -/** - * @brief Replace the first occurrence of a character in a string with another character. - * - * The function takes a string and two characters as input, and replaces the first - * occurrence of the first character in the string with the second character. - * - * @param[in,out] string The input string where the replacement should take place. - * @param[in] from The character to be replaced. - * @param[in] to The character to replace with. - * @return None. - */ -static void replace_first(char *string, char from, char to); - -/** - * @brief Check if a string starts with a prefix. - * - * @param[in] prefix The prefix to check. - * @param[in] string The string to check. - * @return true The string starts with the prefix. - * @return false The string does not start with the prefix or one of the input pointers is NULL. - */ -static bool start_with(const char *prefix, const char *string); - -/** - * @brief Matches a line of text to a key in the parser's list of keys. - * - * @param[in] parser Pointer to the Parser struct. - * @param[in] line Line of text to match. - * @param[out] key_finder Pointer to a KeyFinder pointer where the matched key will be stored. - * @param[out] raw_value Pointer to a char pointer where the value associated with the matched key will be stored. - * - * @return Returns 1 if a key is matched, 0 otherwise. - */ -static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value); - -typedef size_t GenericPointer; -typedef GenericPointer (CopyAllocator) (char *string); -typedef void (Setter) (GenericPointer storage, GenericPointer value); - -struct KeyFinder { - char *key; - char *delimiter; - - CopyAllocator *copy; - Setter *set; -}; - -struct Parser { - GenericPointer storage; - unsigned int nb_stored; - unsigned int capacity; - size_t storage_struct_size; - - KeyFinder *keys; - unsigned int nb_keys; - - FILE *file; -}; - -static void set_value(Parser *parser, KeyFinder *key_finder, char *raw_value) -{ - GenericPointer address = parser->storage + (parser->storage_struct_size * parser->nb_stored); - GenericPointer value = key_finder->copy(raw_value); - key_finder->set(address, value); -} - -static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value) -{ - for (unsigned int i = 0; i < parser->nb_keys; i++) { - KeyFinder *finder = &parser->keys[i]; - - if (start_with(finder->key, line)) { - char *value = NULL; - char *key = NULL; - - split_on_delimiter(line, finder->delimiter, &key, &value); - if ( key == NULL || value == NULL) { - return 0; - } - *key_finder = finder; - *raw_value = value; - return 1; - } - } - return 0; -} - -static unsigned int move_to_next(Parser *parser) -{ - parser->nb_stored += 1; - if (parser->nb_stored >= parser->capacity) { - return 0; - } - return 1; -} - -static unsigned int parse(Parser *parser) -{ - char *line = NULL; - size_t len = 0; - ssize_t read; - unsigned int key_assigned = 0; - - while ((read = getline(&line, &len, parser->file)) != -1) { - if (key_assigned == parser->nb_keys && read > 1) { - continue; - } else if (read == 1) { - if (!move_to_next(parser)) { - return 0; - } - key_assigned = 0; - } else { - KeyFinder *key_finder = NULL; - char *raw_value = NULL; - replace_first(line, '\n', '\0'); - if (match(parser, line, &key_finder, &raw_value)) { - set_value(parser, key_finder, raw_value); - ++key_assigned; - } - } - } - if (key_assigned > 0) { - parser->nb_stored++; - } - free(line); - return 1; -} - - - -static void replace_first(char *string, char from, char to) -{ - for (int i = 0; string[i] != '\0'; i++) { - if (string[i] == from) { - string[i] = to; - break; - } - } -} - -static void split_on_delimiter(char *string, const char *delimiter, char **key, char **value) -{ - *key = NULL; - *value = NULL; - size_t delimiter_len = strlen(delimiter); - char *start_delimiter = strstr(string, delimiter); - if (start_delimiter != NULL) { - *start_delimiter = '\0'; - *key = string; - *value = start_delimiter + delimiter_len; - } -} - -static bool start_with(const char *prefix, const char *string) -{ - if (prefix == NULL || string == NULL) { - return false; - } - - size_t prefix_len = strlen(prefix); - size_t string_len = strlen(string); - - if (string_len < prefix_len) { - return false; - } else { - return memcmp(prefix, string, prefix_len) == 0; - } -} - -#endif - diff --git a/makefile b/makefile index 646a015..f0fa1b1 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,6 @@ SRC_DIR = src DOC_DIR = doc OBJ_DIR = obj BIN_DIR = bin -TESTS_DIR = tests BIN = mojitos @@ -24,7 +23,7 @@ LDFLAGS = ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -all: $(BIN) readme man +all: $(BIN) man $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o @@ -50,28 +49,19 @@ $(BIN_DIR): debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og debug: $(BIN) -tests: - gcc $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run - $(TESTS_DIR)/run - format: $(ASTYLE) $(SRC_DIR)/*.[ch] \ $(DOC_DIR)/*.[ch] \ - $(TESTS_DIR)/*.[ch] clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \ $(SRC_DIR)/counters_option.h \ - $(TESTS_DIR)/run \ $(DOC_DIR)/test_main_ex \ $(DOC_DIR)/info_reader_ex -readme: $(BIN) - sh ./tools/update-readme-usage.sh - man: $(BIN) awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ '/^USAGE/ { $$0=usage } 1' \ doc/mojitos.pre.1 > doc/mojitos.1 2>/dev/null -.PHONY: all clean mojitos debug format tests readme man +.PHONY: all clean mojitos debug format man diff --git a/src/amd_rapl.c b/src/amd_rapl.c deleted file mode 100644 index 1e08517..0000000 --- a/src/amd_rapl.c +++ /dev/null @@ -1,361 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#include <stdio.h> -#include <stdint.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -#include "info_reader.h" -#include "util.h" - -#define BUFFER_SIZE 64 -#define __READ_CPUINFO__ - -// ---------------------------MSR_REGISTERS -static const uint64_t amd_energy_mask = 0xFFFFFFFF; -static const uint64_t amd_energy_unit_mask = 0x01F00; -static const uint64_t msr_rapl_power_unit = 0xC0010299; -static const uint64_t energy_core_msr = 0xC001029A; - -// ------------------------------FILE_PATHS -static const char *base_str = "/dev/cpu/%d/msr"; - -struct CpuSensor { - unsigned int cpu_id; - unsigned int package_id; - unsigned int core_id; - - char *name; - int fd; - - unsigned int energy_units; - uint64_t core_energy; -}; -typedef struct CpuSensor CpuSensor; - -struct AmdRapl { - CpuSensor *sensors; - unsigned int sensor_count; -}; -typedef struct AmdRapl AmdRapl; - -// -----------------------------INFO_READER - -#ifdef __READ_CPUINFO__ -#define NB_KEYS 3 - -static char *cpuinfo = "/proc/cpuinfo"; - -static GenericPointer uint_allocator(char *s) -{ - unsigned int value = atoi(s); - return (GenericPointer) value; -} - -static void _set_cpu_id(GenericPointer storage, GenericPointer data) -{ - CpuSensor *cpu = (CpuSensor *) storage; - cpu->cpu_id = (unsigned int) data; -} - -static void _set_package_id(GenericPointer storage, GenericPointer data) -{ - CpuSensor *cpu = (CpuSensor *) storage; - cpu->package_id = (unsigned int) data; -} - -static void _set_core_id(GenericPointer storage, GenericPointer data) -{ - CpuSensor *cpu = (CpuSensor *) storage; - cpu->core_id = (unsigned int) data; -} - -static KeyFinder keys[NB_KEYS] = { - {"processor", ": ", uint_allocator, _set_cpu_id}, - {"physical id", ": ", uint_allocator, _set_package_id}, - {"core id", ": ", uint_allocator, _set_core_id} -}; - - -static unsigned int parse_cpuinfo(CpuSensor *storage, unsigned int capacity) -{ - Parser parser = { - .storage = (GenericPointer) storage, - .nb_stored = 0, - .capacity = capacity, - .storage_struct_size = sizeof(CpuSensor), - .keys = keys, - .nb_keys = NB_KEYS, - .file = fopen(cpuinfo, "r") - }; - return parse(&parser); -} - -#endif - -// --------------------------------READ_MSR - -uint64_t read_msr(int fd, uint64_t msr) -{ - uint64_t data; - if (pread(fd, &data, sizeof data, msr) != sizeof data) { - fprintf(stderr, "read_msr(%ld):", msr); - perror("pread"); - exit(127); - } - return data; -} - -unsigned int read_unit(int fd) -{ - uint64_t unit = read_msr(fd, msr_rapl_power_unit); - return ((unit & amd_energy_unit_mask) >> 8); -} - -uint64_t read_raw_core_energy(int fd) -{ - uint64_t energy = read_msr(fd, energy_core_msr); - return energy & amd_energy_mask; -} - -// -------------------------READ_PKG_ENERGY - -#ifdef __READ_PKG_ENERGY__ -// TODO: Verify if these functions are still useful (the package energy can be calculed) - -static const uint64_t energy_pkg_msr = 0xC001029B; -uint64_t read_raw_pkg_energy(int fd) -{ - uint64_t energy = read_msr(fd, energy_pkg_msr); - return energy & amd_energy_mask; -} -#endif - -// ----------------------------------ENERGY - -uint64_t raw_to_microjoule(uint64_t raw, unsigned int unit) -{ - static const double to_microjoule = 1000000.0; - // raw * (1 / (unit^2)) -> Joule - // Joule * 1000000 -> uJoule - return (uint64_t) (((double) raw * to_microjoule) / (double)(1U << unit)); -} - -uint64_t raw_to_joule(uint64_t raw, uint64_t unit) -{ - // raw * (1 / (unit^2)) -> Joule - int64_t joule = raw / (1UL << unit); - return joule; -} - -// -----------------------------------DEBUG - -#ifdef DEBUG -void debug_print_sensor(CpuSensor *sensor) -{ - //CASSERT(sizeof(CpuSensor) == 56, amd_rapl_c); - printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", - sensor->cpu_id, - sensor->package_id, - sensor->core_id, - sensor->name, - sensor->fd, - sensor->energy_units, - sensor->core_energy - ); -} - -void debug_print_amd_rapl(AmdRapl *rapl) -{ - for (unsigned int i = 0; i < rapl->sensor_count; i++) { - debug_print_sensor(&rapl->sensors[i]); - } -} - -#endif - -// ---------------------------AMD_RAPL_UTIL - -unsigned int get_nb_cpu() -{ - char filename[BUFFER_SIZE]; - - unsigned int n_cpu = 0; - for (;; n_cpu++) { - snprintf(filename, BUFFER_SIZE, base_str, n_cpu); - - int fd = open(filename, O_RDONLY); - if (fd < 0) { - break; - } - close(fd); - } - return n_cpu; -} - -void get_arch(unsigned int *ret_nb_package, unsigned int *ret_nb_core, CpuSensor *sensors, unsigned int nb_sensor) -{ - unsigned int nb_package = 0; - unsigned int nb_core = 0; - for (unsigned int i = 0; i < nb_sensor; i++) { - if (sensors[i].package_id > nb_package) { - nb_package = sensors[i].package_id; - } - if (sensors[i].core_id > nb_core) { - nb_core = sensors[i].core_id; - } - } - *ret_nb_package = nb_package + 1; - *ret_nb_core = nb_core + 1; -} - -char *get_name(unsigned int cpu_id) -{ - static const char *base_name = "core%d"; - static const size_t max_lenght = 20; - char *name = (char *)calloc(max_lenght, sizeof(char)); - snprintf(name, max_lenght, base_name, cpu_id); - return name; -} - -void update_cpu_sensor(CpuSensor *sensor, uint64_t *energy_consumed) -{ - sensor->energy_units = read_unit(sensor->fd); - uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); - uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - - *energy_consumed = modulo_substraction(core_energy, sensor->core_energy); - sensor->core_energy = core_energy; -} - -unsigned int is_duplicate(CpuSensor *sensor,unsigned int nb_core, unsigned int nb_package, unsigned char map[nb_core][nb_package]) -{ - if (map[sensor->core_id][sensor->package_id] == 1) { - return 0; - } - map[sensor->core_id][sensor->package_id] += 1; - return 1; -} - -void init_cpu_sensor(CpuSensor *sensor, CpuSensor *cpu_info) -{ - static char filename[BUFFER_SIZE]; - snprintf(filename,BUFFER_SIZE, base_str, cpu_info->cpu_id); - - int fd = open(filename, O_RDONLY); - if (fd < 0) { - fprintf(stderr, base_str, cpu_info->cpu_id); - perror(":open()"); - exit(127); - } - - memcpy(sensor, cpu_info, sizeof(CpuSensor)); - sensor->name = get_name(sensor->cpu_id); - sensor->fd = fd; -} - -void clean_cpu_sensor(CpuSensor *sensor) -{ - close(sensor->fd); - free(sensor->name); -} - -void free_amd_rapl(AmdRapl *rapl) -{ - free(rapl->sensors); - free(rapl); -} - -// ----------------------AMD_RAPL_INTERFACE - -unsigned int init_amd_rapl(char *none, void **ptr) -{ - UNUSED(none); - - unsigned int max_cpus = get_nb_cpu(); - if (max_cpus == 0) { - fprintf(stderr, base_str, 0); - perror(":open()"); - exit(127); - } - - CpuSensor *cpu_information = (CpuSensor *) calloc(max_cpus, sizeof(CpuSensor)); - if (parse_cpuinfo(cpu_information, max_cpus)) { - free(cpu_information); - PANIC(1, "cpuinfo"); - } - - unsigned int nb_package; - unsigned int nb_core; - get_arch(&nb_package, &nb_core, cpu_information, max_cpus); - - unsigned char cpu_map[nb_core][nb_package]; - memset(cpu_map, 0, sizeof(cpu_map)); - CpuSensor *sensors = (CpuSensor *) calloc(max_cpus, sizeof(CpuSensor)); - - unsigned int sensor_count = 0; - for (unsigned int i = 0; i < max_cpus; i++) { - if (is_duplicate(&cpu_information[i], nb_core, nb_package, cpu_map) == 1) { - init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); - sensor_count += 1; - } - } - free(cpu_information); - - AmdRapl *rapl = (AmdRapl *) calloc(1, sizeof(AmdRapl)); - rapl->sensors = sensors; - rapl->sensor_count = sensor_count; - *ptr = (void *) rapl; - return rapl->sensor_count; -} - - -unsigned int get_amd_rapl(uint64_t *results, void *ptr) -{ - AmdRapl *rapl = (AmdRapl *) ptr; - for (unsigned int i = 0; i < rapl->sensor_count; i++) { - update_cpu_sensor(&rapl->sensors[i], &results[i]); - } - return rapl->sensor_count; -} - -void label_amd_rapl(char **labels, void *ptr) -{ - AmdRapl *rapl = (AmdRapl *) ptr; - for (unsigned int i = 0; i < rapl->sensor_count; i++) { - labels[i] = rapl->sensors[i].name; - } -} - -void clean_amd_rapl(void *ptr) -{ - AmdRapl *rapl = (AmdRapl *) ptr; - - for (unsigned int i = 0; i < rapl->sensor_count; ++i) { - clean_cpu_sensor(&rapl->sensors[i]); - } - free(rapl->sensors); - free(rapl); -} - diff --git a/src/amd_rapl.h b/src/amd_rapl.h deleted file mode 100644 index e58cc16..0000000 --- a/src/amd_rapl.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - - *******************************************************/ - -unsigned int init_amd_rapl(char *, void **); -unsigned int get_amd_rapl(uint64_t *results, void *); -void clean_amd_rapl(void *); -void label_amd_rapl(char **labels, void *); - -Sensor amd_rapl = { - .init = init_amd_rapl, - .get = get_amd_rapl, - .clean = clean_amd_rapl, - .label = label_amd_rapl, - .nb_opt = 1, -}; - -Optparse amd_rapl_opt[1] = { - { - .longname = "amd-rapl", - .shortname = 'r', - .argtype = OPTPARSE_NONE, - .usage_arg = NULL, - .usage_msg = "AMD RAPL", - }, -}; diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c deleted file mode 100644 index 7c05ab5..0000000 --- a/tests/amd_rapl.c +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#include "small_test.h" -#include "../src/amd_rapl.c" - -TFUNCTION(test_raw_to_microjoule, { - uint64_t raw = 0; - uint64_t unit = 0; - uint64_t result = 0; - uint64_t expected = 0; - - // Test 1: - // -- Setup - raw = 100; - unit = 1000; - expected = 390625; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 2: - // -- Setup - raw = 200; - unit = 1; - expected = 100000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 3: - // -- Setup - raw = 500; - unit = 2; - expected = 125000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 4: - // -- Setup - raw = 1000; - unit = 3; - expected = 125000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // TEST 5: - // -- Setup - raw = 10000; - unit = 4; - expected = 625000000; - // -- Run - result = raw_to_microjoule(raw, unit); - // -- Verification - TEST_UINT64_T(&result, &expected); -}) - -TFUNCTION(test_get_name, { - size_t cpu_id = 0; - char *result = NULL; - char expected[100]; - - // TEST 1: - // -- Setup - cpu_id = 0; - strcpy(expected, "core0"); - // -- Run - result = get_name(cpu_id); - // -- Verification - TEST_STR(result, expected); - free(result); - - // TEST 2: - // -- Setup - cpu_id = 10000; - strcpy(expected, "core10000"); - // -- Run - result = get_name(cpu_id); - // -- Verification - TEST_STR(result, expected); - free(result); -}) - -#define NONE 0 -#define DUMMY_SENSOR(__sensor, __cpu_id, __name) \ -do { \ - __sensor = (CpuSensor) { \ - .cpu_id = __cpu_id, \ - .package_id = NONE, \ - .core_id = NONE, \ - .name = __name, \ - .fd = NONE, \ - .energy_units = NONE, \ - .core_energy = NONE, \ - }; \ -} while(0); - -#define DUMMY_RAPL(__rapl, __sensors, __sensors_count) \ -do { \ - __rapl = (AmdRapl) { \ - .sensors = __sensors, \ - .sensor_count = __sensors_count \ - }; \ -} while(0); - -TFUNCTION(test_label_amd_rapl, { - CpuSensor sensors[100]; - AmdRapl rapl; - char *results[100]; - char expecteds[10][100]; - uint64_t nb = 0; - - // Test 1: - // -- Setup - nb = 1; - DUMMY_SENSOR(sensors[0], 0, "core0"); - DUMMY_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - // -- Run - label_amd_rapl(results, (void *) &rapl); - // -- Verification - for(unsigned int i = 0; i < nb; i++) - { - TEST_STR(results[i], expecteds[i]); - } - - // Test 2: - // -- Setup - nb = 4; - DUMMY_SENSOR(sensors[0], 0, "core0"); - DUMMY_SENSOR(sensors[1], 1, "core1"); - DUMMY_SENSOR(sensors[2], 2, "core2"); - DUMMY_SENSOR(sensors[3], 3, "core3"); - DUMMY_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - strcpy(expecteds[1], "core1"); - strcpy(expecteds[2], "core2"); - strcpy(expecteds[3], "core3"); - // -- Run - label_amd_rapl(results, (void *) &rapl); - // -- Verification - for(unsigned int i = 0; i < nb; i++) - { - TEST_STR(results[i], expecteds[i]); - } - // Test 3: - // -- Setup - nb = 4; - DUMMY_SENSOR(sensors[0], 0, "core0"); - DUMMY_SENSOR(sensors[1], 3, "core3"); - DUMMY_SENSOR(sensors[2], 1, "core1"); - DUMMY_SENSOR(sensors[3], 2, "core2"); - DUMMY_RAPL(rapl, sensors, nb); - strcpy(expecteds[0], "core0"); - strcpy(expecteds[1], "core3"); - strcpy(expecteds[2], "core1"); - strcpy(expecteds[3], "core2"); - // -- Run - label_amd_rapl(results, (void *) &rapl); - // -- Verification - for(unsigned int i = 0; i < nb; i++) - { - TEST_STR(results[i], expecteds[i]); - } -}) - - -#define DUMMY_CPUINFO(__sensor, __cpu_id, __package_id, __core_id) \ -do { \ - __sensor = (CpuSensor) { \ - .cpu_id = __cpu_id, \ - .package_id = __package_id, \ - .core_id = __core_id, \ - .name = NULL, \ - .fd = NONE, \ - .energy_units = NONE, \ - .core_energy = NONE \ - }; \ -} while (0); - -TFUNCTION(test_is_duplicate, { - static const unsigned int nb_core = 4; - static const unsigned int nb_package = 2; - static const unsigned int max_cpu = 10; - - unsigned char map[nb_core][nb_package]; - CpuSensor cpu_information[max_cpu]; - unsigned int results[max_cpu]; - unsigned int expecteds[max_cpu]; - - // -- Setup - memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); - DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); - expecteds[0] = 1; - expecteds[1] = 0; - // -- Run - results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package,map); - results[1] = is_duplicate(&cpu_information[0], nb_core, nb_package,map); - // -- Verification - TEST_BOOL(&results[0], &expecteds[0]); - TEST_BOOL(&results[1], &expecteds[1]); - - // -- Setup - memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); - DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); - DUMMY_CPUINFO(cpu_information[1], 0, 1, 1); - expecteds[0] = 1; - expecteds[1] = 0; - // -- Run - results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); - results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); - // -- Verification - TEST_BOOL(&results[0], &expecteds[0]); - TEST_BOOL(&results[1], &expecteds[1]); - - // -- Setup - memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); - DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); - DUMMY_CPUINFO(cpu_information[1], 0, 0, 0); - expecteds[0] = 1; - expecteds[1] = 1; - // -- Run - results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); - results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); - // -- Verification - TEST_BOOL(&results[0], &expecteds[0]); - TEST_BOOL(&results[1], &expecteds[1]); - - // -- Setup - memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); - DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); - DUMMY_CPUINFO(cpu_information[1], 0, 1, 0); - expecteds[0] = 1; - expecteds[1] = 1; - // -- Run - results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); - results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); - // -- Verification - TEST_BOOL(&results[0], &expecteds[0]); - TEST_BOOL(&results[1], &expecteds[1]); - - // -- Setup - memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); - DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); - DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); - expecteds[0] = 1; - expecteds[1] = 1; - // -- Run - results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); - results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); - // -- Verification - TEST_BOOL(&results[0], &expecteds[0]); - TEST_BOOL(&results[1], &expecteds[1]); - - // -- Setup - memset(map, NONE, sizeof(map)); - memset(cpu_information,NONE, sizeof(CpuSensor) * max_cpu); - DUMMY_CPUINFO(cpu_information[0], 0, 0, 0); - DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); - DUMMY_CPUINFO(cpu_information[2], 0, 1, 0); - DUMMY_CPUINFO(cpu_information[3], 0, 1, 1); - DUMMY_CPUINFO(cpu_information[4], 0, 0, 0); - DUMMY_CPUINFO(cpu_information[5], 0, 0, 1); - DUMMY_CPUINFO(cpu_information[6], 0, 1, 0); - DUMMY_CPUINFO(cpu_information[7], 0, 1, 1); - memset(expecteds, 1, sizeof(unsigned int) * 4); - memset(&expecteds[4], 0, sizeof(unsigned int) * 4); - // -- Run - for (unsigned int i = 0; i < 8; i++) - { - results[i] = is_duplicate(&cpu_information[i], nb_core, nb_package, map ); - } - // -- Verification - for(unsigned int i = 0; i < 8; i++) - { - TEST_BOOL(&results[i], &expecteds[i]); - } -}) - - -TFILE_ENTRY_POINT(test_amd_rapl, { - CALL_TFUNCTION(test_raw_to_microjoule); - CALL_TFUNCTION(test_get_name); - CALL_TFUNCTION(test_label_amd_rapl); - CALL_TFUNCTION(test_is_duplicate); -}) - -#ifdef __TESTING__AMD__ -int main() -{ - static const unsigned int time = 10; - AmdRapl *rapl = NULL; - unsigned int count_cpu = init_amd_rapl(NULL, (void **) &rapl); - uint64_t results[count_cpu]; - char *labels[count_cpu]; - - label_amd_rapl(labels, (void *) rapl); - - for (unsigned int i = 0; i < rapl->sensor_count; ++i) { - printf("%s ", labels[i]); - } - printf("\n"); - - // -- Run - - for (unsigned int i = 0; i < time; ++i) { - sleep(1); - get_amd_rapl(results, (void *)rapl); - - for (unsigned int j = 0; j < rapl->sensor_count; ++j) { - printf("%ld ", results[j]); - } - printf("\n"); - } - - clean_amd_rapl(rapl); - return 0; -} - -#endif - diff --git a/tests/info_reader.c b/tests/info_reader.c deleted file mode 100644 index 5000f48..0000000 --- a/tests/info_reader.c +++ /dev/null @@ -1,284 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#include "small_test.h" -#include "./../lib/info_reader.h" - -TFUNCTION(test_replace_first, { - // useful variables : - char result[100]; - char expected[100]; - - // -- Setup - strcpy(result, "This is my string"); - strcpy(expected, "ThIs is my string"); - // -- Run - replace_first(result, 'i', 'I'); - // -- Verification - TEST_STR(result, expected); - - // -- Setup - strcpy(result, "This is my string"); - strcpy(expected, "This is my string"); - // -- Run - replace_first(result, 'x', 'X'); - // -- Verification - TEST_STR(result, expected); - - // -- Setup - strcpy(result, "This is my string"); - strcpy(expected, "This_is my string"); - // -- Run - replace_first(result, ' ', '_'); - // -- Verification - TEST_STR(result, expected); - - // -- Setup - strcpy(result, "This is my string"); - strcpy(expected, "This_is my string"); - // -- Run - replace_first(result, ' ', '_'); - // -- Verification - TEST_STR(result, expected); - - // -- Setup - strcpy(result, "This is my string"); - strcpy(expected, "This is my string"); - // -- Run - replace_first(result, 'T', 'T'); - // -- Verification - TEST_STR(result, expected); -}) - -TFUNCTION(test_split_on_delimiter, { - // Useful variables - char string[100]; - char *result_key; - char *result_value; - char expected_key[100]; - char expected_value[100]; - - // Setup - strcpy(string, "key:value"); - strcpy(expected_key, "key"); - strcpy(expected_value, "value"); - // Run - split_on_delimiter(string, ":", &result_key, &result_value); - // Verification - TEST_STR(result_key, expected_key); - TEST_STR(result_value, expected_value); - - // Setup - strcpy(string, "key: value"); - strcpy(expected_key, "key"); - strcpy(expected_value, " value"); - // Run - split_on_delimiter(string, ":", &result_key, &result_value); - // Verification - TEST_STR(result_key, expected_key); - TEST_STR(result_value, expected_value); - - // Setup - strcpy(string, "key:value"); - strcpy(expected_key, "key"); - strcpy(expected_value, "value"); - replace_first(string, ':', ' '); - // Run - split_on_delimiter(string, " ", &result_key, &result_value); - // Verification - TEST_STR(result_key, expected_key); - TEST_STR(result_value, expected_value); - - // Setup - strcpy(string, ""); - // Run - split_on_delimiter(string, ":", &result_key, &result_value); - // Verification - TEST_STR(result_key, NULL); - TEST_STR(result_value, NULL); - - // Setup - strcpy(string, "key:value:extra"); - strcpy(expected_key, "key"); - strcpy(expected_value, "value:extra"); - // Run - split_on_delimiter(string, ":", &result_key, &result_value); - // Verification - TEST_STR(result_key, expected_key); - TEST_STR(result_value, expected_value); - - // Setup - strcpy(string, "key: value :extra"); - strcpy(expected_key, "key"); - strcpy(expected_value, " value :extra"); - // Run - split_on_delimiter(string, ":", &result_key, &result_value); - // Verification - TEST_STR(result_key, expected_key); - TEST_STR(result_value, expected_value); -}) - -TFUNCTION(test_start_with, { - char *prefix = NULL; - char *string = NULL; - bool result = false; - bool _true = true; - bool _false = false; - - prefix = "Hello"; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOL(&result, &_true); - - prefix = "Goodbye"; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOL(&result, &_false); - - prefix = "Hello World"; - string = "Hello"; - result = start_with(prefix, string); - TEST_BOOL(&result, &_false); - - prefix = "Hello"; - string = "Hello"; - result = start_with(prefix, string); - TEST_BOOL(&result, &_true); - - prefix = NULL; - string = "Hello World"; - result = start_with(prefix, string); - TEST_BOOL(&result, &_false); -}) - -#define NONE 0 -#define DUMMY_KEYFINDER(__key_finder, __key, __delimiter) \ - do { \ - __key_finder = (KeyFinder) { \ - .key = __key, \ - .delimiter = __delimiter, \ - .copy = NONE, \ - .set = NONE \ - }; \ - } while (0); - -#define DUMMY_PARSER(__parser, __keys, __nb_keys) \ - do { \ - __parser = (Parser) { \ - .storage = NONE, \ - .nb_stored = NONE, \ - .capacity = NONE, \ - .storage_struct_size = NONE, \ - .keys = __keys, \ - .nb_keys = __nb_keys, \ - .file = NONE \ - }; \ - } while (0); - - -TFUNCTION(test_match, { - // useful variables : - bool _true = true; - bool _false = false; - KeyFinder keys[10]; - char line[100]; - Parser parser; - bool result; - KeyFinder *found_key_finder = NULL; - char *raw_value = NULL; - - // Test 1: - // -- Setup - DUMMY_KEYFINDER(keys[0], "key", ": "); - DUMMY_PARSER(parser, keys, 1); - strcpy(line, "key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOL(&result, &_true); - TEST_PTR(found_key_finder, &keys[0]); - TEST_STR(raw_value, "value"); - - // Test 2: - // -- Setup - DUMMY_KEYFINDER(keys[0], "key", ": "); - DUMMY_PARSER(parser, keys, 1) - strcpy(line, "not a key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOL(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); - - // Test 3: - // -- Setup - DUMMY_KEYFINDER(keys[0],"key", ": "); - DUMMY_PARSER(parser, keys, 1); - strcpy(line, "key:value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOL(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); - - // Test 4: - // -- Setup - DUMMY_KEYFINDER(keys[0], "key", ": "); - DUMMY_KEYFINDER(keys[1], "second_key", ": "); - DUMMY_PARSER(parser, keys, 2); - strcpy(line, "second_key: value"); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - // -- Verification - TEST_BOOL(&result, &_true); - TEST_PTR(found_key_finder, &keys[1]); - TEST_STR(raw_value, "value"); - - // Test 5: - // -- Setup - DUMMY_KEYFINDER(keys[0], "key", ": "); - DUMMY_PARSER(parser, keys, 1); - strcpy(line, ""); - found_key_finder = NULL; - raw_value = NULL; - // -- Run - result = match(&parser, line, &found_key_finder, &raw_value); - TEST_BOOL(&result, &_false); - TEST_PTR(found_key_finder, NULL); - TEST_STR(raw_value, NULL); -}) - -TFILE_ENTRY_POINT(test_info_reader, { - CALL_TFUNCTION(test_replace_first); - CALL_TFUNCTION(test_split_on_delimiter); - CALL_TFUNCTION(test_start_with); - CALL_TFUNCTION(test_match); -}) - diff --git a/tests/main.c b/tests/main.c deleted file mode 100644 index 3246f04..0000000 --- a/tests/main.c +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#include "util.c" -#include "amd_rapl.c" -#include "info_reader.c" - -TMAIN({ - CALL_TFUNCTION(test_util); - CALL_TFUNCTION(test_amd_rapl); - CALL_TFUNCTION(test_info_reader); -}) diff --git a/tests/small_test.h b/tests/small_test.h deleted file mode 100644 index 66c4de9..0000000 --- a/tests/small_test.h +++ /dev/null @@ -1,393 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#ifndef __SMALL_TEST_H -#define __SMALL_TEST_H - -#include <stdbool.h> -#include <string.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> - -#include "../src/util.h" - -#define FMT_BUFFER_SIZE 1000 - -// ---------------------------API_INTERFACE -/** - * @def TMAIN(__code) - * - * @brief Define the entry point for the tests. - * It initialises any useful variables and acts as the main one. - * - * @param __code The code that contains the calls to the test functions. - */ - -#define TMAIN(__code) \ - int main() \ -{ \ - unsigned int __indentation_level = 0; \ - INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ - unsigned int __error_counter__ = 0; \ - do __code while (0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ -} - -/** - * @def TFILE_ENTRY_POINT(__filename, __code) - * - * @brief Define the entry point of a test file. - * This macro is used to define the entry point of a test file. - * It defines a function with the specified __filename that contains the test code specified in code. - * - * When the function is called, it initialises the test file using the INIT_TEST_FILE macro, - * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, - * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. - * The function returns the value of __error_counter__, - * which indicates the number of errors encountered during the tests. - * - * @param __filename The name of the function to be used as an entry point for the test file. - * @param __code The test code to be executed in the function. - */ -#define TFILE_ENTRY_POINT(__filename, __code) \ - int __filename (unsigned int __indentation_level) \ -{ \ - INIT_TEST_FILE(); \ - int __error_counter__ = 0; \ - do __code while(0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ -} - -/** - * @def TFUNCTION(__function_name, __code) - * - * @brief Define a test function within a test file. - * This macro is used to define a test function within a test file. - * It defines a function with the given __function_name containing the test code specified in __code. - * - * When the function is called, it initialises the test function using the INIT_TEST_FUNCTION macro, - * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, - * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. - * The function returns the value of __error_counter__, which indicates the number of errors encountered during the tests. - * - * @param __function_name The name of the test function. - * @param __code The test code to be executed in the function. - */ -#define TFUNCTION(__function_name, __code) \ - int __function_name(unsigned int __indentation_level) \ -{ \ - INIT_TEST_FUNCTION(); \ - int __error_counter__ = 0; \ - do __code while(0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ -} - -/** - * @def CALL_TFUNCTION(__function_name) - * - * @brief Call a test function within a test file. - * This macro is used to call a test function within a test file. - * It calls the function specified by __function_name and adds the return value to the __error_counter__ variable. - * This allows multiple test functions to be executed and their error count to be accumulated. - * - * @param __function_name The name of the test function to be called. - */ -#define CALL_TFUNCTION(__function_name) \ - do {__error_counter__ += __function_name(__indentation_level + 1);} while(0) - -/** - * @def TEST_STR(__result, __expected) - * - * @brief Test strings - * This macro is used to test strings. It takes two arguments: `__result`, which is the string to test, and `__expected`, - * which is the expected value of the string. - * - * @param __result the string to test. - * @param __expected the expected value of the string. - * - * @code - * TEST_STR("Hello", "Hello"); - * @endcode - */ -#define TEST_STR(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &str_interface);} while(0) - -/** - * @def TEST_BOOL(__result, __expected) - * - * @brief Test bools - * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to test, and `__expected`, - * which is the expected value of the bool. - * - * @param __result the pointer to bool to test. - * @param __expected the pointer to the expected value of the bool. - * - * @code - * bool x = true; - * bool y = true; - * TEST_BOOL(&x, &y); - * @endcode - */ -#define TEST_BOOL(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &bool_interface);} while (0) - -/** - * @def TEST_INT(__result, __expected) - * - * @brief Test ints - * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be test, and `__expected`, - * which is the expected value of the int. - * - * @param __result the pointer to int to test. - * @param __expected the pointer to expected value of the int. - * - * @code - * int x = 1; - * int y = 1; - * TEST_INT(&x, &y) - * @endcode - */ -#define TEST_INT(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &int_interface);} while (0) - -/** - * @def TEST_PTR(__result, __expected) - * - * @brief Test pointers - * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to test, and `__expected`, - * which is the expected value of the pointer. - * - * @param __result the pointer to test. - * @param __expected the expected value of the pointer. - * - * @code - * int x = 5; - * int *ptr = &x; - * TEST_PTR(ptr, &x); - * @endcode - */ -#define TEST_PTR(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &ptr_interface);} while(0) - - -/** - * @def TEST_UINT64_T(__result, __expected) - * - * @brief Test 64-bit unsigned integers - * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, - * which is the integer to test, and `__expected`, which is the expected value of the integer. - * - * @param __result the pointer to integer to test. - * @param __expected the pointer to expected value of the integer. - * - * @code - * uint64_t x = 5; - * uint64_t y = 5; - * TEST_UINT64_T(&x, &y); - * @endcode - */ -#define TEST_UINT64_T(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) - -/** - * @def TEST_INTERFACE(__result, __expected, __interface) - * - * @brief Define a macro on a usertype with the given __interface. - * This macro is used by the user to define a new test macro on a usertype. - * - * @param __result - * @param __expected - * @param __interface the interface of the usertype. - * - * @code - * TestInterface usertype_interface = {.compare = ..., .format = ...}; - * #define TEST_USERTYPE(__result, __expected) \ - * TEST_INTERFACE(__result, __expected, &usertype_interface) - * @endcode - */ -#define TEST_INTERFACE(__result, __expected, __interface) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) - - - - -// ------------------------------------CODE -// These functions should not be in use, only the previous macros should be in use. - -#define INDENTED_PRINT(__fmt, ...) \ - do { \ - for(unsigned int i = 0; i < __indentation_level; i++) { \ - printf("| "); \ - } \ - printf(__fmt, ##__VA_ARGS__); \ - } while(0) - - -#define INIT_TEST_FILE() \ - INDENTED_PRINT("%s:%s\n", __FILE__, __func__) - -#define INIT_TEST_FUNCTION() \ - INDENTED_PRINT("%s()\n", __func__); - -#define DEFERRED_ERROR(nb_error) \ - INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); - -typedef int (Comparator) (void *, void *); -typedef char *(Formatter) (char[FMT_BUFFER_SIZE], void *); - -typedef struct { - Comparator *compare; - Formatter *format; -} TestInterface; - -// ---------------------------TEST FUNCTION - -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) -{ - __indentation_level += 1; - static char buffer_result[FMT_BUFFER_SIZE]; - static char buffer_expected[FMT_BUFFER_SIZE]; - int is_equal = interface->compare(result, expected); - - char *fmt_result = interface->format(buffer_expected, expected); - char *fmt_expected = interface->format(buffer_result, result); - if (!is_equal) { - INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); - } - return !is_equal; -} - -// ------------------------------INTERFACES - -// -- str_interface -int str_compare(void *ptr1, void *ptr2) -{ - char *str1 = (char *) ptr1; - char *str2 = (char *) ptr2; - - if (str1 == NULL && str2 == NULL) { - return 1; - } else if (str1 == NULL || str2 == NULL) { - return 0; - } else { - return (strcmp(str1, str2) == 0); - } -} - -char *str_format(char buffer[FMT_BUFFER_SIZE], void *ptr) -{ - UNUSED(buffer); - static char *str_null = "NULL"; - char *str = (char *) ptr; - return str ? str : str_null; -} - -static const TestInterface str_interface = { - .compare = str_compare, - .format = str_format -}; - -// -- bool_interface - -int bool_compare(void *ptr1, void *ptr2) -{ - bool *bool1 = (bool *) ptr1; - bool *bool2 = (bool *) ptr2; - return *bool1 == *bool2; -} - -char *bool_format(char buffer[FMT_BUFFER_SIZE], void *ptr) -{ - UNUSED(buffer); - bool *_bool = (bool *) ptr; - return *_bool ? "True" : "False"; -} - -static const TestInterface bool_interface = { - .compare = bool_compare, - .format = bool_format -}; - -// -- int_interface - -int int_compare(void *ptr1, void *ptr2) -{ - int *int1 = (int *) ptr1; - int *int2 = (int *) ptr2; - return *int1 == *int2; -} - -char *int_format(char buffer[FMT_BUFFER_SIZE], void *ptr) -{ - int *_int = (int *) ptr; - snprintf(buffer, FMT_BUFFER_SIZE, "%d", *_int); - return buffer; -} - -static const TestInterface int_interface = { - .compare = int_compare, - .format = int_format -}; - -// -- ptr_interface - -int ptr_compare(void *ptr1, void *ptr2) -{ - return ptr1 == ptr2; -} - -char *ptr_format(char buffer[FMT_BUFFER_SIZE], void *ptr) -{ - snprintf(buffer, FMT_BUFFER_SIZE, "%p", ptr); - return buffer; -} - -static const TestInterface ptr_interface = { - .compare = ptr_compare, - .format = ptr_format -}; - -// -- u64_interface - -int u64_compare(void *ptr1, void *ptr2) -{ - uint64_t *v1 = (uint64_t *) ptr1; - uint64_t *v2 = (uint64_t *) ptr2; - return *v1 == *v2; -} - -char *u64_format(char buffer[FMT_BUFFER_SIZE], void *ptr) -{ - uint64_t *v = (uint64_t *) ptr; - snprintf(buffer, FMT_BUFFER_SIZE, "%"PRIu64"", *v); - return buffer; -} - -static const TestInterface u64_interface = { - .compare = u64_compare, - .format = u64_format -}; - -#endif - diff --git a/tests/util.c b/tests/util.c deleted file mode 100644 index 69941bf..0000000 --- a/tests/util.c +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************* - Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - - This file is part of Mojitos. - - Mojitos is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Mojitos is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. - -*******************************************************/ - -#include "../src/util.h" -#include "small_test.h" - - -TFUNCTION(test_modulo_substraction, { - uint64_t lhs = 0; - uint64_t rhs = 0; - uint64_t result = 0; - uint64_t expected = 0; - - // Test 1: - // -- Setup - lhs = 10; - rhs = 10; - expected = 0; - // -- Run - result = modulo_substraction(lhs, rhs); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // Test 2: - // -- Setup - lhs = UINT64_MAX; - rhs = 0; - expected = UINT64_MAX; - // -- Run - result = modulo_substraction(lhs, rhs); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // Test 3: - // -- Setup - lhs = 0; - rhs = UINT64_MAX; - expected = 1; - // -- Run - result = modulo_substraction(lhs, rhs); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // Test 4: - // -- Setup - lhs = 10; - rhs = 20; - expected = UINT64_MAX - 9; - // -- Run - result = modulo_substraction(lhs, rhs); - // -- Verification - TEST_UINT64_T(&result, &expected); - - // Test 5: - // -- Setup - lhs = 1000; - rhs = 1000; - expected = 0; - result = modulo_substraction(lhs, rhs); - TEST_UINT64_T(&result, &expected); -}) - -TFILE_ENTRY_POINT(test_util, { - CALL_TFUNCTION(test_modulo_substraction); -}) diff --git a/tools/update-readme-usage.sh b/tools/update-readme-usage.sh deleted file mode 100755 index ad2f88f..0000000 --- a/tools/update-readme-usage.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> - -die() { yell "$*"; exit 111; } -try() { "$@" || die "cannot $*"; } -yell() { echo "$0: $*" >&2; } -echo() { printf '%s\n' "$*"; } - -usage=$(./bin/mojitos) -[ -n "$usage" ] || die 'empty usage. try to recompile mojitos.' - -try awk -v "usage=$usage" ' - /^Usage/ { - print usage - del = 1 - } - { - if (del == 1) { - if (match($0, "^```")) { - del = 0 - print $0 - } - } else { - print $0 - } - } -' README.md > README.tmp -try mv README.tmp README.md -- GitLab From b36861ab5150990398e5942b2ea74d7693045e87 Mon Sep 17 00:00:00 2001 From: Georges Da Costa <42-dacosta@users.noreply.022e47118ec0> Date: Fri, 17 Feb 2023 14:29:26 +0000 Subject: [PATCH 125/125] Update configure.sh --- configure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.sh b/configure.sh index f67b644..9264caa 100755 --- a/configure.sh +++ b/configure.sh @@ -106,7 +106,7 @@ gen_sensors_mk() { detect_caps() { [ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters - [ -d /sys/class/infiniband ] && hdr_whitelist=${hdr_whitelist}|infiniband + [ -d /sys/class/infiniband ] && hdr_whitelist="${hdr_whitelist}|infiniband" [ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load" if [ -r /proc/net/route ]; then -- GitLab