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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] =?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/229] =?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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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/229] 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 eab8f8bf862f796b589374803af9d501d7a7ef08 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 6 Feb 2023 14:09:22 +0100 Subject: [PATCH 105/229] Add dev name to labels plus some other changes, in particular: - index --> strchr - sprintf --> snprintf --- src/network.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/network.c b/src/network.c index 543a053..aee5659 100644 --- a/src/network.c +++ b/src/network.c @@ -28,10 +28,17 @@ #define NB_SENSOR 4 static char *route = "/proc/net/route"; +char *_labels_network[NB_SENSOR] = { + "%s:rxp", + "%s:rxb", + "%s:txp", + "%s:txb", +}; struct network_t { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; + char labels[NB_SENSOR][128]; }; unsigned int _get_network(uint64_t *results, int *sources) @@ -54,8 +61,6 @@ unsigned int _get_network(uint64_t *results, int *sources) return NB_SENSOR; } - - unsigned int init_network(char *dev, void **ptr) { if (dev == NULL) { @@ -79,25 +84,27 @@ unsigned int init_network(char *dev, void **ptr) exit(1); } - char *start_of_dev = index(buffer, '\n') + 1; - char *end_of_dev = index(start_of_dev, '\t'); + char *start_of_dev = strchr(buffer, '\n') + 1; + char *end_of_dev = strchr(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" - }; + 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); + snprintf(buffer2, sizeof(buffer2), filenames[i], dev); state->sources[i] = open(buffer2, O_RDONLY); + snprintf(state->labels[i], sizeof(state->labels[i]), _labels_network[i], dev); } *ptr = (void *) state; @@ -134,12 +141,11 @@ void clean_network(void *ptr) free(state); } -char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; -void label_network(char **labels, void *none) +void label_network(char **labels, void *ptr) { - UNUSED(none); + struct network_t *state = (struct network_t *) ptr; for (int i = 0; i < NB_SENSOR; i++) { - labels[i] = _labels_network[i]; + labels[i] = state->labels[i]; } } -- 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 106/229] 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 107/229] 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 108/229] 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 109/229] 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 110/229] 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 111/229] 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 112/229] 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 113/229] 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 114/229] 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 72ae8099f4559689c3d8a30957a5933b695101a6 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 115/229] 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 ae734b928303fa5690dd1c51b83bc1f1e25751b1 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 116/229] 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 5d63d39b713348c4596905f0cebaba9a127dfd3b 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 117/229] 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 e052fe6b71eb27213afbf631d6c25407e449aa24 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 118/229] 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 49943ea17c5bdcb96cd808454e3044c15d984b55 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 119/229] 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 6e2d8275d7863201bee91ee188adaadb6c2ad276 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 120/229] 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 be9a5e0585953b8b3ce75adf0a273a9e32babb19 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 121/229] 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 221ec2635483b360fdd9d2198eba678609c6993c 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 122/229] 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 26c34e9e53e0c139f7cecf578b9bcf41e16f670b 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 123/229] 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 d1d5853bdd89bf2dac4b707d163958542aa5ac76 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 124/229] 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 d8d7594057326d29a07d48057cfba3574df122e8 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 125/229] 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 730f969f8cd60054edf8cc995650fdee0f9d2d44 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 126/229] 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 e16dc9f4d47bc55b5875136ff06629459839ffca 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 127/229] 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 22cbdb2ae7804be8f3a03610175c3b4e56c93dc0 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 128/229] 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 95956fd34bad0e160dd15e96f25d006eef8df7a1 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 129/229] 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 427ee8f328e16521aa18d3778f9b769c417a5fba 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 130/229] 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 fb5106fc764e64a741fe9a5e97e67e4184fb1f09 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 131/229] 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 844433049c8f02aab7238679b6d052d2f84aa0ff 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 132/229] 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 76653cfafb1f60a31791a761fcd41d5c54b6b9c4 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 133/229] 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 bab4a95c8dccf445cb0bb359fc8dfe9b8eee0d59 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 134/229] 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 a1cded04769e4d1c90e9b370419026e8c296b8e3 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 135/229] 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 00600d4ad379584817de4a5cdabaeb78a8206a1c 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 136/229] 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 851cef1b09b4bf468aed0e11ca8c6cba31826067 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 137/229] 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 5e505cc72bb11a4a119527a21c80b6d208fffdbb 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 138/229] 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 9b9a4c4206947e9cd6180cd1071441911a3783ba 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 139/229] 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 585fa51e2a9f1d181ccd1bc10f2ac3deba544a3b 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 140/229] 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 bea62d235a126b799dd3e05692903e27cc7129ed 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 141/229] 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 fa47271704f8d2fe67a86d94b8746c8d39eb527d 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 142/229] 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 402140300f756114e7ed4f18fd4692b9b5e6aae4 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 143/229] 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 4b22f61991d079ebfce3c387d4ceae227a57ed47 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 144/229] 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 f29c9ade9da41bc824c40c59b4ce0e48e79c13fb 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 145/229] 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 8aeab626fdda56b5090c4b88ae6ca46631509491 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 12:39:47 +0100 Subject: [PATCH 146/229] 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 | 21 +++++----- 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, 234 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index dd136f4..6643912 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ -src/counters_option.h -src/captors.h -tests/run -bin -obj -*.swp -*.swo -.vscode -doc/test_main_ex -doc/info_reader_ex +doc/test_main_ex +doc/info_reader_ex +tests/run +src/counters_option.h +src/sensors.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 f16ed4f..52a7c6c 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 ea44320719bf3b4c74772dc732535ae1e45e214b Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 13:05:29 +0100 Subject: [PATCH 147/229] 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 569f527a427531691dee1b9e305cab5d4b6d00f8 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 17:32:40 +0100 Subject: [PATCH 148/229] 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 | 3 +- 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, 213 insertions(+), 163 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 6643912..31260f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ doc/test_main_ex doc/info_reader_ex +doc/mojitos.1 tests/run src/counters_option.h src/sensors.h -captors.mk +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 52a7c6c..1a16db8 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 24f03a059ada281567c9b7a600cd461619865640 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 6 Feb 2023 10:43:08 +0100 Subject: [PATCH 149/229] 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 10d6b8c4c1cffff4f52dca798cd6d7cba8eee1ee Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 7 Feb 2023 14:11:24 +0100 Subject: [PATCH 150/229] 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 151/229] 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 152/229] 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 9ef7c81ca0b0ca2d3cd09340d8c357f3f6655524 Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Wed, 8 Feb 2023 23:13:54 +0100 Subject: [PATCH 153/229] gitlab CI config --- .gitlab-ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..cac871a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,14 @@ +job-build + stage: build + script: + - ./configure.sh + - make + +job-build-test + stage: build + script: + - ./configure.sh + - make tests + +workflow: + name: 'Pipeline for branch: $CI_COMMIT_BRANCH' -- GitLab From 30c61950fbca95eb6f6aeab88e9e248262dca19a Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Sat, 11 Feb 2023 19:37:59 +0100 Subject: [PATCH 154/229] fix gitlab ci --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cac871a..91608c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,12 @@ -job-build +job-build: stage: build script: - ./configure.sh - make -job-build-test +job-build-test: stage: build - script: + script: - ./configure.sh - make tests -- 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 155/229] 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 156/229] 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 157/229] 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 158/229] 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 159/229] 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 160/229] 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 161/229] 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 27b4914943dd51aca0600f20b77659bb7532d86e Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Feb 2023 16:40:07 +0100 Subject: [PATCH 162/229] the README.md file now present all sensors - add `--all` option to configure.sh - makefile: readme is no longer a "all" dependency - plus some minor changes --- README.md | 9 +++++++++ configure.sh | 14 +++++++++++--- makefile | 6 +++--- tools/update-readme-usage.sh | 26 +++++++++++++++++++++++--- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 10f5aaf..ac5b2d3 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,22 @@ OPTIONS: -s|--overhead-stats enable overhead statistics (nanoseconds). +``` + +The following is an exhaustive list of all the sensors (it is very likely +that one will not have all the sensors activated in his build): +```bash SENSORS: +-a|--amd-rapl + AMD RAPL -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 +-i|--monitor-infiniband <infiniband_path> + infiniband monitoring (if infiniband_path is X, tries to detect it automatically) -u|--sysload system load -d|--net-dev <net_dev> diff --git a/configure.sh b/configure.sh index 62f297a..6b48fb5 100755 --- a/configure.sh +++ b/configure.sh @@ -23,18 +23,19 @@ debug=0 target_hdr=src/sensors.h target_mk=sensors.mk -nonsensor='counters_option|optparse|sensors|util|info_reader' +nonsensor='counters_option|sensors|util' hdr_blacklist=$nonsensor hdr_whitelist='' usage() { - printf -- 'Usage: %s [-l] [-e <sensor>] [-i <sensor>] [-u <sensor>]\n' "$(basename "$0")" >&2 + printf -- 'Usage: %s [-la] [-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 + printf -- '-a | --all : include all sensors, meant to be used only by the makefile\n' >&2 exit 1 } @@ -131,8 +132,15 @@ detect_caps() { [ $(ls -1 /sys/class/hwmon | wc -l) -gt 0 ] && hdr_whitelist="${hdr_whitelist}|temperature" } -detect_caps +case $1 in +--all|-a) + all=1 + ;; +esac +[ "$all" ] || detect_caps + +[ "$all" ] || while [ "$1" ]; do case $1 in --include|-i) diff --git a/makefile b/makefile index 950028c..07c8061 100644 --- a/makefile +++ b/makefile @@ -24,7 +24,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 @@ -51,7 +51,7 @@ debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og debug: $(BIN) tests: - gcc $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run + $(CC) $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run $(TESTS_DIR)/run format: @@ -70,6 +70,6 @@ readme: $(BIN) man: $(BIN) awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ '/^USAGE/ { $$0=usage } 1' \ - doc/mojitos.pre.1 > doc/mojitos.1 2>/dev/null + doc/$(BIN).pre.1 > doc/$(BIN).1 2>/dev/null .PHONY: all clean mojitos debug format tests readme man diff --git a/tools/update-readme-usage.sh b/tools/update-readme-usage.sh index b9f16de..c9e0797 100755 --- a/tools/update-readme-usage.sh +++ b/tools/update-readme-usage.sh @@ -5,8 +5,24 @@ try() { "$@" || die "cannot $*"; } yell() { echo "$0: $*" >&2; } echo() { printf '%s\n' "$*"; } -usage=$(./bin/mojitos) -[ -n "$usage" ] || die 'empty usage. try to recompile mojitos.' +try ./configure.sh --all +try make mojitos +usage=$( + ./bin/mojitos | + awk ' + /^SENSORS/ { + $0 = "" + printf "```\n" + printf "\n" + printf "The following is an exhaustive list of all the sensors (it is very likely\n" + printf "that one will not have all the sensors activated in his build):\n" + printf "```bash\n" + printf "SENSORS:" + } + { print } + ' +) +[ -n "$usage" ] || die 'empty usage. cannot continue.' try awk -v "usage=$usage" ' /^Usage/ { @@ -14,7 +30,11 @@ try awk -v "usage=$usage" ' del = 1 } { - if (del == 1) { + if (del == 1 || del == 2) { + if (match($0, "^```")) { + del++ + } + } else if (del == 3) { if (match($0, "^```")) { del = 0 print $0 -- GitLab From 9544a1e31849f953c498ebaa861d27a004628c90 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Feb 2023 18:02:56 +0100 Subject: [PATCH 163/229] the option to dump all options is now a long option --- makefile | 2 +- src/mojitos.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 07c8061..cd9be75 100644 --- a/makefile +++ b/makefile @@ -68,7 +68,7 @@ readme: $(BIN) sh ./tools/update-readme-usage.sh man: $(BIN) - awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ + awk -v "usage=$$($(BIN_DIR)/$(BIN) --dump-opts)" \ '/^USAGE/ { $$0=usage } 1' \ doc/$(BIN).pre.1 > doc/$(BIN).1 2>/dev/null diff --git a/src/mojitos.c b/src/mojitos.c index 3ecf111..343ec21 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -24,6 +24,7 @@ #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <time.h> #include <unistd.h> #include "util.h" @@ -219,7 +220,7 @@ int main(int argc, char **argv) usage(argv); } - if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '1' && argv[1][2] == '\0') { + if (argc == 2 && strcmp(argv[1], "--dump-opts") == 0) { dumpopts(opts, NB_OPT, NB_SENSOR_OPT); exit(EXIT_SUCCESS); } -- GitLab From 927e0fe276ab52a3ef796cd3239734e49ea65ba4 Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Wed, 15 Feb 2023 10:48:41 +0100 Subject: [PATCH 164/229] trying different build options --- .gitignore | 20 ++++++++++---------- .gitlab-ci.yml | 28 ++++++++++++++++++++++++++++ configure.sh | 2 +- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index dd136f4..c9b9c0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ -src/counters_option.h -src/captors.h -tests/run -bin -obj -*.swp -*.swo -.vscode -doc/test_main_ex -doc/info_reader_ex +src/counters_option.h +src/captors.h +tests/run +bin +obj +*.swp +*.swo +.vscode +doc/test_main_ex +doc/info_reader_ex diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 91608c4..2052da5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,31 @@ +stages: + - build-option + - build + +job-build-counters: + stage: build-option + script: + - ./configure.sh -u counters + - make + +job-build-load: + stage: build-option + script: + - ./configure.sh -u load + - make + +job-build-network: + stage: build-option + script: + - ./configure.sh -u network + - make + +job-build-rapl: + stage: build-option + script: + - ./configure.sh -u rapl + - make + job-build: stage: build script: diff --git a/configure.sh b/configure.sh index 2d21bf5..d272629 100755 --- a/configure.sh +++ b/configure.sh @@ -33,7 +33,7 @@ usage() { 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 + printf -- ' if this option is used, any use of `-e` or `-i` will be ignored\n' >&2 exit 1 } -- GitLab From 4691e8d7633fe2a17c7c82e9ec5655e80da58b82 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Feb 2023 16:40:07 +0100 Subject: [PATCH 165/229] the README.md file now present all sensors - add `--all` option to configure.sh - makefile: readme is no longer a "all" dependency - plus some minor changes --- README.md | 9 +++++++++ configure.sh | 14 +++++++++++--- makefile | 6 +++--- tools/update-readme-usage.sh | 26 +++++++++++++++++++++++--- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 95b6d7e..869c358 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,22 @@ OPTIONS: -s|--overhead-stats enable overhead statistics (nanoseconds). +``` + +The following is an exhaustive list of all the sensors (it is very likely +that one will not have all the sensors activated in his build): +```bash SENSORS: +-a|--amd-rapl + AMD RAPL -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 +-i|--monitor-infiniband <infiniband_path> + infiniband monitoring (if infiniband_path is X, tries to detect it automatically) -u|--sysload system load -d|--net-dev <net_dev> diff --git a/configure.sh b/configure.sh index 196aaf8..3f82c3b 100755 --- a/configure.sh +++ b/configure.sh @@ -26,18 +26,19 @@ debug=0 target_hdr=src/sensors.h target_mk=sensors.mk -nonsensor='counters_option|optparse|sensors|util|info_reader' +nonsensor='counters_option|sensors|util' hdr_blacklist=$nonsensor hdr_whitelist='' usage() { - printf -- 'Usage: %s [-l] [-e <sensor>] [-i <sensor>] [-u <sensor>]\n' "$(basename "$0")" >&2 + printf -- 'Usage: %s [-la] [-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 + printf -- '-a | --all : include all sensors, meant to be used only by the makefile\n' >&2 exit 1 } @@ -134,8 +135,15 @@ detect_caps() { [ $(ls -1 /sys/class/hwmon | wc -l) -gt 0 ] && hdr_whitelist="${hdr_whitelist}|temperature" } -detect_caps +case $1 in +--all|-a) + all=1 + ;; +esac +[ "$all" ] || detect_caps + +[ "$all" ] || while [ "$1" ]; do case $1 in --include|-i) diff --git a/makefile b/makefile index 646a015..9d24542 100644 --- a/makefile +++ b/makefile @@ -24,7 +24,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 @@ -51,7 +51,7 @@ debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og debug: $(BIN) tests: - gcc $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run + $(CC) $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run $(TESTS_DIR)/run format: @@ -72,6 +72,6 @@ readme: $(BIN) man: $(BIN) awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ '/^USAGE/ { $$0=usage } 1' \ - doc/mojitos.pre.1 > doc/mojitos.1 2>/dev/null + doc/$(BIN).pre.1 > doc/$(BIN).1 2>/dev/null .PHONY: all clean mojitos debug format tests readme man diff --git a/tools/update-readme-usage.sh b/tools/update-readme-usage.sh index ad2f88f..2c1950e 100755 --- a/tools/update-readme-usage.sh +++ b/tools/update-readme-usage.sh @@ -8,8 +8,24 @@ try() { "$@" || die "cannot $*"; } yell() { echo "$0: $*" >&2; } echo() { printf '%s\n' "$*"; } -usage=$(./bin/mojitos) -[ -n "$usage" ] || die 'empty usage. try to recompile mojitos.' +try ./configure.sh --all +try make mojitos +usage=$( + ./bin/mojitos | + awk ' + /^SENSORS/ { + $0 = "" + printf "```\n" + printf "\n" + printf "The following is an exhaustive list of all the sensors (it is very likely\n" + printf "that one will not have all the sensors activated in his build):\n" + printf "```bash\n" + printf "SENSORS:" + } + { print } + ' +) +[ -n "$usage" ] || die 'empty usage. cannot continue.' try awk -v "usage=$usage" ' /^Usage/ { @@ -17,7 +33,11 @@ try awk -v "usage=$usage" ' del = 1 } { - if (del == 1) { + if (del == 1 || del == 2) { + if (match($0, "^```")) { + del++ + } + } else if (del == 3) { if (match($0, "^```")) { del = 0 print $0 -- GitLab From 83536ab019b525c21714b1650c5bc255efa454ca Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Feb 2023 18:02:56 +0100 Subject: [PATCH 166/229] the option to dump all options is now a long option --- makefile | 2 +- src/mojitos.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 9d24542..a197961 100644 --- a/makefile +++ b/makefile @@ -70,7 +70,7 @@ readme: $(BIN) sh ./tools/update-readme-usage.sh man: $(BIN) - awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ + awk -v "usage=$$($(BIN_DIR)/$(BIN) --dump-opts)" \ '/^USAGE/ { $$0=usage } 1' \ doc/$(BIN).pre.1 > doc/$(BIN).1 2>/dev/null diff --git a/src/mojitos.c b/src/mojitos.c index 4274b6a..e8cb6fa 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -23,6 +23,7 @@ #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <time.h> #include <unistd.h> #include "util.h" @@ -218,7 +219,7 @@ int main(int argc, char **argv) usage(argv); } - if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '1' && argv[1][2] == '\0') { + if (argc == 2 && strcmp(argv[1], "--dump-opts") == 0) { dumpopts(opts, NB_OPT, NB_SENSOR_OPT); exit(EXIT_SUCCESS); } -- GitLab From 5d36e20bd88712be509e2271c842411fc647f251 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Wed, 15 Feb 2023 19:08:53 +0100 Subject: [PATCH 167/229] remove bc(1) dependency in configure.sh --- configure.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.sh b/configure.sh index 3f82c3b..4f6375b 100755 --- a/configure.sh +++ b/configure.sh @@ -63,9 +63,9 @@ gen_sensors_h() { for sensor in $sensors; do sed -n 's/.*'"${sensor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${sensor}.h" done | - paste -s -d '+' | - bc + paste -s -d '+' ) + nb_sensor_opts=$(eval "echo \$(($nb_sensor_opts))") dprint sensors >&2 dprint nb_sensor_opts >&2 -- GitLab From af9d66eb766053d851018c3cad6e95ea29f680e0 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 168/229] 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 a985ebc78334dec2a3b32e5882d2effa8353598f 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 169/229] 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 6b48fb5..3f82c3b 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 343ec21..e8cb6fa 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 c9e0797..2c1950e 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 c24d82e19ac6b9587c00434ebcfffa188d6d61cd 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 170/229] 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 ac5b2d3..954e7e0 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,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 e3c98657d45ec85eaa22ba237c17f60410f43542 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 171/229] 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 954e7e0..869c358 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,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 d5978ba397b79ecc3442e96e10bdb62177b7f868 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 172/229] 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 8546c84fb3145e6dbbe80b035aa6afc5ac602b9d 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 173/229] 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 8e57326b26cd88dd37b615c1d19275bb4b1bf3f4 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 174/229] 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 c27d5e1f5677eba93117e50ec76d31bc0d8b7c13 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 175/229] clear doc --- makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index cd9be75..a197961 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 9edca7def641888d20204f5afb390434a5f33a5d Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Wed, 15 Feb 2023 19:08:53 +0100 Subject: [PATCH 176/229] remove bc(1) dependency in configure.sh --- configure.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.sh b/configure.sh index 3f82c3b..4f6375b 100755 --- a/configure.sh +++ b/configure.sh @@ -63,9 +63,9 @@ gen_sensors_h() { for sensor in $sensors; do sed -n 's/.*'"${sensor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${sensor}.h" done | - paste -s -d '+' | - bc + paste -s -d '+' ) + nb_sensor_opts=$(eval "echo \$(($nb_sensor_opts))") dprint sensors >&2 dprint nb_sensor_opts >&2 -- GitLab From de5e735b03a1b8820dd3d2df9bd62438bb1b8463 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Thu, 16 Feb 2023 18:24:28 +0100 Subject: [PATCH 177/229] add quotation marks --- configure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.sh b/configure.sh index 4f6375b..21c94ef 100755 --- a/configure.sh +++ b/configure.sh @@ -107,7 +107,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 From 82dc9a2e4bf08ff775bd255159fb04bb3e7346d5 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 20 Feb 2023 11:50:56 +0100 Subject: [PATCH 178/229] add some error checking --- src/network.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/network.c b/src/network.c index aee5659..0f23206 100644 --- a/src/network.c +++ b/src/network.c @@ -17,14 +17,17 @@ along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. *******************************************************/ -#include <unistd.h> +#include <errno.h> #include <fcntl.h> -#include <stdlib.h> +#include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <stdint.h> +#include <unistd.h> + #include "util.h" +#define NB_MAX_DEV 8 #define NB_SENSOR 4 static char *route = "/proc/net/route"; @@ -39,6 +42,8 @@ struct network_t { uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; char labels[NB_SENSOR][128]; + char dev[NB_MAX_DEV][128]; + int ndev; }; unsigned int _get_network(uint64_t *results, int *sources) @@ -103,7 +108,14 @@ unsigned int init_network(char *dev, void **ptr) char buffer2[256]; for (int i = 0; i < NB_SENSOR; i++) { snprintf(buffer2, sizeof(buffer2), filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); + errno = 0; + int fd = open(buffer2, O_RDONLY); + if (fd < 0) { + perror("init_network: open"); + free(state); + return 0; + } + state->sources[i] = fd; snprintf(state->labels[i], sizeof(state->labels[i]), _labels_network[i], dev); } -- GitLab From 1cb227e7cd0d3f6562d06f4266017176daca4ecc Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 20 Feb 2023 17:21:13 +0100 Subject: [PATCH 179/229] add MIN() and MAX() macros to util.h --- src/util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util.h b/src/util.h index 23978c1..b1fa6e3 100644 --- a/src/util.h +++ b/src/util.h @@ -38,6 +38,8 @@ exit(code); \ } while (0) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) /** * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, -- GitLab From 5b82667289ec077d9ed9c5658b72d572810fed08 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 20 Feb 2023 17:21:22 +0100 Subject: [PATCH 180/229] network sensor can now detect multiple routes from /proc/net/route note that there is a hard limit to the number of devices the sensor can watch. this limit is defined by "NB_MAX_DEV" (value of 8 for now) --- src/network.c | 170 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 125 insertions(+), 45 deletions(-) diff --git a/src/network.c b/src/network.c index 0f23206..33fdadf 100644 --- a/src/network.c +++ b/src/network.c @@ -38,18 +38,18 @@ char *_labels_network[NB_SENSOR] = { "%s:txb", }; struct network_t { - uint64_t values[NB_SENSOR]; - uint64_t tmp_values[NB_SENSOR]; - int sources[NB_SENSOR]; - char labels[NB_SENSOR][128]; - char dev[NB_MAX_DEV][128]; + uint64_t values[NB_MAX_DEV][NB_SENSOR]; + uint64_t tmp_values[NB_MAX_DEV][NB_SENSOR]; + int sources[NB_MAX_DEV][NB_SENSOR]; + char labels[NB_MAX_DEV][NB_SENSOR][128]; + char devs[NB_MAX_DEV][128]; int ndev; }; -unsigned int _get_network(uint64_t *results, int *sources) +static void _get_network(uint64_t *results, int *sources) { if (sources == NULL) { - return 0; + return; } char buffer[128]; @@ -62,16 +62,47 @@ unsigned int _get_network(uint64_t *results, int *sources) results[i] = strtoull(buffer, NULL, 10); } +} + +static int strchr_refill(int fd, char *buf, int len, char **s, char c) +{ + *s = strchr(*s, c); + + if (*s == NULL) { + int nbytes = read(fd, buf, len - 1); + if (nbytes < 0) { + perror("read"); + return -1; + } + buf[len - 1] = '\0'; + + /* whole file read */ + if (nbytes == 0) { + return 0; + } + + *s = strchr(buf, c); + } - return NB_SENSOR; + return 1; } unsigned int init_network(char *dev, void **ptr) { if (dev == NULL) { - return 0; + exit(1); } + 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)); + memset(state, '\0', sizeof(*state)); + if (strcmp(dev, "X") == 0) { int fd = open(route, O_RDONLY); @@ -83,59 +114,104 @@ unsigned int init_network(char *dev, void **ptr) char buffer[1000]; - if (read(fd, buffer, 999) < 0 ) { - perror("read"); + /* skip first line */ + char *s = buffer; + int ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\n'); + if (ret != 1) { close(fd); + free(state); exit(1); } + s++; - char *start_of_dev = strchr(buffer, '\n') + 1; - char *end_of_dev = strchr(start_of_dev, '\t'); - *end_of_dev = '\0'; - dev = start_of_dev; - close(fd); - } + char *start_of_dev = s; + /* jump to the end of the device name */ + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\t'); + if (ret != 1) { + close(fd); + free(state); + exit(1); + } - 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", - }; + state->ndev++; // ndev should be equal to 1 at this point + memcpy(&(state->devs[state->ndev - 1]), start_of_dev, + MIN((size_t)(sizeof(state->devs[0]) - 1), (size_t)(s - start_of_dev))); + + for (;;) { + /* jump to the next line */ + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\n'); + if (ret != 1) { + break; + } + s++; + + start_of_dev = s; + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\t'); + if (ret != 1) { + break; + } + + /* compare dev name to the previously saved one */ + if (strncmp(start_of_dev, state->devs[state->ndev - 1], s - start_of_dev) != 0) { + if (state->ndev >= NB_MAX_DEV) { + fprintf(stderr, "Maximum amount of network devices exceeded (%d).\n", NB_MAX_DEV); + break; + } + state->ndev++; + memcpy(&(state->devs[state->ndev - 1]), start_of_dev, + MIN((size_t)(sizeof(state->devs[0]) - 1), (size_t)(s - start_of_dev))); + } + } - struct network_t *state = malloc(sizeof(struct network_t)); + close(fd); + } else { + state->ndev = 1; + memcpy(&(state->devs[0]), dev, strlen(dev) + 1); + } char buffer2[256]; - for (int i = 0; i < NB_SENSOR; i++) { - snprintf(buffer2, sizeof(buffer2), filenames[i], dev); - errno = 0; - int fd = open(buffer2, O_RDONLY); - if (fd < 0) { - perror("init_network: open"); - free(state); - return 0; + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + snprintf(buffer2, sizeof(buffer2), filenames[j], state->devs[i]); + errno = 0; + int fd = open(buffer2, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "init_network: open: %s: %.*s\n", strerror(errno), + (int)sizeof(buffer2), buffer2); + free(state); + exit(1); + } + state->sources[i][j] = fd; + snprintf(state->labels[i][j], sizeof(state->labels[i][j]), _labels_network[j], + state->devs[i]); } - state->sources[i] = fd; - snprintf(state->labels[i], sizeof(state->labels[i]), _labels_network[i], dev); } *ptr = (void *) state; - _get_network(state->values, state->sources); - return NB_SENSOR; + for (int i = 0; i < state->ndev; i++) { + _get_network(state->values[i], state->sources[i]); + } + + return state->ndev * 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] = modulo_substraction(state->tmp_values[i], state->values[i]); + for (int i = 0; i < state->ndev; i++) { + _get_network(state->tmp_values[i], state->sources[i]); + + for (int j = 0; j < NB_SENSOR; j++) { + results[i*NB_SENSOR + j] = modulo_substraction(state->tmp_values[i][j], state->values[i][j]); + } + + memcpy(&(state->values[i]), &(state->tmp_values[i]), + NB_SENSOR * sizeof(state->values[i][0])); } - memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); - return NB_SENSOR; + return state->ndev * NB_SENSOR; } void clean_network(void *ptr) @@ -146,8 +222,10 @@ void clean_network(void *ptr) return; } - for (int i = 0; i < NB_SENSOR; i++) { - close(state->sources[i]); + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + close(state->sources[i][j]); + } } free(state); @@ -157,7 +235,9 @@ void label_network(char **labels, void *ptr) { struct network_t *state = (struct network_t *) ptr; - for (int i = 0; i < NB_SENSOR; i++) { - labels[i] = state->labels[i]; + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + labels[i*NB_SENSOR + j] = state->labels[i][j]; + } } } -- GitLab From a0c1db322c0c5e6525724a56998c6af634ef322e Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 21 Feb 2023 11:26:50 +0100 Subject: [PATCH 181/229] fix infiniband --- src/infiniband.c | 64 ++++++++++++++++++++++++++++++++++++++++++------ src/infiniband.h | 6 +++-- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/infiniband.c b/src/infiniband.c index aa4a8de..6a5a6b4 100644 --- a/src/infiniband.c +++ b/src/infiniband.c @@ -17,25 +17,44 @@ 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> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + #include "util.h" #define NB_SENSOR 4 -struct Network { +struct Infiniband { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; }; -typedef struct Network Network; +typedef struct Infiniband Infiniband; + +unsigned int _get_infiniband(uint64_t *results, int *sources) +{ + if (sources == NULL) { + return 0; + } + + char buffer[128]; -unsigned int _get_network(uint64_t *results, int *sources); + 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_infiniband(char *infi_path, void **ptr) { @@ -50,6 +69,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) glob("/sys/class/infiniband/*/ports/*/counters/", 0, NULL, &res); if (res.gl_pathc == 0) { + fprintf(stderr, "No infiniband found.\n"); return 0; } @@ -62,7 +82,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr) "%s/port_xmit_data" }; - Network *state = malloc(sizeof(Network)); + Infiniband *state = malloc(sizeof(Infiniband)); char buffer[1024]; for (int i = 0; i < NB_SENSOR; i++) { @@ -71,11 +91,39 @@ unsigned int init_infiniband(char *infi_path, void **ptr) } *ptr = (void *) state; - _get_network(state->values, state->sources); + _get_infiniband(state->values, state->sources); return NB_SENSOR; } +unsigned int get_infiniband(uint64_t *results, void *ptr) +{ + Infiniband *state = (Infiniband *) ptr; + _get_infiniband(state->tmp_values, state->sources); + + for (int i = 0; i < NB_SENSOR; i++) { + results[i] = modulo_substraction(state->tmp_values[i], state->values[i]); + } + + memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); + return NB_SENSOR; +} + +void clean_infiniband(void *ptr) +{ + Infiniband *state = (Infiniband *) ptr; + + if (state == NULL) { + return; + } + + for (int i = 0; i < NB_SENSOR; i++) { + close(state->sources[i]); + } + + free(state); +} + char *_labels_infiniband[NB_SENSOR] = {"irxp", "irxb", "itxp", "itxb"}; void label_infiniband(char **labels, void *none) { diff --git a/src/infiniband.h b/src/infiniband.h index e30d78b..8098cf5 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -19,12 +19,14 @@ *******************************************************/ unsigned int init_infiniband(char *infi_path, void **ptr); +unsigned int get_infiniband(uint64_t *results, void *ptr); +void clean_infiniband(void *ptr); void label_infiniband(char **labels, void *); Sensor infiniband = { .init = init_infiniband, - .get = NULL, - .clean = NULL, + .get = get_infiniband, + .clean = clean_infiniband, .label = label_infiniband, .nb_opt = 1, }; -- GitLab From afec2006a9bab8dfda94ef4ddb05d3c1708792c0 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 21 Feb 2023 16:03:02 +0100 Subject: [PATCH 182/229] add "install" and "uninstall" make targets --- makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index a197961..dc852f4 100644 --- a/makefile +++ b/makefile @@ -7,6 +7,7 @@ BIN_DIR = bin TESTS_DIR = tests BIN = mojitos +PREFIX = /usr/local CAPTOR_OBJ = @@ -74,4 +75,16 @@ man: $(BIN) '/^USAGE/ { $$0=usage } 1' \ doc/$(BIN).pre.1 > doc/$(BIN).1 2>/dev/null -.PHONY: all clean mojitos debug format tests readme man +install: $(BIN) man + mkdir -p $(PREFIX)/bin + cp $(BIN_DIR)/$(BIN) $(PREFIX)/bin/. + chmod 755 $(PREFIX)/bin/$(BIN) + mkdir -p $(PREFIX)/share/man/man1 + cp $(DOC_DIR)/$(BIN).1 $(PREFIX)/share/man/man1/. + chmod 644 $(PREFIX)/share/man/man1/$(BIN).1 + +uninstall: + rm -f $(PREFIX)/bin/$(BIN) + rm -f $(PREFIX)/share/man/man1/$(BIN).1 + +.PHONY: all clean mojitos debug format tests readme man install uninstall -- GitLab From 44b132bf26e445016c9bd6fb75373847d0188b03 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 21 Feb 2023 16:50:00 +0100 Subject: [PATCH 183/229] revise build system (makefile and sensors.mk) Make it more posix compliant (remove '%.o: %.c %.h' usage, which is not posix). Sadly, it appears to not support well separate directories for object and source files: inference rules do not work, and it recompiles everything at each invocation even though there is not necessarily any change within the source files. --- configure.sh | 5 +++++ makefile | 26 ++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/configure.sh b/configure.sh index 21c94ef..747a078 100755 --- a/configure.sh +++ b/configure.sh @@ -103,6 +103,11 @@ gen_sensors_mk() { printf '$(OBJ_DIR)/%s.o ' "$sensor" done printf '\n' + for sensor in $sensors; do + printf '$(OBJ_DIR)/%s.o: $(SRC_DIR)/%s.c $(SRC_DIR)/%s.h $(SRC_DIR)/util.h\n' \ + "$sensor" "$sensor" "$sensor" + printf '\t$(CC) $(CFLAGS) -c $< -o $@\n' + done } detect_caps() { diff --git a/makefile b/makefile index dc852f4..bd26308 100644 --- a/makefile +++ b/makefile @@ -9,14 +9,6 @@ TESTS_DIR = tests BIN = mojitos PREFIX = /usr/local -CAPTOR_OBJ = - -include ./sensors.mk - -OBJ = \ - $(CAPTOR_OBJ) \ - $(OBJ_DIR)/util.o - CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib CFLAGS = $(CPPFLAGS) -O3 -Werror @@ -24,9 +16,23 @@ LDFLAGS = ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q - all: $(BIN) man +CAPTOR_OBJ = + +include ./sensors.mk + +OBJ = \ + $(CAPTOR_OBJ) \ + $(OBJ_DIR)/util.o + +options: + @echo BIN: $(BIN) + @echo CC: $(CC) + @echo CFLAGS: $(CFLAGS) + @echo LDFLAGS: $(LDFLAGS) + @echo OBJ: $(OBJ) + $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o @@ -36,7 +42,7 @@ $(OBJ_DIR)/counters.o: $(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)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h $(CC) $(CFLAGS) -c $< -o $@ $(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh -- GitLab From 745d90b59eadf5e4072c8a6a3ed86d745a674d2a Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Feb 2023 18:58:48 +0100 Subject: [PATCH 184/229] unfinished sensor --- src/nvidia_gpu.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++ src/nvidia_gpu.h | 0 2 files changed, 324 insertions(+) create mode 100644 src/nvidia_gpu.c create mode 100644 src/nvidia_gpu.h diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c new file mode 100644 index 0000000..75f0915 --- /dev/null +++ b/src/nvidia_gpu.c @@ -0,0 +1,324 @@ +#include <stdio.h> +#include <stdint.h> +#include <nvml.h> +#include <stdlib.h> +#include <string.h> + +#include "util.h" + + +// -----------------------------SENSOR_KIND +typedef enum { + CLOCK_SENSOR = 0, + MEMORY_SENSOR = 1, + UTILIZATION_SENSOR = 2, + + COUNT_SENSOR = 3, +} SENSOR_KIND; + +typedef unsigned int (Initializer) (nvmlDevice_t, void **); +typedef unsigned int (Getter) (nvmlDevice_t, uint64_t *, void *); +typedef void (Cleaner) (void *); + +typedef struct { + void *data; + + Initializer *init; + Getter *get; + Cleaner *clean; +} ISensor; + +// ----------------------------CLOCK_SENSOR +// -- All existing clocks +#if NVML_CLOCK_COUNT != 4 +#error "NVML_CLOCK_COUNT must be equal 4"; +#endif + +// -- SM : Streaming Multiprocessor +static const nvmlClockType_t clocks[NVML_CLOCK_COUNT] = {NVML_CLOCK_GRAPHICS, NVML_CLOCK_SM, NVML_CLOCK_MEM, NVML_CLOCK_VIDEO}; +static const char *clock_names[NVML_CLOCK_COUNT] = {"Graphics", "SM", "Memory", "Video"}; + +// -- Must contain the clocks compatible with the device +typedef struct { + nvmlClockType_t clocks[NVML_CLOCK_COUNT]; + unsigned int count; +} ClockData; + +unsigned int init_clock_sensor(nvmlDevice_t device, void** data) +{ + ClockData tmp = {0}; + nvmlReturn_t result; + unsigned int clock; + + // -- Test all clocks + for (unsigned int i = 0; i < NVML_CLOCK_COUNT; i++) { + if ((result = nvmlDeviceGetClockInfo(device, clocks[i], &clock)) == NVML_SUCCESS) { + tmp.clocks[tmp.count] = clocks[i]; + tmp.count += 1; + } else { + fprintf(stderr, "Failed to get %s clock : %s", clock_names[i], nvmlErrorString(result)); + } + } + + // -- No clock avaible + if (tmp.count == 0) { + return 0; + } + + *data = calloc(1, sizeof(ClockData)); + memcpy(*data, &tmp, sizeof (ClockData)); + return tmp.count; +} + +unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data) +{ + ClockData *clock_data = (ClockData *) data; + nvmlReturn_t err; + unsigned int clock; + + for (unsigned int i = 0; i < clock_data->count; i++) { + nvmlClockType_t clock_type = clock_data->clocks[i]; + + if((err = nvmlDeviceGetClockInfo(device, clock_type, &clock)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get %s clock : %s", clock_names[clock_type], nvmlErrorString(err)); + exit(99); + } + results[i] = clock; + } + return clock_data->count; +} + +void clean_clock_sensor(void* data) +{ + free(data); +} + +// ---------------------------MEMORY_SENSOR +typedef enum { + FREE_MEMORY = 0U, + USED_MEMORY = 1U, + TOTAL_MEMORY = 2U, + + COUNT_MEMORY = 3U, +} MemoryKind; +static const char *memory_names[COUNT_MEMORY] = {"Free", "Used", "Total"}; + +unsigned int init_memory_sensor(nvmlDevice_t device, void **none) +{ + UNUSED(none); + + nvmlMemory_t memory; + nvmlReturn_t result; + if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + return 0; + } + + return COUNT_MEMORY; +} + +unsigned int get_memory_sensor(nvmlDevice_t device, uint64_t *results, void *none) +{ + UNUSED(none); + + nvmlMemory_t memory; + nvmlReturn_t result; + if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + exit(99); + } + + results[FREE_MEMORY] = memory.free; + results[USED_MEMORY] = memory.used; + results[TOTAL_MEMORY] = memory.total; + return COUNT_MEMORY; +} + + +void clean_memory_sensor(void *none) +{ + UNUSED(none); +} + +// ----------------------UTILIZATION_SENSOR +typedef enum { + GPU_UTILIZATION = 0U, + MEMORY_UTILIZATION = 1U, + + COUNT_UTILIZATION = 2U, +} UtilizationKind; + +static const char *utilization_names[COUNT_UTILIZATION] = {"Gpu", "Memory"}; + +unsigned int init_utilization_sensor(nvmlDevice_t device, void **none); +{ + UNUSED(none); + + nvmlReturn_t result; + nvmlUtilization_t utilization; + if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + return 0; + } + + return COUNT_UTILIZATION; +} + +unsigned int get_utilization_sensor(nvmlDevice_t device, uint64_t *results, void* none) +{ + UNUSED(none); + + nvmlReturn_t result; + nvmlUtilization_t utilization; + if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + exit(99); + } + + results[GPU_UTILIZATION] = utilization.gpu; + results[MEMORY_UTILIZATION] = utilization.memory; + return COUNT_UTILIZATION; +} + +void clean_utilization_sensor(void* none) +{ + UNUSED(none); +} + +// ----------------------------ERROR_SENSOR +// TODO + +// ---------------------------------------- + +typedef struct { + char name[NVML_DEVICE_NAME_BUFFER_SIZE]; + nvmlDevice_t device; + + ISensor sensors[COUNT_SENSOR]; + unsigned int count; +} Device; + +typedef struct { + Device *devices; + unsigned int count; +} NvidiaSensor; + +// -------------------------AVAIBLE_SENSORS +static const ISensor avaible_sensors[COUNT_SENSOR] = { + {.init = init_clock_sensor, .get = get_clock_sensor, .clean = clean_memory_sensor, .data = NULL}; + {.init = init_memory_sensor, .get = get_memory_sensor, .clean = clean_memory_sensor, .data = NULL}; + {.init = init_utilization_sensor, .get = get_utilization_sensor, .clean = clean_memory_sensor, .data = NULL}; +}; + +// ------------------------DEVICE_FUNCTIONS + +unsigned int init_device(unsigned int device_idx, Device *device) { + nvmlReturn_t result; + nvmlDevice_t nvml_device; + if ((result = nvmlDeviceGetByIndex(i, &nvml_device) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device handle for device %d: %s\n", device_idx, nvmlErrorString(result)); + return 0; + } + + if ((result = nvmlDeviceGetName(nvml_device, device->name, NVML_DEVICE_NAME_BUFFER_SIZE))) { + fprintf(stderr, "Failed to get device name for device %d: %s\n", device_idx, nvmlErrorString(result)); + return 0; + } + + unsigned int count = 0; + for (unsigned int i = 0; i < COUNT_SENSOR; i++) { + void* data; + if (avaible_sensors.init(nvml_device, &data) != 0) { + ISensor *sensor = &device->sensors[count]; + memcpy(sensor, &avaible_sensors[i], sizeof(ISensor)); + sensor->data = data; + count += 1; + } + } + + device->device = nvml_device; + device->count = count; + return count; +} + +unsigned int get_device(Device *device, uint64_t *results) { + unsigned int count; + nvmlDevice_t nvml_device = device->device; + for (unsigned int i = 0; i < device->count; i++) { + unsigned int result = device->sensor.get(nvml_device, &device->sensor.data, results); + count += result; + results += result; + } + + return count; +} +void clean_device(Device *device) { + for (unsigned int i = 0; i < device->count; i++) { + device->sensor.clean(&device->sensor.data); + } +} + +// ------------------------NVIDIA_INTERFACE + +unsigned int init_nvidia_sensor(char *none, void **ptr) +{ + UNUSED(none); + UNUSED(ptr); + + nvmlReturn_t result; + if ((result = nvmlInit()) != NVML_SUCCESS) { + fprintf(stderr, "Failed to initialize NVML: %s\n", nvmlErrorString(result)); + exit(1); + } + + unsigned int avaible_device_count; + if ((result = nvmlDeviceGetCount(&avaible_device_count)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device count : %s\n", nvmlErrorString(result)); + nvmlShutdown(); + exit(1); + } + + Device* devices = calloc(avaible_device_count, sizeof(Device)); + + unsigned int sensor_count = 0; + unsigned int device_count = 0; + for (unsigned int i = 0; i < avaible_device_count; i++) { + unsigned int initialized_count; + if ((initialized_count = init_device(&devices[device_count])) != 0) { + sensor_count += initialized_count; + device_count += 1; + } + } + + NvidiaSensor *nvidia = (NvidiaSensor*) calloc(1, sizeof(NvidiaSensor)); + nvidia->devices = devices; + nvidia->count = device_count; + + *ptr = (void*) nvidia; + return count; +} + + +unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) { + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + unsigned count = 0; + + for (unsigned int i = 0; i < nvidia.count; i++) { + unsigned int result = get_device(&nvidia->devices[i], results); + results += result; + count += result; + } + + return count; +} +void label_nvidia_sensor(char **labels, void *ptr); + +void clean_nvidia_sensor(void *ptr) +{ + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + + for (unsigned int i = 0; i < nvidia->count; i++) { + clean_device(&nvidia->device[i]); + } + nvmlShutdown(); +} diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h new file mode 100644 index 0000000..e69de29 -- GitLab From 54bba401354dcbfc30804bea721e9a563b50c778 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 6 Mar 2023 15:20:44 +0100 Subject: [PATCH 185/229] working sensor --- src/nvidia_gpu.c | 345 ++++++++++++++++++++++++++++++++++++----------- src/nvidia_gpu.h | 43 ++++++ 2 files changed, 309 insertions(+), 79 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 75f0915..22f65a1 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.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 <stdio.h> #include <stdint.h> #include <nvml.h> @@ -6,7 +26,6 @@ #include "util.h" - // -----------------------------SENSOR_KIND typedef enum { CLOCK_SENSOR = 0, @@ -16,47 +35,82 @@ typedef enum { COUNT_SENSOR = 3, } SENSOR_KIND; -typedef unsigned int (Initializer) (nvmlDevice_t, void **); -typedef unsigned int (Getter) (nvmlDevice_t, uint64_t *, void *); -typedef void (Cleaner) (void *); +typedef struct Device Device; +typedef struct NvidiaSensor NvidiaSensor; +typedef struct ISensor ISensor; +typedef struct Sensor Sensor; -typedef struct { - void *data; +// -- Sensor interface +typedef unsigned int (Initializer) (const Device *, void **); +typedef unsigned int (Getter) (uint64_t *, const Device *, void *); +typedef unsigned int (Labeller) (char **, void *); +typedef void (Cleaner) (void *); +struct ISensor { Initializer *init; Getter *get; + Labeller *label; Cleaner *clean; -} ISensor; +}; + +// -- Sensor +struct Sensor { + void *data; + const ISensor *fun; +}; + +// -- Device: represents a gpu +struct Device { + char name[NVML_DEVICE_NAME_BUFFER_SIZE]; + nvmlDevice_t device; + unsigned int idx; + + Sensor sensors[COUNT_SENSOR]; + unsigned int count; +}; + +// -- NvidiaSensor: represents the devices +struct NvidiaSensor { + Device *devices; + unsigned int count; +}; + +// -- Label template +static const char *label_template = "gpu%u_%s_%s"; // ----------------------------CLOCK_SENSOR -// -- All existing clocks -#if NVML_CLOCK_COUNT != 4 -#error "NVML_CLOCK_COUNT must be equal 4"; -#endif +#define CLOCK_LABEL_SIZE 25 + +// -- All existing clocks // -- SM : Streaming Multiprocessor static const nvmlClockType_t clocks[NVML_CLOCK_COUNT] = {NVML_CLOCK_GRAPHICS, NVML_CLOCK_SM, NVML_CLOCK_MEM, NVML_CLOCK_VIDEO}; -static const char *clock_names[NVML_CLOCK_COUNT] = {"Graphics", "SM", "Memory", "Video"}; +static const char *clock_names[NVML_CLOCK_COUNT] = {"graphics", "sm", "memory", "video"}; +static const char *clock_base_name = "clk"; // -- Must contain the clocks compatible with the device typedef struct { nvmlClockType_t clocks[NVML_CLOCK_COUNT]; + char labels[NVML_CLOCK_COUNT][CLOCK_LABEL_SIZE]; unsigned int count; } ClockData; -unsigned int init_clock_sensor(nvmlDevice_t device, void** data) +unsigned int init_clock_sensor(const Device *device, void **data) { + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; ClockData tmp = {0}; nvmlReturn_t result; unsigned int clock; // -- Test all clocks for (unsigned int i = 0; i < NVML_CLOCK_COUNT; i++) { - if ((result = nvmlDeviceGetClockInfo(device, clocks[i], &clock)) == NVML_SUCCESS) { + if ((result = nvmlDeviceGetClockInfo(nvml_device, clocks[i], &clock)) == NVML_SUCCESS) { + snprintf(tmp.labels[tmp.count], CLOCK_LABEL_SIZE, label_template, device_idx, clock_base_name, clock_names[i]); tmp.clocks[tmp.count] = clocks[i]; tmp.count += 1; } else { - fprintf(stderr, "Failed to get %s clock : %s", clock_names[i], nvmlErrorString(result)); + fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[i], nvmlErrorString(result)); } } @@ -70,8 +124,9 @@ unsigned int init_clock_sensor(nvmlDevice_t device, void** data) return tmp.count; } -unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data) +unsigned int get_clock_sensor(uint64_t *results, const Device *device, void *data) { + const nvmlDevice_t nvml_device = device->device; ClockData *clock_data = (ClockData *) data; nvmlReturn_t err; unsigned int clock; @@ -79,8 +134,8 @@ unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data for (unsigned int i = 0; i < clock_data->count; i++) { nvmlClockType_t clock_type = clock_data->clocks[i]; - if((err = nvmlDeviceGetClockInfo(device, clock_type, &clock)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get %s clock : %s", clock_names[clock_type], nvmlErrorString(err)); + if((err = nvmlDeviceGetClockInfo(nvml_device, clock_type, &clock)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[clock_type], nvmlErrorString(err)); exit(99); } results[i] = clock; @@ -88,42 +143,69 @@ unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data return clock_data->count; } -void clean_clock_sensor(void* data) +unsigned int label_clock_sensor(char **labels, void *data) +{ + ClockData *clock_data = (ClockData *) data; + + for (unsigned int i = 0; i < clock_data->count; i++) { + labels[i] = clock_data->labels[i]; + } + + return clock_data->count; +} + +void clean_clock_sensor(void *data) { free(data); } // ---------------------------MEMORY_SENSOR +#define MEMORY_LABEL_SIZE 25 + typedef enum { FREE_MEMORY = 0U, USED_MEMORY = 1U, TOTAL_MEMORY = 2U, - + COUNT_MEMORY = 3U, } MemoryKind; -static const char *memory_names[COUNT_MEMORY] = {"Free", "Used", "Total"}; -unsigned int init_memory_sensor(nvmlDevice_t device, void **none) +static const char *memory_names[COUNT_MEMORY] = {"free", "used", "total"}; +static const char *memory_base_name = "mem"; + +typedef struct { + char labels[COUNT_MEMORY][MEMORY_LABEL_SIZE]; +} MemoryData; + +unsigned int init_memory_sensor(const Device *device, void **data) { - UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; nvmlMemory_t memory; nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); return 0; } + MemoryData *memory_data = (MemoryData *) calloc(1, sizeof(MemoryData)); + for (unsigned int i = 0; i < COUNT_MEMORY; i++) { + snprintf(memory_data->labels[i], MEMORY_LABEL_SIZE, label_template, device_idx, memory_base_name, memory_names[i]); + } + + *data = (void *) memory_data; return COUNT_MEMORY; } -unsigned int get_memory_sensor(nvmlDevice_t device, uint64_t *results, void *none) +unsigned int get_memory_sensor(uint64_t *results, const Device *device, void *none) { UNUSED(none); + const nvmlDevice_t nvml_device = device->device; nvmlMemory_t memory; nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); exit(99); } @@ -135,12 +217,23 @@ unsigned int get_memory_sensor(nvmlDevice_t device, uint64_t *results, void *non } -void clean_memory_sensor(void *none) +unsigned int label_memory_sensor(char **labels, void* data) { - UNUSED(none); + MemoryData *memory_data = (MemoryData *) data; + + for (unsigned int i = 0; i < COUNT_MEMORY; i++) { + labels[i] = memory_data->labels[i]; + } + + return COUNT_MEMORY; +} +void clean_memory_sensor(void *data) +{ + free(data); } // ----------------------UTILIZATION_SENSOR +#define UTILIZATION_LABEL_SIZE 35 typedef enum { GPU_UTILIZATION = 0U, MEMORY_UTILIZATION = 1U, @@ -148,29 +241,42 @@ typedef enum { COUNT_UTILIZATION = 2U, } UtilizationKind; -static const char *utilization_names[COUNT_UTILIZATION] = {"Gpu", "Memory"}; +typedef struct { + char labels[COUNT_UTILIZATION][UTILIZATION_LABEL_SIZE]; +} UtilizationData; + +static const char *utilization_names[COUNT_UTILIZATION] = {"gpu", "memory"}; +static const char *utilization_base_name = "utilization"; -unsigned int init_utilization_sensor(nvmlDevice_t device, void **none); +unsigned int init_utilization_sensor(const Device *device, void **data) { - UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; nvmlReturn_t result; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); return 0; } + UtilizationData *utilization_data = (UtilizationData *) calloc(1, sizeof(UtilizationData)); + for (unsigned int i = 0; i < COUNT_UTILIZATION; i++) { +snprintf(utilization_data->labels[i], UTILIZATION_LABEL_SIZE, label_template, device_idx, utilization_base_name, utilization_names[i]); + } + + *data = (void *) utilization_data; return COUNT_UTILIZATION; } -unsigned int get_utilization_sensor(nvmlDevice_t device, uint64_t *results, void* none) +unsigned int get_utilization_sensor(uint64_t *results, const Device *device, void *none) { UNUSED(none); + const nvmlDevice_t nvml_device = device->device; nvmlReturn_t result; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); exit(99); } @@ -180,9 +286,19 @@ unsigned int get_utilization_sensor(nvmlDevice_t device, uint64_t *results, void return COUNT_UTILIZATION; } -void clean_utilization_sensor(void* none) +unsigned int label_utilization_sensor(char **labels, void* data) { - UNUSED(none); + UtilizationData *utilization_data = (UtilizationData *) data; + + for (unsigned int i = 0; i < COUNT_UTILIZATION; i++) { + labels[i] = utilization_data->labels[i]; + } + + return COUNT_UTILIZATION; +} +void clean_utilization_sensor(void *data) +{ + free(data); } // ----------------------------ERROR_SENSOR @@ -190,32 +306,21 @@ void clean_utilization_sensor(void* none) // ---------------------------------------- -typedef struct { - char name[NVML_DEVICE_NAME_BUFFER_SIZE]; - nvmlDevice_t device; - - ISensor sensors[COUNT_SENSOR]; - unsigned int count; -} Device; - -typedef struct { - Device *devices; - unsigned int count; -} NvidiaSensor; // -------------------------AVAIBLE_SENSORS static const ISensor avaible_sensors[COUNT_SENSOR] = { - {.init = init_clock_sensor, .get = get_clock_sensor, .clean = clean_memory_sensor, .data = NULL}; - {.init = init_memory_sensor, .get = get_memory_sensor, .clean = clean_memory_sensor, .data = NULL}; - {.init = init_utilization_sensor, .get = get_utilization_sensor, .clean = clean_memory_sensor, .data = NULL}; + {.init = init_clock_sensor, .get = get_clock_sensor, .label = label_clock_sensor, .clean = clean_clock_sensor}, + {.init = init_memory_sensor, .get = get_memory_sensor, .label = label_memory_sensor, .clean = clean_memory_sensor}, + {.init = init_utilization_sensor, .get = get_utilization_sensor, .label = label_utilization_sensor, .clean = clean_utilization_sensor}, }; // ------------------------DEVICE_FUNCTIONS -unsigned int init_device(unsigned int device_idx, Device *device) { +unsigned int init_device(unsigned int device_idx, Device *device) +{ nvmlReturn_t result; nvmlDevice_t nvml_device; - if ((result = nvmlDeviceGetByIndex(i, &nvml_device) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetHandleByIndex(device_idx, &nvml_device)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device handle for device %d: %s\n", device_idx, nvmlErrorString(result)); return 0; } @@ -225,39 +330,62 @@ unsigned int init_device(unsigned int device_idx, Device *device) { return 0; } - unsigned int count = 0; + device->device = nvml_device; + device->idx = device_idx; + + unsigned int sensor_count = 0; + unsigned int total_count = 0; + for (unsigned int i = 0; i < COUNT_SENSOR; i++) { - void* data; - if (avaible_sensors.init(nvml_device, &data) != 0) { - ISensor *sensor = &device->sensors[count]; - memcpy(sensor, &avaible_sensors[i], sizeof(ISensor)); - sensor->data = data; - count += 1; + Sensor *sensor = &device->sensors[sensor_count]; + sensor->fun = &avaible_sensors[i]; + unsigned int count; + + if ((count = sensor->fun->init(device, &sensor->data)) != 0) { + sensor_count += 1; + total_count += count; } } - device->device = nvml_device; - device->count = count; - return count; + device->count = sensor_count; + return total_count; } -unsigned int get_device(Device *device, uint64_t *results) { - unsigned int count; - nvmlDevice_t nvml_device = device->device; +unsigned int get_device(uint64_t *results, Device *device) +{ + unsigned int count = 0; for (unsigned int i = 0; i < device->count; i++) { - unsigned int result = device->sensor.get(nvml_device, &device->sensor.data, results); + Sensor *sensor = &device->sensors[i]; + unsigned int result = sensor->fun->get(results, device, sensor->data); count += result; results += result; } return count; } -void clean_device(Device *device) { + +unsigned int label_device(char **labels, Device *device) +{ + unsigned int count = 0; + for (unsigned int i = 0; i < device->count; i++) { + Sensor *sensor = &device->sensors[i]; + unsigned int result = sensor->fun->label(labels, sensor->data); + labels += result; + count += result; + } + + return count; +} + +void clean_device(Device *device) +{ for (unsigned int i = 0; i < device->count; i++) { - device->sensor.clean(&device->sensor.data); + Sensor *sensor = &device->sensors[i]; + sensor->fun->clean(sensor->data); } } + // ------------------------NVIDIA_INTERFACE unsigned int init_nvidia_sensor(char *none, void **ptr) @@ -278,47 +406,106 @@ unsigned int init_nvidia_sensor(char *none, void **ptr) exit(1); } - Device* devices = calloc(avaible_device_count, sizeof(Device)); + Device *devices = calloc(avaible_device_count, sizeof(Device)); unsigned int sensor_count = 0; unsigned int device_count = 0; for (unsigned int i = 0; i < avaible_device_count; i++) { unsigned int initialized_count; - if ((initialized_count = init_device(&devices[device_count])) != 0) { + if ((initialized_count = init_device(i, &devices[device_count])) != 0) { sensor_count += initialized_count; device_count += 1; } } - NvidiaSensor *nvidia = (NvidiaSensor*) calloc(1, sizeof(NvidiaSensor)); + NvidiaSensor *nvidia = (NvidiaSensor *) calloc(1, sizeof(NvidiaSensor)); nvidia->devices = devices; nvidia->count = device_count; - *ptr = (void*) nvidia; - return count; + *ptr = (void *) nvidia; + return sensor_count; } -unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) { +unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) +{ NvidiaSensor *nvidia = (NvidiaSensor *) ptr; unsigned count = 0; - for (unsigned int i = 0; i < nvidia.count; i++) { - unsigned int result = get_device(&nvidia->devices[i], results); + for (unsigned int i = 0; i < nvidia->count; i++) { + unsigned int result = get_device(results, &nvidia->devices[i]); results += result; count += result; } return count; } -void label_nvidia_sensor(char **labels, void *ptr); + +unsigned int label_nvidia_sensor(char **labels, void *ptr) { + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + unsigned count = 0; + + for (unsigned int i = 0; i < nvidia->count; i++) { + unsigned int result = label_device(labels, &nvidia->devices[i]); + labels += result; + count += result; + } + + return count; +} void clean_nvidia_sensor(void *ptr) { NvidiaSensor *nvidia = (NvidiaSensor *) ptr; for (unsigned int i = 0; i < nvidia->count; i++) { - clean_device(&nvidia->device[i]); + clean_device(&nvidia->devices[i]); } + + free(nvidia->devices); + free(nvidia); nvmlShutdown(); } + +// -------------------------------TEST_MAIN + +#ifdef __NVIDIA__MAIN__TEST +int main() +{ + void *ptr = NULL; + char *none = NULL; + + unsigned int sensor_count = init_nvidia_sensor(none, &ptr); + + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + printf("%d\n", nvidia->count); + printf("%u\n", sensor_count); + + + + uint64_t results[sensor_count]; + char *labels[sensor_count]; + + memset(results, 0, sensor_count * sizeof(uint64_t)); + memset(labels, 0, sensor_count * sizeof(char**)); + + + unsigned count_label = label_nvidia_sensor(labels, ptr); + unsigned count_get = get_nvidia_sensor(results, ptr); + printf("total : %u, get : %u, label : %u\n", sensor_count, count_get, count_label); + + + for (unsigned int i = 0; i < sensor_count; i++) { + printf("%s ", labels[i]); + } + printf("\n"); + for (unsigned int i = 0; i < sensor_count; i++) { + printf("%lu ", results[i]); + } + printf("\n"); + printf("sensor_count: %d\n", sensor_count); + + clean_nvidia_sensor(ptr); +} +#endif + diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index e69de29..6f2419e 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -0,0 +1,43 @@ +/******************************************************* + 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_nvidia_sensor(char *, void **); +unsigned int get_nvidia_sensor(uint64_t *results, void *); +void clean_nvidia_sensor(void *); +void label_nvidia_sensor(char **labels, void *); + + +Sensor nvidia_gpu = { + .init = init_nvidia_sensor, + .get = get_nvidia_sensor, + .clean = clean_nvidia_sensor, + .label = label_nvidia_sensor, + .nb_opt = 1, +}; + +Optparse nvidia_gpu_opt[1] = { + { + .longname = "nvidia", + .shortname = 'n', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "NVIDIA GPU", + }, +}; -- GitLab From 5b6f0ec8b3ac06859e2f5294e1210ddefdb393de Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 6 Mar 2023 15:51:47 +0100 Subject: [PATCH 186/229] pedantic --- src/nvidia_gpu.c | 55 ++++++++++++++++++++++++++---------------------- src/nvidia_gpu.h | 18 ++++++++-------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 22f65a1..479eecb 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -20,10 +20,14 @@ #include <stdio.h> #include <stdint.h> -#include <nvml.h> #include <stdlib.h> #include <string.h> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#include <nvml.h> +#pragma GCC diagnostic pop + #include "util.h" // -----------------------------SENSOR_KIND @@ -36,7 +40,7 @@ typedef enum { } SENSOR_KIND; typedef struct Device Device; -typedef struct NvidiaSensor NvidiaSensor; +typedef struct NvidiaGpu NvidiaGpu; typedef struct ISensor ISensor; typedef struct Sensor Sensor; @@ -69,8 +73,8 @@ struct Device { unsigned int count; }; -// -- NvidiaSensor: represents the devices -struct NvidiaSensor { +// -- NvidiaGpu: represents the devices +struct NvidiaGpu { Device *devices; unsigned int count; }; @@ -217,7 +221,7 @@ unsigned int get_memory_sensor(uint64_t *results, const Device *device, void *no } -unsigned int label_memory_sensor(char **labels, void* data) +unsigned int label_memory_sensor(char **labels, void *data) { MemoryData *memory_data = (MemoryData *) data; @@ -229,7 +233,7 @@ unsigned int label_memory_sensor(char **labels, void* data) } void clean_memory_sensor(void *data) { - free(data); + free(data); } // ----------------------UTILIZATION_SENSOR @@ -242,7 +246,7 @@ typedef enum { } UtilizationKind; typedef struct { - char labels[COUNT_UTILIZATION][UTILIZATION_LABEL_SIZE]; + char labels[COUNT_UTILIZATION][UTILIZATION_LABEL_SIZE]; } UtilizationData; static const char *utilization_names[COUNT_UTILIZATION] = {"gpu", "memory"}; @@ -262,7 +266,7 @@ unsigned int init_utilization_sensor(const Device *device, void **data) UtilizationData *utilization_data = (UtilizationData *) calloc(1, sizeof(UtilizationData)); for (unsigned int i = 0; i < COUNT_UTILIZATION; i++) { -snprintf(utilization_data->labels[i], UTILIZATION_LABEL_SIZE, label_template, device_idx, utilization_base_name, utilization_names[i]); + snprintf(utilization_data->labels[i], UTILIZATION_LABEL_SIZE, label_template, device_idx, utilization_base_name, utilization_names[i]); } *data = (void *) utilization_data; @@ -286,7 +290,7 @@ unsigned int get_utilization_sensor(uint64_t *results, const Device *device, voi return COUNT_UTILIZATION; } -unsigned int label_utilization_sensor(char **labels, void* data) +unsigned int label_utilization_sensor(char **labels, void *data) { UtilizationData *utilization_data = (UtilizationData *) data; @@ -388,7 +392,7 @@ void clean_device(Device *device) // ------------------------NVIDIA_INTERFACE -unsigned int init_nvidia_sensor(char *none, void **ptr) +unsigned int init_nvidia_gpu(char *none, void **ptr) { UNUSED(none); UNUSED(ptr); @@ -418,7 +422,7 @@ unsigned int init_nvidia_sensor(char *none, void **ptr) } } - NvidiaSensor *nvidia = (NvidiaSensor *) calloc(1, sizeof(NvidiaSensor)); + NvidiaGpu *nvidia = (NvidiaGpu *) calloc(1, sizeof(NvidiaGpu)); nvidia->devices = devices; nvidia->count = device_count; @@ -427,9 +431,9 @@ unsigned int init_nvidia_sensor(char *none, void **ptr) } -unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) +unsigned int get_nvidia_gpu(uint64_t *results, void *ptr) { - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; unsigned count = 0; for (unsigned int i = 0; i < nvidia->count; i++) { @@ -441,8 +445,9 @@ unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) return count; } -unsigned int label_nvidia_sensor(char **labels, void *ptr) { - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; +unsigned int label_nvidia_gpu(char **labels, void *ptr) +{ + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; unsigned count = 0; for (unsigned int i = 0; i < nvidia->count; i++) { @@ -454,9 +459,9 @@ unsigned int label_nvidia_sensor(char **labels, void *ptr) { return count; } -void clean_nvidia_sensor(void *ptr) +void clean_nvidia_gpu(void *ptr) { - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; for (unsigned int i = 0; i < nvidia->count; i++) { clean_device(&nvidia->devices[i]); @@ -475,26 +480,26 @@ int main() void *ptr = NULL; char *none = NULL; - unsigned int sensor_count = init_nvidia_sensor(none, &ptr); + unsigned int sensor_count = init_nvidia_gpu(none, &ptr); - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; printf("%d\n", nvidia->count); printf("%u\n", sensor_count); - + uint64_t results[sensor_count]; char *labels[sensor_count]; memset(results, 0, sensor_count * sizeof(uint64_t)); - memset(labels, 0, sensor_count * sizeof(char**)); + memset(labels, 0, sensor_count * sizeof(char **)); - unsigned count_label = label_nvidia_sensor(labels, ptr); - unsigned count_get = get_nvidia_sensor(results, ptr); + unsigned count_label = label_nvidia_gpu(labels, ptr); + unsigned count_get = get_nvidia_gpu(results, ptr); printf("total : %u, get : %u, label : %u\n", sensor_count, count_get, count_label); - + for (unsigned int i = 0; i < sensor_count; i++) { printf("%s ", labels[i]); } @@ -505,7 +510,7 @@ int main() printf("\n"); printf("sensor_count: %d\n", sensor_count); - clean_nvidia_sensor(ptr); + clean_nvidia_gpu(ptr); } #endif diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index 6f2419e..c741055 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -18,23 +18,23 @@ *******************************************************/ -unsigned int init_nvidia_sensor(char *, void **); -unsigned int get_nvidia_sensor(uint64_t *results, void *); -void clean_nvidia_sensor(void *); -void label_nvidia_sensor(char **labels, void *); +unsigned int init_nvidia_gpu(char *, void **); +unsigned int get_nvidia_gpu(uint64_t *results, void *); +void clean_nvidia_gpu(void *); +void label_nvidia_gpu(char **labels, void *); Sensor nvidia_gpu = { - .init = init_nvidia_sensor, - .get = get_nvidia_sensor, - .clean = clean_nvidia_sensor, - .label = label_nvidia_sensor, + .init = init_nvidia_gpu, + .get = get_nvidia_gpu, + .clean = clean_nvidia_gpu, + .label = label_nvidia_gpu, .nb_opt = 1, }; Optparse nvidia_gpu_opt[1] = { { - .longname = "nvidia", + .longname = "nvidia-gpu", .shortname = 'n', .argtype = OPTPARSE_NONE, .usage_arg = NULL, -- GitLab From 5c6076ad0729836751c1a1284357d69a9e26bf46 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 7 Mar 2023 09:04:34 +0100 Subject: [PATCH 187/229] temp change of the make file --- makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index a197961..81a4e41 100644 --- a/makefile +++ b/makefile @@ -17,9 +17,9 @@ OBJ = \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib -I/usr/local/cuda/include CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS = +LDFLAGS = -L/usr/local/cuda/lib64 -lnvidia-ml ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q @@ -27,7 +27,7 @@ ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q all: $(BIN) man $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o - $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o + $(CC) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o $(LDFLAGS) $(OBJ): $(OBJ_DIR) $(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h -- GitLab From 8709019f8d0c1c986ec94ce25792d7942b2ece87 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 7 Mar 2023 11:36:46 +0100 Subject: [PATCH 188/229] compare new dev name to all saved ones --- src/network.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/network.c b/src/network.c index 33fdadf..cea2a89 100644 --- a/src/network.c +++ b/src/network.c @@ -64,6 +64,10 @@ static void _get_network(uint64_t *results, int *sources) } } +/* + * read from fd len chars and store them into buf + * make *s points to the first occurence of c into buf +*/ static int strchr_refill(int fd, char *buf, int len, char **s, char c) { *s = strchr(*s, c); @@ -152,7 +156,13 @@ unsigned int init_network(char *dev, void **ptr) } /* compare dev name to the previously saved one */ - if (strncmp(start_of_dev, state->devs[state->ndev - 1], s - start_of_dev) != 0) { + int newdev = 1; + for (int i = 0; i < state->ndev && newdev; i++) { + if (strncmp(start_of_dev, state->devs[i], s - start_of_dev) == 0) { + newdev = 0; + } + } + if (newdev) { if (state->ndev >= NB_MAX_DEV) { fprintf(stderr, "Maximum amount of network devices exceeded (%d).\n", NB_MAX_DEV); break; -- GitLab From 38fe56fc0d5de9d32dd906fc261eef2521f62d82 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 7 Mar 2023 12:56:44 +0100 Subject: [PATCH 189/229] debug help --- src/nvidia_gpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 479eecb..0be83ce 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -18,6 +18,8 @@ *******************************************************/ +// -- test : +// gcc -std=gnu99 -Wall -Wextra -Wpedantic -fsanitize=address -D__NVIDIA__MAIN__TEST nvidia_gpu.c -I/lib -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lnvidia-ml #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -300,6 +302,7 @@ unsigned int label_utilization_sensor(char **labels, void *data) return COUNT_UTILIZATION; } + void clean_utilization_sensor(void *data) { free(data); -- GitLab From b6bd0080167596b8c8af6d7bd28b29fb705810f7 Mon Sep 17 00:00:00 2001 From: TwilCynder <twilcynder@gmail.com> Date: Tue, 7 Mar 2023 17:26:01 +0100 Subject: [PATCH 190/229] small merge --- README.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/README.md b/README.md index 95b6d7e..30b840a 100644 --- a/README.md +++ b/README.md @@ -22,20 +22,8 @@ OPTIONS: 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|--intel-rapl INTEL RAPL --c|--cpu-temp - processor temperature ``` ## Installation Instructions -- GitLab From 2622d3c0087d88ec10da2fd87dae8d8fd4624578 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 08:28:36 +0100 Subject: [PATCH 191/229] fix print uint64_t format --- src/amd_rapl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 1e08517..253711f 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -120,7 +120,7 @@ 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); + fprintf(stderr, "read_msr(%"PRIu64"):", msr); perror("pread"); exit(127); } @@ -175,7 +175,7 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) 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", + printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %"PRIu64"\n", sensor->cpu_id, sensor->package_id, sensor->core_id, -- GitLab From 73936d2860b2b91689380450f438b07f2123b04b Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 09:27:42 +0100 Subject: [PATCH 192/229] add msg --- src/nvidia_gpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index c741055..681a028 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -38,6 +38,6 @@ Optparse nvidia_gpu_opt[1] = { .shortname = 'n', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "NVIDIA GPU", + .usage_msg = "provides basic gpu information", }, }; -- GitLab From d19aa35ecc91d47c143fd503abf5ff776eceaf48 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 09:37:45 +0100 Subject: [PATCH 193/229] fix include --- src/amd_rapl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 253711f..f08c5a7 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 <inttypes.h> #include "info_reader.h" #include "util.h" -- GitLab From bfb4c16b6334e029f1871396a200615d248004b4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 10:02:36 +0100 Subject: [PATCH 194/229] add the detection of nvidia --- configure.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.sh b/configure.sh index 21c94ef..24a379d 100755 --- a/configure.sh +++ b/configure.sh @@ -115,6 +115,10 @@ detect_caps() { [ -e "/sys/class/net/$dev" ] && hdr_whitelist="${hdr_whitelist}|network" fi + if [ -e /usr/local/cuda/lib64 ] && [ -e /usr/local/cuda/include ]; then + hdr_whitelist="${hdr_whitelist}|nvidia_gpu" + fi + vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) vendor_lc=$(echo "$vendor" | tr 'A-Z' 'a-z') case $vendor_lc in -- GitLab From 1a5443e32e004050a96ad27dddfd0bfcef66d05e Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 13:11:27 +0100 Subject: [PATCH 195/229] temperature/power --- src/nvidia_gpu.c | 155 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 18 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 0be83ce..5f4a460 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -37,8 +37,10 @@ typedef enum { CLOCK_SENSOR = 0, MEMORY_SENSOR = 1, UTILIZATION_SENSOR = 2, + POWER_SENSOR = 3, + TEMPERATURE_SENSOR = 4, - COUNT_SENSOR = 3, + COUNT_SENSOR = 5, } SENSOR_KIND; typedef struct Device Device; @@ -83,6 +85,7 @@ struct NvidiaGpu { // -- Label template static const char *label_template = "gpu%u_%s_%s"; +static const char *short_label_template = "gpu%u_%s"; // ----------------------------CLOCK_SENSOR @@ -106,17 +109,17 @@ unsigned int init_clock_sensor(const Device *device, void **data) const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; ClockData tmp = {0}; - nvmlReturn_t result; + nvmlReturn_t err; unsigned int clock; // -- Test all clocks for (unsigned int i = 0; i < NVML_CLOCK_COUNT; i++) { - if ((result = nvmlDeviceGetClockInfo(nvml_device, clocks[i], &clock)) == NVML_SUCCESS) { + if ((err = nvmlDeviceGetClockInfo(nvml_device, clocks[i], &clock)) == NVML_SUCCESS) { snprintf(tmp.labels[tmp.count], CLOCK_LABEL_SIZE, label_template, device_idx, clock_base_name, clock_names[i]); tmp.clocks[tmp.count] = clocks[i]; tmp.count += 1; } else { - fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[i], nvmlErrorString(result)); + fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[i], nvmlErrorString(err)); } } @@ -189,9 +192,9 @@ unsigned int init_memory_sensor(const Device *device, void **data) const unsigned int device_idx = device->idx; nvmlMemory_t memory; - nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + nvmlReturn_t err; + if ((err = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(err)); return 0; } @@ -210,9 +213,9 @@ unsigned int get_memory_sensor(uint64_t *results, const Device *device, void *no const nvmlDevice_t nvml_device = device->device; nvmlMemory_t memory; - nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + nvmlReturn_t err; + if ((err = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(err)); exit(99); } @@ -259,10 +262,10 @@ unsigned int init_utilization_sensor(const Device *device, void **data) const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; - nvmlReturn_t result; + nvmlReturn_t err; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + if ((err = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(err)); return 0; } @@ -280,10 +283,10 @@ unsigned int get_utilization_sensor(uint64_t *results, const Device *device, voi UNUSED(none); const nvmlDevice_t nvml_device = device->device; - nvmlReturn_t result; + nvmlReturn_t err; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + if ((err = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(err)); exit(99); } @@ -308,8 +311,122 @@ void clean_utilization_sensor(void *data) free(data); } -// ----------------------------ERROR_SENSOR -// TODO +// ----------------------------POWER_SENSOR + +#define POWER_LABEL_SIZE 25 +#define COUNT_POWER 1 + +static const char *power_base_name = "power"; + +typedef struct { + char label[POWER_LABEL_SIZE]; +} PowerData; + + +unsigned int init_power_sensor(const Device *device, void** data) { + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; + + unsigned int power; + nvmlReturn_t err; + if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + return 0; + } + + PowerData *power_data = (PowerData *) calloc(1, sizeof(PowerData)); + snprintf(power_data->label, POWER_LABEL_SIZE, short_label_template, device_idx, power_base_name); + + *data = (void *) power_data; + return COUNT_POWER; +} + +unsigned int get_power_sensor(uint64_t *results, const Device *device, void *none) { + UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + + unsigned int power; + nvmlReturn_t err; + if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + exit(99); + } + + *results = power; + return COUNT_POWER; +} + +unsigned int label_power_sensor(char** labels, void *data) { + PowerData *power_data = (PowerData *) data; + *labels = power_data->label; + return COUNT_POWER; +} + +void clean_power_sensor(void *data) { + free(data); +} + +// ----------------------TEMPERATURE_SENSOR + + +#define TEMPERATURE_LABEL_SIZE 35 +#define COUNT_TEMPERATURE 1 + +static const char *temperature_base_name = "temperature"; + +typedef struct { + char label[TEMPERATURE_LABEL_SIZE]; +} TemperatureData; + +unsigned int init_temperature_sensor(const Device *device, void** data) { + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; + + unsigned int temperature; + nvmlReturn_t err; + if ((err = nvmlDeviceGetTemperature(nvml_device, NVML_TEMPERATURE_GPU, &temperature)) != NVML_SUCCESS) { + printf("Failed to get the device temperature: %s\n", nvmlErrorString(err)); + return 0; + } + + TemperatureData *temperature_data = (TemperatureData *) calloc(1, sizeof(TemperatureData)); + snprintf(temperature_data->label, TEMPERATURE_LABEL_SIZE, short_label_template, device_idx, temperature_base_name); + + *data = (void *) temperature_data; + return COUNT_TEMPERATURE; +} + +unsigned int get_temperature_sensor(uint64_t *results, const Device *device, void *none) { + UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + + unsigned int temperature; + nvmlReturn_t err; + if ((err = nvmlDeviceGetTemperature(nvml_device, NVML_TEMPERATURE_GPU, &temperature)) != NVML_SUCCESS) { + printf("Failed to get the device temperature: %s\n", nvmlErrorString(err)); + exit(99); + } + + *results = temperature; + return COUNT_TEMPERATURE; +} + +unsigned int label_temperature_sensor(char** labels, void *data) { + TemperatureData *temperature_data = (TemperatureData *) data; + *labels = temperature_data->label; + return COUNT_TEMPERATURE; +} + +void clean_temperature_sensor(void *data) { + free(data); +} +// // Get the temperature +// result = nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temperature); +// if (NVML_SUCCESS != result) { +// printf("Failed to get temperature for device %d: %s\n", i, nvmlErrorString(result)); +// continue; +// } +// printf("\t - temperature: %u\n", temperature); // ---------------------------------------- @@ -319,6 +436,8 @@ static const ISensor avaible_sensors[COUNT_SENSOR] = { {.init = init_clock_sensor, .get = get_clock_sensor, .label = label_clock_sensor, .clean = clean_clock_sensor}, {.init = init_memory_sensor, .get = get_memory_sensor, .label = label_memory_sensor, .clean = clean_memory_sensor}, {.init = init_utilization_sensor, .get = get_utilization_sensor, .label = label_utilization_sensor, .clean = clean_utilization_sensor}, + {.init = init_power_sensor, .get = get_power_sensor, .label = label_power_sensor, .clean = clean_power_sensor}, + {.init = init_temperature_sensor, .get = get_temperature_sensor, .label = label_temperature_sensor, .clean = clean_temperature_sensor}, }; // ------------------------DEVICE_FUNCTIONS -- GitLab From 73e90167bb968cee8a90b903c829fed3da0bf812 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 13:11:56 +0100 Subject: [PATCH 196/229] doc nvidia --- doc/nvidia-gpu.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 doc/nvidia-gpu.md diff --git a/doc/nvidia-gpu.md b/doc/nvidia-gpu.md new file mode 100644 index 0000000..8c54afd --- /dev/null +++ b/doc/nvidia-gpu.md @@ -0,0 +1,58 @@ +# Nvidia Gpu + +The `nvidia-gpu` sensor provides basic information about the gpu. Depending on +the driver version it is possible that not all sensors are supported, so an +error message will be written to `stderr` but the execution will continue. + +For more information you can consult the [nvidia nvml api](https://docs.nvidia.com/deploy/index.html). + +## [Clock](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g805c0647be9996589fc5e3f6ff680c64) + +All speeds are in Mhz. + +|Output |Description | +|--------|-------------------------------| +|graphics|Graphics clock | +|sm |Streaming Multiprocessor clock | +|memory |Memory clock | +|video |Video encoder/decoder clock | + +## [Memory](https://docs.nvidia.com/deploy/nvml-api/structnvmlMemory__t.html#structnvmlMemory__t) + +All values are in bytes. + +|Output |Description | +|--------|-------------------------------------| +|free |Unallocated device memory | +|used |Sum of Reserved and Allocated memory | +|total |Total physical device memory | + + +## [Utilization](https://docs.nvidia.com/deploy/nvml-api/structnvmlUtilization__t.html#structnvmlUtilization__t) + +Utilization information for a device. Each sample period may be between 1 +second and 1/6 second, depending on the product being queried. + +All values are a percent of time over the past sample period. + +|Output |Description | +|--------|---------------------| +|gpu | Usage of the GPU | +|memory | Usage of the Memory | + +## [Power](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceQueries.html#group__nvmlDeviceQueries_1g7ef7dff0ff14238d08a19ad7fb23fc87) + +Retrieves power usage for this GPU in milliwatts and its associated circuitry (e.g. memory) + +|Output |Description | +|--------|-------------------------| +|power | Power consumption in mW | + +## [Temperature](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g2650b526841fa38b8f293c2d509a1de0) + +Temperature of the GPU. + +|Output |Description | +|------------|----------------------------| +|temperature | Temperature of the GPU die | + -- GitLab From 7a99793661194c32f5b366aca7f9e2289dc7dde7 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 13:18:49 +0100 Subject: [PATCH 197/229] fix line --- doc/nvidia-gpu.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/nvidia-gpu.md b/doc/nvidia-gpu.md index 8c54afd..5a5cebc 100644 --- a/doc/nvidia-gpu.md +++ b/doc/nvidia-gpu.md @@ -49,7 +49,6 @@ Retrieves power usage for this GPU in milliwatts and its associated circuitry (e |power | Power consumption in mW | ## [Temperature](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g2650b526841fa38b8f293c2d509a1de0) - Temperature of the GPU. |Output |Description | -- GitLab From 8e1a6b567cd3270e38f74a8290112b71da6c9feb Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 14:08:11 +0100 Subject: [PATCH 198/229] fix name --- doc/{nvidia-gpu.md => nvidia_gpu.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename doc/{nvidia-gpu.md => nvidia_gpu.md} (97%) diff --git a/doc/nvidia-gpu.md b/doc/nvidia_gpu.md similarity index 97% rename from doc/nvidia-gpu.md rename to doc/nvidia_gpu.md index 5a5cebc..15cc8aa 100644 --- a/doc/nvidia-gpu.md +++ b/doc/nvidia_gpu.md @@ -1,6 +1,6 @@ # Nvidia Gpu -The `nvidia-gpu` sensor provides basic information about the gpu. Depending on +The `nvidia_gpu` sensor provides basic information about the gpu. Depending on the driver version it is possible that not all sensors are supported, so an error message will be written to `stderr` but the execution will continue. -- GitLab From 22721bfe5886ec3159ca34091e593a172511ce05 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 14:09:41 +0100 Subject: [PATCH 199/229] format --- src/nvidia_gpu.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 5f4a460..17d77f5 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -319,19 +319,20 @@ void clean_utilization_sensor(void *data) static const char *power_base_name = "power"; typedef struct { - char label[POWER_LABEL_SIZE]; + char label[POWER_LABEL_SIZE]; } PowerData; -unsigned int init_power_sensor(const Device *device, void** data) { +unsigned int init_power_sensor(const Device *device, void **data) +{ const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; unsigned int power; nvmlReturn_t err; if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { - printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); - return 0; + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + return 0; } PowerData *power_data = (PowerData *) calloc(1, sizeof(PowerData)); @@ -341,28 +342,31 @@ unsigned int init_power_sensor(const Device *device, void** data) { return COUNT_POWER; } -unsigned int get_power_sensor(uint64_t *results, const Device *device, void *none) { +unsigned int get_power_sensor(uint64_t *results, const Device *device, void *none) +{ UNUSED(none); const nvmlDevice_t nvml_device = device->device; unsigned int power; nvmlReturn_t err; if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { - printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); - exit(99); + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + exit(99); } *results = power; return COUNT_POWER; } -unsigned int label_power_sensor(char** labels, void *data) { +unsigned int label_power_sensor(char **labels, void *data) +{ PowerData *power_data = (PowerData *) data; *labels = power_data->label; return COUNT_POWER; } -void clean_power_sensor(void *data) { +void clean_power_sensor(void *data) +{ free(data); } @@ -375,10 +379,11 @@ void clean_power_sensor(void *data) { static const char *temperature_base_name = "temperature"; typedef struct { - char label[TEMPERATURE_LABEL_SIZE]; + char label[TEMPERATURE_LABEL_SIZE]; } TemperatureData; -unsigned int init_temperature_sensor(const Device *device, void** data) { +unsigned int init_temperature_sensor(const Device *device, void **data) +{ const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; @@ -396,7 +401,8 @@ unsigned int init_temperature_sensor(const Device *device, void** data) { return COUNT_TEMPERATURE; } -unsigned int get_temperature_sensor(uint64_t *results, const Device *device, void *none) { +unsigned int get_temperature_sensor(uint64_t *results, const Device *device, void *none) +{ UNUSED(none); const nvmlDevice_t nvml_device = device->device; @@ -411,13 +417,15 @@ unsigned int get_temperature_sensor(uint64_t *results, const Device *device, voi return COUNT_TEMPERATURE; } -unsigned int label_temperature_sensor(char** labels, void *data) { +unsigned int label_temperature_sensor(char **labels, void *data) +{ TemperatureData *temperature_data = (TemperatureData *) data; *labels = temperature_data->label; return COUNT_TEMPERATURE; } -void clean_temperature_sensor(void *data) { +void clean_temperature_sensor(void *data) +{ free(data); } // // Get the temperature -- GitLab From 6ac893561fca6e5b433a3b9ab779a61c11b13744 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Mar 2023 14:17:48 +0100 Subject: [PATCH 200/229] add doc to "network" sensor explaining #interfaces hard-limit in use --- doc/network.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/network.md diff --git a/doc/network.md b/doc/network.md new file mode 100644 index 0000000..b5d1e68 --- /dev/null +++ b/doc/network.md @@ -0,0 +1,8 @@ +This sensor can autodetect interfaces in use by giving the special +interface name "X". But the total number of interfaces it can autodetect +is currently under a hard-limit. This hard-limit can be changed by +modifying this line in `src/network.c`: + +```c +#define NB_MAX_DEV 8 +``` -- GitLab From 1e6746bee0c8e7f867c778f50369e3a17d3f5ddb Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Mar 2023 15:36:34 +0100 Subject: [PATCH 201/229] configure.sh: avoid cd(1) and ls(1) in ls_sensors() --- configure.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.sh b/configure.sh index 747a078..203fd04 100755 --- a/configure.sh +++ b/configure.sh @@ -43,16 +43,16 @@ usage() { } ls_sensors() { - try cd src + [ -d src ] || die 'fatal: the "src" directory does not exit.' [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' dprint hdr_blacklist >&2 dprint hdr_whitelist >&2 - ls -1 *.h | - grep -xEv "($hdr_blacklist)\.h" | - grep -xE "($hdr_whitelist)\.h" | - sed 's/\.h$//' + try find src -type f -name '*.h' | + sed 's,src/\(.*\)\.h,\1,' | + grep -xEv "($hdr_blacklist)" | + grep -xE "($hdr_whitelist)" } # gen_sensors_h(sensor, nb_sensors) -- GitLab From 856c5a6e577428882179c3dceba4aeaf1bb7192d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 08:56:20 +0100 Subject: [PATCH 202/229] auto config nvidia --- configure.sh | 79 +++++++++++++++++++++++++++++----------------------- makefile | 6 ++-- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/configure.sh b/configure.sh index 24a379d..207cf07 100755 --- a/configure.sh +++ b/configure.sh @@ -4,12 +4,15 @@ # Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> try() { "$@" || die "cannot $*"; } -die() { yell "$*"; exit 111; } +die() { + yell "$*" + exit 111 +} yell() { echo "$0: $*" >&2; } echo() { printf '%s\n' "$*"; } isnum() { case "${1#[+-]}" in - *[!0-9]*|'') return 1 ;; + *[!0-9]* | '') return 1 ;; *) return 0 ;; esac } @@ -51,7 +54,7 @@ ls_sensors() { ls -1 *.h | grep -xEv "($hdr_blacklist)\.h" | - grep -xE "($hdr_whitelist)\.h" | + grep -xE "($hdr_whitelist)\.h" | sed 's/\.h$//' } @@ -86,10 +89,10 @@ gen_sensors_h() { printf ' int opt_idx = offset;\n' for sensor in $sensors; do cat <<-! - for (int i = 0; i < ${sensor}.nb_opt; i++) { - opts[opt_idx++] = ${sensor}_opt[i]; - } - sensors[(*nb_defined)++] = ${sensor}; + for (int i = 0; i < ${sensor}.nb_opt; i++) { + opts[opt_idx++] = ${sensor}_opt[i]; + } + sensors[(*nb_defined)++] = ${sensor}; ! done printf ' assert((offset + *nb_defined) <= len);\n' @@ -117,6 +120,8 @@ detect_caps() { if [ -e /usr/local/cuda/lib64 ] && [ -e /usr/local/cuda/include ]; then hdr_whitelist="${hdr_whitelist}|nvidia_gpu" + NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml" + NVML_IFLAGS="-I/usr/local/cuda/include" fi vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) @@ -140,7 +145,7 @@ detect_caps() { } case $1 in ---all|-a) +--all | -a) all=1 ;; esac @@ -148,30 +153,33 @@ esac [ "$all" ] || detect_caps [ "$all" ] || -while [ "$1" ]; do - case $1 in - --include|-i) - shift; [ "$1" ] || usage - hdr_whitelist="${hdr_whitelist}|${1}" - ;; - --exclude|-e) - shift; [ "$1" ] || usage - hdr_blacklist="${hdr_blacklist}|${1}" - ;; - --list-sensors|-l) - ls_sensors - exit 0 - ;; - --unique|-u) - shift; [ "$1" ] || usage - hdr_whitelist=$1 - ;; - --help|-h) - usage - ;; - esac - shift -done + while [ "$1" ]; do + case $1 in + --include | -i) + shift + [ "$1" ] || usage + hdr_whitelist="${hdr_whitelist}|${1}" + ;; + --exclude | -e) + shift + [ "$1" ] || usage + hdr_blacklist="${hdr_blacklist}|${1}" + ;; + --list-sensors | -l) + ls_sensors + exit 0 + ;; + --unique | -u) + shift + [ "$1" ] || usage + hdr_whitelist=$1 + ;; + --help | -h) + usage + ;; + esac + shift + done sensors=$(ls_sensors) nb_sensors=$(echo "$sensors" | sed '/^$/d' | wc -l) @@ -181,12 +189,13 @@ if [ "$nb_sensors" -eq 0 ]; then exit 1 fi -try gen_sensors_h "$sensors" "$nb_sensors" > "$target_hdr" -try gen_sensors_mk "$sensors" > "$target_mk" +try gen_sensors_h "$sensors" "$nb_sensors" >"$target_hdr" +try gen_sensors_mk "$sensors" >"$target_mk" +try printf "LDFLAGS += %s\n" "$NVML_LDFLAGS" >>"$target_mk" +try printf "IFLAGS += %s\n" "$NVML_IFLAGS" >>"$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&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/makefile b/makefile index 81a4e41..1b636c4 100644 --- a/makefile +++ b/makefile @@ -9,6 +9,8 @@ TESTS_DIR = tests BIN = mojitos CAPTOR_OBJ = +IFLAGS = +LDFLAGS = include ./sensors.mk @@ -17,9 +19,9 @@ OBJ = \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib -I/usr/local/cuda/include +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(IFLAGS) CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS = -L/usr/local/cuda/lib64 -lnvidia-ml +LDFLAGS += ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -- GitLab From ddbe21e68e58bc5923b17d59d64d08ae9fc45cee Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 09:19:06 +0100 Subject: [PATCH 203/229] fix: Readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c6d591..9fee622 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,15 @@ make ``` You may want to run `./configure.sh --help` to see configuration options. +To use `amd_rapl` you have to load the module `msr` +```bash +sudo modprobe msr +``` 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 +To execute mojitos 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/*/*/* -- GitLab From bd68a69a55783fe7985910fe0e3e359de7102e3c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 11:36:10 +0100 Subject: [PATCH 204/229] auto configure nvml --- configure.sh | 5 +++-- makefile | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/configure.sh b/configure.sh index 207cf07..ebf6881 100755 --- a/configure.sh +++ b/configure.sh @@ -191,8 +191,9 @@ fi try gen_sensors_h "$sensors" "$nb_sensors" >"$target_hdr" try gen_sensors_mk "$sensors" >"$target_mk" -try printf "LDFLAGS += %s\n" "$NVML_LDFLAGS" >>"$target_mk" -try printf "IFLAGS += %s\n" "$NVML_IFLAGS" >>"$target_mk" + +try printf "NVML_LDFLAGS = %s\n" "$NVML_LDFLAGS" >>"$target_mk" +try printf "NVML_IFLAGS = %s\n" "$NVML_IFLAGS" >>"$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 printf -- 'The resulting binary will have the %d following sensors:\n' "$nb_sensors" >&2 diff --git a/makefile b/makefile index 1b636c4..8a3c129 100644 --- a/makefile +++ b/makefile @@ -9,8 +9,8 @@ TESTS_DIR = tests BIN = mojitos CAPTOR_OBJ = -IFLAGS = -LDFLAGS = +NVML_LDFLAGS = +NVML_IFLAGS = include ./sensors.mk @@ -19,9 +19,9 @@ OBJ = \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(IFLAGS) +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(NVML_IFLAGS) CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS += +LDFLAGS = $(NVML_LDFLAGS) ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -- GitLab From a7ae9dc8fc367af447a1a76c1ba72630e893e2b4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 12:00:11 +0100 Subject: [PATCH 205/229] clean up --- src/nvidia_gpu.c | 55 +----------------------------------------------- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 17d77f5..4078002 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -18,13 +18,12 @@ *******************************************************/ -// -- test : -// gcc -std=gnu99 -Wall -Wextra -Wpedantic -fsanitize=address -D__NVIDIA__MAIN__TEST nvidia_gpu.c -I/lib -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lnvidia-ml #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +// Pedantic throws a warning in the nvml library #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #include <nvml.h> @@ -428,16 +427,6 @@ void clean_temperature_sensor(void *data) { free(data); } -// // Get the temperature -// result = nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temperature); -// if (NVML_SUCCESS != result) { -// printf("Failed to get temperature for device %d: %s\n", i, nvmlErrorString(result)); -// continue; -// } -// printf("\t - temperature: %u\n", temperature); - -// ---------------------------------------- - // -------------------------AVAIBLE_SENSORS static const ISensor avaible_sensors[COUNT_SENSOR] = { @@ -602,45 +591,3 @@ void clean_nvidia_gpu(void *ptr) nvmlShutdown(); } -// -------------------------------TEST_MAIN - -#ifdef __NVIDIA__MAIN__TEST -int main() -{ - void *ptr = NULL; - char *none = NULL; - - unsigned int sensor_count = init_nvidia_gpu(none, &ptr); - - NvidiaGpu *nvidia = (NvidiaGpu *) ptr; - printf("%d\n", nvidia->count); - printf("%u\n", sensor_count); - - - - uint64_t results[sensor_count]; - char *labels[sensor_count]; - - memset(results, 0, sensor_count * sizeof(uint64_t)); - memset(labels, 0, sensor_count * sizeof(char **)); - - - unsigned count_label = label_nvidia_gpu(labels, ptr); - unsigned count_get = get_nvidia_gpu(results, ptr); - printf("total : %u, get : %u, label : %u\n", sensor_count, count_get, count_label); - - - for (unsigned int i = 0; i < sensor_count; i++) { - printf("%s ", labels[i]); - } - printf("\n"); - for (unsigned int i = 0; i < sensor_count; i++) { - printf("%lu ", results[i]); - } - printf("\n"); - printf("sensor_count: %d\n", sensor_count); - - clean_nvidia_gpu(ptr); -} -#endif - -- GitLab From 82224cf547220db437b09b720285141c575c2982 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 12:08:10 +0100 Subject: [PATCH 206/229] fix: usage msg --- src/nvidia_gpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index 681a028..1f3d053 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -38,6 +38,6 @@ Optparse nvidia_gpu_opt[1] = { .shortname = 'n', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "provides basic gpu information", + .usage_msg = "provides basic gpu information [clocks, memory, utilization, power, temperature].", }, }; -- GitLab From 80686673103879c1eb6b197c45493b521c7702a9 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 10:41:57 +0100 Subject: [PATCH 207/229] add memory sensor --- configure.sh | 6 +++- src/memory.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/memory.h | 43 +++++++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/memory.c create mode 100644 src/memory.h diff --git a/configure.sh b/configure.sh index 740e87a..7e10ec3 100755 --- a/configure.sh +++ b/configure.sh @@ -55,7 +55,7 @@ ls_sensors() { try find src -type f -name '*.h' | sed 's,src/\(.*\)\.h,\1,' | grep -xEv "($hdr_blacklist)" | - grep -xE "($hdr_whitelist)" + grep -xE "($hdr_whitelist)" } # gen_sensors_h(sensor, nb_sensors) @@ -118,6 +118,10 @@ detect_caps() { [ -d /sys/class/infiniband ] && hdr_whitelist="${hdr_whitelist}|infiniband" [ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load" + if [ "$(uname -r | cut -d "." -f 1)" -gt "2" ]; then + hdr_whitelist="${hdr_whitelist}|memory" + fi + 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" diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..3356a82 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,97 @@ +/******************************************************* + 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 <stdlib.h> +#include <sys/sysinfo.h> +#include <string.h> + +#include "util.h" + +typedef enum { + TOTALRAM = 0, + FREERAM, + SHAREDRAM, + BUFFERRAM, + TOTALSWAP, + FREESWAP, + PROCS, + TOTALHIGH, + FREEHIGH, + MEM_UNIT, + + MEMORY_COUNT, +} MemoryKind; + +static const char *memory_labels[MEMORY_COUNT] = { + "totalram", "freeram", "sharedram", "bufferram", + "totalswap", "freeswap", + "procs", + "totalhigh", "freehigh", "mem_unit", +}; + +unsigned int init_memory(char *none1, void **none2) +{ + UNUSED(none1); + UNUSED(none2); + struct sysinfo info; + if (sysinfo(&info) < 0) { + fprintf(stderr, "Failed to get the memory information"); + return 0; + } + return MEMORY_COUNT; +} + +unsigned int get_memory(uint64_t *results, void *none) +{ + UNUSED(none); + struct sysinfo info; + if (sysinfo(&info) < 0) { + fprintf(stderr, "Failed to get the memory information"); + exit(99); + } + + // Can't use memcpy, the size isn't always the same + results[TOTALRAM] = info.totalram; + results[FREERAM] = info.freeram; + results[SHAREDRAM] = info.sharedram; + results[BUFFERRAM] = info.bufferram; + results[TOTALSWAP] = info.totalswap; + results[FREESWAP] = info.freeswap; + results[PROCS] = info.procs; + results[TOTALHIGH] = info.totalhigh; + results[FREEHIGH] = info.freehigh; + results[MEM_UNIT] = info.mem_unit; + + return MEMORY_COUNT; +} + +void label_memory(char **labels, void *none) +{ + UNUSED(none); + memcpy(labels, memory_labels, sizeof(char *) * MEMORY_COUNT); +} + +void clean_memory(void *none) +{ + UNUSED(none); + return; +} + diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000..6e275c6 --- /dev/null +++ b/src/memory.h @@ -0,0 +1,43 @@ +/******************************************************* + 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_memory(char *, void **); +unsigned int get_memory(uint64_t *results, void *); +void clean_memory(void *); +void label_memory(char **labels, void *); + + +Sensor memory = { + .init = init_memory, + .get = get_memory, + .clean = clean_memory, + .label = label_memory, + .nb_opt = 1, +}; + +Optparse memory_opt[1] = { + { + .longname = "memory", + .shortname = 'm', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "Retrieves information about the memory via the syscall 'sysinfo(2)'.", + }, +}; -- GitLab From 482202be2c2811baf0f5f4fff1c5056f9b2b3e04 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 11:21:58 +0100 Subject: [PATCH 208/229] non breaking change, ptr -> const ptr --- tests/small_test.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index 66c4de9..8301ae7 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -253,8 +253,8 @@ #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 int (Comparator) (const void *, const void *); +typedef char *(Formatter) (char[FMT_BUFFER_SIZE], const void *); typedef struct { Comparator *compare; @@ -263,7 +263,7 @@ typedef struct { // ---------------------------TEST FUNCTION -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) +int test(char *file, int line, unsigned int __indentation_level, const void *result, const void *expected, const TestInterface *interface) { __indentation_level += 1; static char buffer_result[FMT_BUFFER_SIZE]; @@ -281,7 +281,7 @@ int test(char *file, int line, unsigned int __indentation_level, void *result, v // ------------------------------INTERFACES // -- str_interface -int str_compare(void *ptr1, void *ptr2) +int str_compare(const void *ptr1, const void *ptr2) { char *str1 = (char *) ptr1; char *str2 = (char *) ptr2; @@ -295,7 +295,7 @@ int str_compare(void *ptr1, void *ptr2) } } -char *str_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *str_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { UNUSED(buffer); static char *str_null = "NULL"; @@ -310,14 +310,14 @@ static const TestInterface str_interface = { // -- bool_interface -int bool_compare(void *ptr1, void *ptr2) +int bool_compare(const void *ptr1, const void *ptr2) { bool *bool1 = (bool *) ptr1; bool *bool2 = (bool *) ptr2; return *bool1 == *bool2; } -char *bool_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *bool_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { UNUSED(buffer); bool *_bool = (bool *) ptr; @@ -331,14 +331,14 @@ static const TestInterface bool_interface = { // -- int_interface -int int_compare(void *ptr1, void *ptr2) +int int_compare(const void *ptr1, const void *ptr2) { int *int1 = (int *) ptr1; int *int2 = (int *) ptr2; return *int1 == *int2; } -char *int_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *int_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { int *_int = (int *) ptr; snprintf(buffer, FMT_BUFFER_SIZE, "%d", *_int); @@ -352,12 +352,12 @@ static const TestInterface int_interface = { // -- ptr_interface -int ptr_compare(void *ptr1, void *ptr2) +int ptr_compare(const void *ptr1, const void *ptr2) { return ptr1 == ptr2; } -char *ptr_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *ptr_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { snprintf(buffer, FMT_BUFFER_SIZE, "%p", ptr); return buffer; @@ -370,14 +370,14 @@ static const TestInterface ptr_interface = { // -- u64_interface -int u64_compare(void *ptr1, void *ptr2) +int u64_compare(const void *ptr1, const 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) +char *u64_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { uint64_t *v = (uint64_t *) ptr; snprintf(buffer, FMT_BUFFER_SIZE, "%"PRIu64"", *v); -- GitLab From 32ff911bf1e940750eadf0e5080f374aa45921ef Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 11:23:21 +0100 Subject: [PATCH 209/229] add tests --- tests/main.c | 2 ++ tests/memory.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/memory.c diff --git a/tests/main.c b/tests/main.c index 3246f04..e90e8dd 100644 --- a/tests/main.c +++ b/tests/main.c @@ -21,9 +21,11 @@ #include "util.c" #include "amd_rapl.c" #include "info_reader.c" +#include "memory.c" TMAIN({ CALL_TFUNCTION(test_util); CALL_TFUNCTION(test_amd_rapl); CALL_TFUNCTION(test_info_reader); + CALL_TFUNCTION(test_memory); }) diff --git a/tests/memory.c b/tests/memory.c new file mode 100644 index 0000000..78efd28 --- /dev/null +++ b/tests/memory.c @@ -0,0 +1,78 @@ +/******************************************************* + 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/memory.c" + +// In order to verify the integrity. +TFUNCTION(test_labels, { + // If it fails update the tests + int tested_count = 10; + int expected_count = MEMORY_COUNT; + TEST_INT(&tested_count, &expected_count); + + const char *result = NULL; + char *expected = NULL; + + expected = "totalram"; + result = memory_labels[TOTALRAM]; + TEST_STR(result, expected); + + expected = "freeram"; + result = memory_labels[FREERAM]; + TEST_STR(result, expected); + + expected = "sharedram"; + result = memory_labels[SHAREDRAM]; + TEST_STR(result, expected); + + expected = "bufferram"; + result = memory_labels[BUFFERRAM]; + TEST_STR(result, expected); + + expected = "totalswap"; + result = memory_labels[TOTALSWAP]; + TEST_STR(result, expected); + + expected = "freeswap"; + result = memory_labels[FREESWAP]; + TEST_STR(result, expected); + + expected = "procs"; + result = memory_labels[PROCS]; + TEST_STR(result, expected); + + expected = "totalhigh"; + result = memory_labels[TOTALHIGH]; + TEST_STR(result, expected); + + expected = "freehigh"; + result = memory_labels[FREEHIGH]; + TEST_STR(result, expected); + + expected = "mem_unit"; + result = memory_labels[MEM_UNIT]; + TEST_STR(result, expected); +}) + +TFILE_ENTRY_POINT(test_memory, { + CALL_TFUNCTION(test_labels); +}) + -- GitLab From 4ffdcfaf2192b0929cd7d0902bcb5a2cc34510fe Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 11:39:45 +0100 Subject: [PATCH 210/229] add tests --- tests/util.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/util.c b/tests/util.c index 69941bf..231ab47 100644 --- a/tests/util.c +++ b/tests/util.c @@ -77,6 +77,50 @@ TFUNCTION(test_modulo_substraction, { TEST_UINT64_T(&result, &expected); }) +TFUNCTION(test_max, { + int expected = 0; + int result = 0; + + expected = 10; + result = MAX(expected, 9); + TEST_INT(&result, &expected); + + expected = -15; + result = MAX(expected, -16); + TEST_INT(&result, &expected); + + expected = 0; + result = MAX(expected, -1); + TEST_INT(&result, &expected); + + expected = 1; + result = MAX(expected, 0); + TEST_INT(&result, &expected); +}) + +TFUNCTION(test_min, { + int expected = 0; + int result = 0; + + expected = 9; + result = MIN(expected, 10); + TEST_INT(&result, &expected); + + expected = -16; + result = MIN(expected, -15); + TEST_INT(&result, &expected); + + expected = -1; + result = MIN(expected, 0); + TEST_INT(&result, &expected); + + expected = 0; + result = MIN(expected, 1); + TEST_INT(&result, &expected); +}) + TFILE_ENTRY_POINT(test_util, { CALL_TFUNCTION(test_modulo_substraction); + CALL_TFUNCTION(test_max); + CALL_TFUNCTION(test_min); }) -- GitLab From bdb2908f2cecc768711d92eede0d41e5d856c404 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 12:46:42 +0100 Subject: [PATCH 211/229] add: exit information --- src/amd_rapl.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index f08c5a7..adc4461 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -201,17 +201,36 @@ void debug_print_amd_rapl(AmdRapl *rapl) unsigned int get_nb_cpu() { char filename[BUFFER_SIZE]; + int cpy_errno; unsigned int n_cpu = 0; for (;; n_cpu++) { snprintf(filename, BUFFER_SIZE, base_str, n_cpu); int fd = open(filename, O_RDONLY); + cpy_errno = errno; if (fd < 0) { break; } close(fd); } + + if (n_cpu == 0) { + perror("open()"); + fprintf(stderr, "on %s\n", filename); + switch (cpy_errno) { + case ENOENT: + fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n"); + exit(99); + case EACCES: + fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n"); + exit(98); + default: + fprintf(stderr, "Unexpected error"); + exit(97); + } + } + // n_cpu > 0 return n_cpu; } @@ -295,11 +314,6 @@ 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)) { -- GitLab From f3368b52b60d7b46a39411a0e8f69e378a285f0a Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 12:52:02 +0100 Subject: [PATCH 212/229] error handling --- src/amd_rapl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index adc4461..9eaac45 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -217,7 +217,7 @@ unsigned int get_nb_cpu() if (n_cpu == 0) { perror("open()"); - fprintf(stderr, "on %s\n", filename); + fprintf(stderr, "on the file: '%s'\n", filename); switch (cpy_errno) { case ENOENT: fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n"); @@ -226,7 +226,7 @@ unsigned int get_nb_cpu() fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n"); exit(98); default: - fprintf(stderr, "Unexpected error"); + fprintf(stderr, "Unexpected error\n"); exit(97); } } -- GitLab From b0ed77f36c82b785f193bf0a41b6fae1760b87e1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 27 Mar 2023 12:39:16 +0200 Subject: [PATCH 213/229] fix: fmt error msg --- tests/small_test.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index 8301ae7..7e8c11e 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -270,8 +270,8 @@ int test(char *file, int line, unsigned int __indentation_level, const void *res 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); + char *fmt_expected = interface->format(buffer_expected, expected); + char *fmt_result = interface->format(buffer_result, result); if (!is_equal) { INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); } -- GitLab From dadb4703629af08e5c329c0d2e1e67330874f6e3 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 27 Mar 2023 12:39:59 +0200 Subject: [PATCH 214/229] getline without alloc --- lib/info_reader.h | 59 +++++++++++++++++++++++-- tests/info_reader.c | 90 ++++++++++++++++++++++++++++++-------- tests/info_reader_test.txt | 9 ++++ 3 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 tests/info_reader_test.txt diff --git a/lib/info_reader.h b/lib/info_reader.h index ec28db6..15a077c 100644 --- a/lib/info_reader.h +++ b/lib/info_reader.h @@ -105,6 +105,24 @@ static bool start_with(const char *prefix, const char *string); */ static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value); +/** +* @brief Reads a line of text from a file stream and stores it in a static + buffer with a maximum size of PAGE_SIZE. + +* This function reads a line of text from the input stream pointed to by +* 'stream'. The line of text is stored in a static buffer with a maximum size of +* PAGE_SIZE. The function updates the pointer pointed to by 'lineptr' to point to +* the buffer containing the line of text. If the line of text is longer than the +* buffer, the function returns -1. If an error occurs, + +* @param lineptr A pointer to a pointer to the buffer where the line of text + will be stored. +* @param stream A pointer to the input stream to read from. +* @return The number of characters read, or -1 if an error occurred the + function returns -1. +*/ +ssize_t buffer_getline(char **lineptr, FILE *stream); + typedef size_t GenericPointer; typedef GenericPointer (CopyAllocator) (char *string); typedef void (Setter) (GenericPointer storage, GenericPointer value); @@ -166,14 +184,50 @@ static unsigned int move_to_next(Parser *parser) return 1; } + +#define PAGE_SIZE 4096 +ssize_t buffer_getline(char **lineptr, FILE *stream) { + ssize_t num_chars_read = 0; + static char buffer[PAGE_SIZE] = {0}; + + if (!lineptr || !stream) { + return -1; + } + + while (1) { + int ch = fgetc(stream); + if (ch == EOF) { + if (num_chars_read == 0) { + return -1; + } else { + break; + } + } + + if (num_chars_read == PAGE_SIZE - 1) { + return -1; + } + + buffer[num_chars_read++] = ch; + if (ch == '\n') { + break; + } + } + + buffer[num_chars_read] = '\0'; + *lineptr = buffer; + + return num_chars_read; +} + + 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) { + while ((read = buffer_getline(&line, parser->file)) != -1) { if (key_assigned == parser->nb_keys && read > 1) { continue; } else if (read == 1) { @@ -194,7 +248,6 @@ static unsigned int parse(Parser *parser) if (key_assigned > 0) { parser->nb_stored++; } - free(line); return 1; } diff --git a/tests/info_reader.c b/tests/info_reader.c index 5000f48..92f2ff9 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -169,28 +169,36 @@ TFUNCTION(test_start_with, { }) #define NONE 0 +#define INIT_KEYFINDER(__key_finder, __key, __delimiter, __copy, __set) \ + do { \ + __key_finder = (KeyFinder) { \ + .key = __key, \ + .delimiter = __delimiter, \ + .copy = __copy, \ + .set = __set \ + }; \ + } while (0); + #define DUMMY_KEYFINDER(__key_finder, __key, __delimiter) \ - do { \ - __key_finder = (KeyFinder) { \ - .key = __key, \ - .delimiter = __delimiter, \ - .copy = NONE, \ - .set = NONE \ - }; \ + INIT_KEYFINDER(__key_finder, __key, __delimiter, NONE, NONE) \ + +#define INIT_PARSER(__parser, __storage, __nb_stored, __capacity, \ + __storage_struct_size, __keys, __nb_keys, __file) \ +do { \ + __parser = (Parser) { \ + .storage = __storage, \ + .nb_stored = __nb_stored, \ + .capacity = __capacity, \ + .storage_struct_size = __storage_struct_size, \ + .keys = __keys, \ + .nb_keys = __nb_keys, \ + .file = __file \ + }; \ } 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); + INIT_PARSER(__parser, NONE, NONE, NONE, NONE, __keys, __nb_keys, NONE) TFUNCTION(test_match, { @@ -275,10 +283,56 @@ TFUNCTION(test_match, { TEST_STR(raw_value, NULL); }) + +#define __NB_KEYS 4 + +typedef struct { + int values[__NB_KEYS]; +} IntArray; + +GenericPointer __test_file_int_allocator(char *s) +{ + unsigned int value = atoi(s); + return (GenericPointer) value; +} + +void __test_file_set_int(GenericPointer storage, GenericPointer data) +{ + IntArray *array = (IntArray*) storage; + int i = (int) data; + array->values[i] = i; +} + +TFUNCTION(test_dummy_file, { + KeyFinder keys[__NB_KEYS]; + INIT_KEYFINDER(keys[0], "int0", " : ", __test_file_int_allocator, __test_file_set_int); + INIT_KEYFINDER(keys[1], "int1", " ", __test_file_int_allocator, __test_file_set_int); + INIT_KEYFINDER(keys[2], "int2", " -> ", __test_file_int_allocator, __test_file_set_int); + INIT_KEYFINDER(keys[3], "int3", "--", __test_file_int_allocator, __test_file_set_int); + + IntArray results; + IntArray expected; + + expected.values[0] = 0; + expected.values[1] = 1; + expected.values[2] = 2; + expected.values[3] = 3; + + Parser parser; + FILE* file = fopen("./tests/info_reader_test.txt", "r"); + INIT_PARSER(parser, (GenericPointer) &results, 0, 1, sizeof(IntArray), keys, __NB_KEYS, file); + parse(&parser); + + for (unsigned int i = 0; i < __NB_KEYS; i++) { + TEST_INT(&(results.values[i]), &(expected.values[i])); + } +}) + 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); + CALL_TFUNCTION(test_dummy_file); }) diff --git a/tests/info_reader_test.txt b/tests/info_reader_test.txt new file mode 100644 index 0000000..17d4ee4 --- /dev/null +++ b/tests/info_reader_test.txt @@ -0,0 +1,9 @@ +noise: +int0 : 0 +noise-- +int1 1 +int2 -> 2 +noise-> +int3--3 +noise----->>ss<< +noiseee -- GitLab From e6199994a3da3d66e0addd1eefd487e263d6cc19 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 27 Mar 2023 15:18:50 +0200 Subject: [PATCH 215/229] fix: leak close --- tests/info_reader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/info_reader.c b/tests/info_reader.c index 92f2ff9..af2873c 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -326,6 +326,7 @@ TFUNCTION(test_dummy_file, { for (unsigned int i = 0; i < __NB_KEYS; i++) { TEST_INT(&(results.values[i]), &(expected.values[i])); } + fclose(file); }) TFILE_ENTRY_POINT(test_info_reader, { -- GitLab From 881086c732d33f02d7a3ef77d9620f06dd33d042 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 27 Mar 2023 15:20:19 +0200 Subject: [PATCH 216/229] fix: make format --- src/amd_rapl.c | 34 +++++++++++++-------------- src/network.c | 6 ++--- tests/info_reader.c | 9 ++++---- tests/util.c | 56 ++++++++++++++++++++++----------------------- 4 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 9eaac45..572ac56 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -201,7 +201,7 @@ void debug_print_amd_rapl(AmdRapl *rapl) unsigned int get_nb_cpu() { char filename[BUFFER_SIZE]; - int cpy_errno; + int cpy_errno; unsigned int n_cpu = 0; for (;; n_cpu++) { @@ -215,22 +215,22 @@ unsigned int get_nb_cpu() close(fd); } - if (n_cpu == 0) { - perror("open()"); - fprintf(stderr, "on the file: '%s'\n", filename); - switch (cpy_errno) { - case ENOENT: - fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n"); - exit(99); - case EACCES: - fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n"); - exit(98); - default: - fprintf(stderr, "Unexpected error\n"); - exit(97); - } - } - // n_cpu > 0 + if (n_cpu == 0) { + perror("open()"); + fprintf(stderr, "on the file: '%s'\n", filename); + switch (cpy_errno) { + case ENOENT: + fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n"); + exit(99); + case EACCES: + fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n"); + exit(98); + default: + fprintf(stderr, "Unexpected error\n"); + exit(97); + } + } + // n_cpu > 0 return n_cpu; } diff --git a/src/network.c b/src/network.c index a668725..fec9424 100644 --- a/src/network.c +++ b/src/network.c @@ -159,9 +159,9 @@ unsigned int init_network(char *dev, void **ptr) /* compare dev name to the previously saved one */ int newdev = 1; for (int i = 0; i < state->ndev && newdev; i++) { - if (strncmp(start_of_dev, state->devs[i], s - start_of_dev) == 0) { - newdev = 0; - } + if (strncmp(start_of_dev, state->devs[i], s - start_of_dev) == 0) { + newdev = 0; + } } if (newdev) { if (state->ndev >= NB_MAX_DEV) { diff --git a/tests/info_reader.c b/tests/info_reader.c index af2873c..1e4f281 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -287,7 +287,7 @@ TFUNCTION(test_match, { #define __NB_KEYS 4 typedef struct { - int values[__NB_KEYS]; + int values[__NB_KEYS]; } IntArray; GenericPointer __test_file_int_allocator(char *s) @@ -298,7 +298,7 @@ GenericPointer __test_file_int_allocator(char *s) void __test_file_set_int(GenericPointer storage, GenericPointer data) { - IntArray *array = (IntArray*) storage; + IntArray *array = (IntArray *) storage; int i = (int) data; array->values[i] = i; } @@ -319,11 +319,12 @@ TFUNCTION(test_dummy_file, { expected.values[3] = 3; Parser parser; - FILE* file = fopen("./tests/info_reader_test.txt", "r"); + FILE *file = fopen("./tests/info_reader_test.txt", "r"); INIT_PARSER(parser, (GenericPointer) &results, 0, 1, sizeof(IntArray), keys, __NB_KEYS, file); parse(&parser); - for (unsigned int i = 0; i < __NB_KEYS; i++) { + for (unsigned int i = 0; i < __NB_KEYS; i++) + { TEST_INT(&(results.values[i]), &(expected.values[i])); } fclose(file); diff --git a/tests/util.c b/tests/util.c index 231ab47..ff979b9 100644 --- a/tests/util.c +++ b/tests/util.c @@ -78,45 +78,45 @@ TFUNCTION(test_modulo_substraction, { }) TFUNCTION(test_max, { - int expected = 0; - int result = 0; + int expected = 0; + int result = 0; - expected = 10; - result = MAX(expected, 9); - TEST_INT(&result, &expected); + expected = 10; + result = MAX(expected, 9); + TEST_INT(&result, &expected); - expected = -15; - result = MAX(expected, -16); - TEST_INT(&result, &expected); + expected = -15; + result = MAX(expected, -16); + TEST_INT(&result, &expected); - expected = 0; - result = MAX(expected, -1); - TEST_INT(&result, &expected); + expected = 0; + result = MAX(expected, -1); + TEST_INT(&result, &expected); - expected = 1; - result = MAX(expected, 0); - TEST_INT(&result, &expected); + expected = 1; + result = MAX(expected, 0); + TEST_INT(&result, &expected); }) TFUNCTION(test_min, { - int expected = 0; - int result = 0; + int expected = 0; + int result = 0; - expected = 9; - result = MIN(expected, 10); - TEST_INT(&result, &expected); + expected = 9; + result = MIN(expected, 10); + TEST_INT(&result, &expected); - expected = -16; - result = MIN(expected, -15); - TEST_INT(&result, &expected); + expected = -16; + result = MIN(expected, -15); + TEST_INT(&result, &expected); - expected = -1; - result = MIN(expected, 0); - TEST_INT(&result, &expected); + expected = -1; + result = MIN(expected, 0); + TEST_INT(&result, &expected); - expected = 0; - result = MIN(expected, 1); - TEST_INT(&result, &expected); + expected = 0; + result = MIN(expected, 1); + TEST_INT(&result, &expected); }) TFILE_ENTRY_POINT(test_util, { -- GitLab From 064cfdf09660498e5b001c5d075585c7530164c3 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 27 Mar 2023 18:55:37 +0200 Subject: [PATCH 217/229] working on progress --- meminfo_option.sh | 48 ++++++ src/meminfo_option.h | 402 +++++++++++++++++++++++++++++++++++++++++++ src/memory_extra.c | 95 ++++++++++ 3 files changed, 545 insertions(+) create mode 100644 meminfo_option.sh create mode 100644 src/meminfo_option.h create mode 100644 src/memory_extra.c diff --git a/meminfo_option.sh b/meminfo_option.sh new file mode 100644 index 0000000..4443868 --- /dev/null +++ b/meminfo_option.sh @@ -0,0 +1,48 @@ +#!bin/sh + +MEMINFO="/proc/meminfo" +COUNT=0 + +function get_meminfo_words { + printf "char *meminfo_words[] = {\n" + while read line; do + COUNT=$(expr $COUNT + 1) + word=$(echo $line | awk '{print $1}') + printf " \"${word::-1}\",\n" + done <$MEMINFO + + printf "};\n\n" +} + +function get_count { + printf "static const unsigned int meminfo_count = $COUNT;\n\n" +} + +function get_meminfo_setter { + count=0 + while [ $count -lt $COUNT ]; do + printf "void set_result_offset$count(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[$count] = (uint64_t) data; +}\n\n" + count=$(expr $count + 1) + done +} + +function get_functions { + printf "static void (*setter_functions[])(GenericPointer, GenericPointer) = {\n" + count=0 + while [ $count -lt $COUNT ]; do + printf " set_result_offset$count,\n" + count=$(expr $count + 1) + done + printf "};\n\n" +} + +DEST="./src/meminfo_option.h" +printf "#include \"inttypes.h\"\n" >$DEST +printf "#include <info_reader.h>\n\n" >>$DEST +get_meminfo_words "./text.h" >>$DEST +get_count >>$DEST +get_meminfo_setter >>$DEST +get_functions >>$DEST diff --git a/src/meminfo_option.h b/src/meminfo_option.h new file mode 100644 index 0000000..f3369b8 --- /dev/null +++ b/src/meminfo_option.h @@ -0,0 +1,402 @@ +#include "inttypes.h" +#include <info_reader.h> +char *meminfo_words[] = { + "MemTotal", + "MemFree", + "MemAvailable", + "Buffers", + "Cached", + "SwapCached", + "Active", + "Inactive", + "Active(anon)", + "Inactive(anon)", + "Active(file)", + "Inactive(file)", + "Unevictable", + "Mlocked", + "SwapTotal", + "SwapFree", + "Zswap", + "Zswapped", + "Dirty", + "Writeback", + "AnonPages", + "Mapped", + "Shmem", + "KReclaimable", + "Slab", + "SReclaimable", + "SUnreclaim", + "KernelStack", + "PageTables", + "SecPageTables", + "NFS_Unstable", + "Bounce", + "WritebackTmp", + "CommitLimit", + "Committed_AS", + "VmallocTotal", + "VmallocUsed", + "VmallocChunk", + "Percpu", + "HardwareCorrupted", + "AnonHugePages", + "ShmemHugePages", + "ShmemPmdMapped", + "FileHugePages", + "FilePmdMapped", + "CmaTotal", + "CmaFree", + "HugePages_Total", + "HugePages_Free", + "HugePages_Rsvd", + "HugePages_Surp", + "Hugepagesize", + "Hugetlb", + "DirectMap4k", + "DirectMap2M", + "DirectMap1G", +}; + +static const unsigned int meminfo_count = 56; + +void set_result_offset0(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[0] = (uint64_t) data; +} + +void set_result_offset1(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[1] = (uint64_t) data; +} + +void set_result_offset2(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[2] = (uint64_t) data; +} + +void set_result_offset3(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[3] = (uint64_t) data; +} + +void set_result_offset4(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[4] = (uint64_t) data; +} + +void set_result_offset5(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[5] = (uint64_t) data; +} + +void set_result_offset6(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[6] = (uint64_t) data; +} + +void set_result_offset7(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[7] = (uint64_t) data; +} + +void set_result_offset8(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[8] = (uint64_t) data; +} + +void set_result_offset9(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[9] = (uint64_t) data; +} + +void set_result_offset10(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[10] = (uint64_t) data; +} + +void set_result_offset11(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[11] = (uint64_t) data; +} + +void set_result_offset12(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[12] = (uint64_t) data; +} + +void set_result_offset13(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[13] = (uint64_t) data; +} + +void set_result_offset14(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[14] = (uint64_t) data; +} + +void set_result_offset15(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[15] = (uint64_t) data; +} + +void set_result_offset16(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[16] = (uint64_t) data; +} + +void set_result_offset17(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[17] = (uint64_t) data; +} + +void set_result_offset18(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[18] = (uint64_t) data; +} + +void set_result_offset19(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[19] = (uint64_t) data; +} + +void set_result_offset20(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[20] = (uint64_t) data; +} + +void set_result_offset21(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[21] = (uint64_t) data; +} + +void set_result_offset22(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[22] = (uint64_t) data; +} + +void set_result_offset23(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[23] = (uint64_t) data; +} + +void set_result_offset24(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[24] = (uint64_t) data; +} + +void set_result_offset25(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[25] = (uint64_t) data; +} + +void set_result_offset26(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[26] = (uint64_t) data; +} + +void set_result_offset27(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[27] = (uint64_t) data; +} + +void set_result_offset28(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[28] = (uint64_t) data; +} + +void set_result_offset29(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[29] = (uint64_t) data; +} + +void set_result_offset30(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[30] = (uint64_t) data; +} + +void set_result_offset31(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[31] = (uint64_t) data; +} + +void set_result_offset32(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[32] = (uint64_t) data; +} + +void set_result_offset33(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[33] = (uint64_t) data; +} + +void set_result_offset34(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[34] = (uint64_t) data; +} + +void set_result_offset35(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[35] = (uint64_t) data; +} + +void set_result_offset36(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[36] = (uint64_t) data; +} + +void set_result_offset37(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[37] = (uint64_t) data; +} + +void set_result_offset38(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[38] = (uint64_t) data; +} + +void set_result_offset39(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[39] = (uint64_t) data; +} + +void set_result_offset40(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[40] = (uint64_t) data; +} + +void set_result_offset41(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[41] = (uint64_t) data; +} + +void set_result_offset42(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[42] = (uint64_t) data; +} + +void set_result_offset43(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[43] = (uint64_t) data; +} + +void set_result_offset44(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[44] = (uint64_t) data; +} + +void set_result_offset45(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[45] = (uint64_t) data; +} + +void set_result_offset46(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[46] = (uint64_t) data; +} + +void set_result_offset47(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[47] = (uint64_t) data; +} + +void set_result_offset48(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[48] = (uint64_t) data; +} + +void set_result_offset49(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[49] = (uint64_t) data; +} + +void set_result_offset50(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[50] = (uint64_t) data; +} + +void set_result_offset51(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[51] = (uint64_t) data; +} + +void set_result_offset52(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[52] = (uint64_t) data; +} + +void set_result_offset53(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[53] = (uint64_t) data; +} + +void set_result_offset54(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[54] = (uint64_t) data; +} + +void set_result_offset55(GenericPointer ptr, GenericPointer data) { + uint64_t* result = (uint64_t *) ptr; + result[55] = (uint64_t) data; +} + +static void (*setter_functions[])(GenericPointer, GenericPointer) = { + set_result_offset0, + set_result_offset1, + set_result_offset2, + set_result_offset3, + set_result_offset4, + set_result_offset5, + set_result_offset6, + set_result_offset7, + set_result_offset8, + set_result_offset9, + set_result_offset10, + set_result_offset11, + set_result_offset12, + set_result_offset13, + set_result_offset14, + set_result_offset15, + set_result_offset16, + set_result_offset17, + set_result_offset18, + set_result_offset19, + set_result_offset20, + set_result_offset21, + set_result_offset22, + set_result_offset23, + set_result_offset24, + set_result_offset25, + set_result_offset26, + set_result_offset27, + set_result_offset28, + set_result_offset29, + set_result_offset30, + set_result_offset31, + set_result_offset32, + set_result_offset33, + set_result_offset34, + set_result_offset35, + set_result_offset36, + set_result_offset37, + set_result_offset38, + set_result_offset39, + set_result_offset40, + set_result_offset41, + set_result_offset42, + set_result_offset43, + set_result_offset44, + set_result_offset45, + set_result_offset46, + set_result_offset47, + set_result_offset48, + set_result_offset49, + set_result_offset50, + set_result_offset51, + set_result_offset52, + set_result_offset53, + set_result_offset54, + set_result_offset55, +}; + diff --git a/src/memory_extra.c b/src/memory_extra.c new file mode 100644 index 0000000..f616870 --- /dev/null +++ b/src/memory_extra.c @@ -0,0 +1,95 @@ +#include "meminfo_option.h" +#include <info_reader.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const char *path = "/proc/meminfo"; + +GenericPointer long_allocator(char *s) { + long value = atol(s); + return (GenericPointer)value; +} + +KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) { + KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); + for (unsigned int i = 0; i < count; i++) { + unsigned int idx = indexes[i]; + KeyFinder key = {.key = meminfo_words[idx], + .delimiter = ":", + .copy = long_allocator, + .set = setter_functions[i]}; + memcpy(&keys[i], &key, sizeof(KeyFinder)); + } + return keys; +} + +void memory_list(char *memory_string, unsigned int *count, + unsigned int *indexes) { + char *token; + *count = 0; + + while ((token = strtok(memory_string, ",")) != NULL) { + memory_string = NULL; + + unsigned int i; + for (i = 0; i < meminfo_count; i++) { + if (strcmp(meminfo_words[i], token) == 0) { + (*count)++; + indexes[*count - 1] = i; + break; + } + } + + if (i == meminfo_count) { + fprintf(stderr, "Unknown memory counter: %s\n", token); + exit(EXIT_FAILURE); + } + + if ((*count) > meminfo_count) { + fprintf(stderr, "Too much counters, there are probably duplicates\n"); + exit(EXIT_FAILURE); + } + } +} + +int main(int argc, char **argv) { + + if (argc != 2) { + fprintf(stderr, "Usage ... [elem1,elem2...]\n"); + exit(EXIT_FAILURE); + } + + unsigned int indexes[meminfo_count]; + unsigned int count = 0; + memory_list(argv[1], &count, indexes); + + printf("%d, count \n", count); + + KeyFinder *keys = build_keyfinder(count, indexes); + uint64_t value[count]; + + // -- Init the parser + Parser parser = {.storage = (GenericPointer)&value, + .capacity = 1, + .storage_struct_size = sizeof(uint64_t) * count, + .keys = keys, + .nb_keys = count, + .file = fopen(path, "r")}; + + // -- Parse the file + while (1) { + parse(&parser); + for (unsigned int i = 0; i < count; i++) { + printf("%s: %" PRIu64 "\n", keys[i].key, value[i]); + } + } + + free(keys); + + // Print and free the results + + fclose(parser.file); + return 0; +} -- GitLab From 5149f2fe08bc672f671b9afff72192885f14b120 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 09:36:14 +0200 Subject: [PATCH 218/229] update: script --- .gitignore | 1 + meminfo_option.sh | 48 --- src/meminfo_option.h | 402 ---------------------- src/meminfo_option.sh | 46 +++ src/{memory_extra.c => memory_counters.c} | 12 +- 5 files changed, 53 insertions(+), 456 deletions(-) delete mode 100644 meminfo_option.sh delete mode 100644 src/meminfo_option.h create mode 100644 src/meminfo_option.sh rename src/{memory_extra.c => memory_counters.c} (89%) diff --git a/.gitignore b/.gitignore index 83a8dc0..eb6940e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ doc/info_reader_ex doc/mojitos.1 tests/run src/counters_option.h +src/meminfo_option.h src/sensors.h sensors.mk bin diff --git a/meminfo_option.sh b/meminfo_option.sh deleted file mode 100644 index 4443868..0000000 --- a/meminfo_option.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!bin/sh - -MEMINFO="/proc/meminfo" -COUNT=0 - -function get_meminfo_words { - printf "char *meminfo_words[] = {\n" - while read line; do - COUNT=$(expr $COUNT + 1) - word=$(echo $line | awk '{print $1}') - printf " \"${word::-1}\",\n" - done <$MEMINFO - - printf "};\n\n" -} - -function get_count { - printf "static const unsigned int meminfo_count = $COUNT;\n\n" -} - -function get_meminfo_setter { - count=0 - while [ $count -lt $COUNT ]; do - printf "void set_result_offset$count(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[$count] = (uint64_t) data; -}\n\n" - count=$(expr $count + 1) - done -} - -function get_functions { - printf "static void (*setter_functions[])(GenericPointer, GenericPointer) = {\n" - count=0 - while [ $count -lt $COUNT ]; do - printf " set_result_offset$count,\n" - count=$(expr $count + 1) - done - printf "};\n\n" -} - -DEST="./src/meminfo_option.h" -printf "#include \"inttypes.h\"\n" >$DEST -printf "#include <info_reader.h>\n\n" >>$DEST -get_meminfo_words "./text.h" >>$DEST -get_count >>$DEST -get_meminfo_setter >>$DEST -get_functions >>$DEST diff --git a/src/meminfo_option.h b/src/meminfo_option.h deleted file mode 100644 index f3369b8..0000000 --- a/src/meminfo_option.h +++ /dev/null @@ -1,402 +0,0 @@ -#include "inttypes.h" -#include <info_reader.h> -char *meminfo_words[] = { - "MemTotal", - "MemFree", - "MemAvailable", - "Buffers", - "Cached", - "SwapCached", - "Active", - "Inactive", - "Active(anon)", - "Inactive(anon)", - "Active(file)", - "Inactive(file)", - "Unevictable", - "Mlocked", - "SwapTotal", - "SwapFree", - "Zswap", - "Zswapped", - "Dirty", - "Writeback", - "AnonPages", - "Mapped", - "Shmem", - "KReclaimable", - "Slab", - "SReclaimable", - "SUnreclaim", - "KernelStack", - "PageTables", - "SecPageTables", - "NFS_Unstable", - "Bounce", - "WritebackTmp", - "CommitLimit", - "Committed_AS", - "VmallocTotal", - "VmallocUsed", - "VmallocChunk", - "Percpu", - "HardwareCorrupted", - "AnonHugePages", - "ShmemHugePages", - "ShmemPmdMapped", - "FileHugePages", - "FilePmdMapped", - "CmaTotal", - "CmaFree", - "HugePages_Total", - "HugePages_Free", - "HugePages_Rsvd", - "HugePages_Surp", - "Hugepagesize", - "Hugetlb", - "DirectMap4k", - "DirectMap2M", - "DirectMap1G", -}; - -static const unsigned int meminfo_count = 56; - -void set_result_offset0(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[0] = (uint64_t) data; -} - -void set_result_offset1(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[1] = (uint64_t) data; -} - -void set_result_offset2(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[2] = (uint64_t) data; -} - -void set_result_offset3(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[3] = (uint64_t) data; -} - -void set_result_offset4(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[4] = (uint64_t) data; -} - -void set_result_offset5(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[5] = (uint64_t) data; -} - -void set_result_offset6(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[6] = (uint64_t) data; -} - -void set_result_offset7(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[7] = (uint64_t) data; -} - -void set_result_offset8(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[8] = (uint64_t) data; -} - -void set_result_offset9(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[9] = (uint64_t) data; -} - -void set_result_offset10(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[10] = (uint64_t) data; -} - -void set_result_offset11(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[11] = (uint64_t) data; -} - -void set_result_offset12(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[12] = (uint64_t) data; -} - -void set_result_offset13(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[13] = (uint64_t) data; -} - -void set_result_offset14(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[14] = (uint64_t) data; -} - -void set_result_offset15(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[15] = (uint64_t) data; -} - -void set_result_offset16(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[16] = (uint64_t) data; -} - -void set_result_offset17(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[17] = (uint64_t) data; -} - -void set_result_offset18(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[18] = (uint64_t) data; -} - -void set_result_offset19(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[19] = (uint64_t) data; -} - -void set_result_offset20(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[20] = (uint64_t) data; -} - -void set_result_offset21(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[21] = (uint64_t) data; -} - -void set_result_offset22(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[22] = (uint64_t) data; -} - -void set_result_offset23(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[23] = (uint64_t) data; -} - -void set_result_offset24(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[24] = (uint64_t) data; -} - -void set_result_offset25(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[25] = (uint64_t) data; -} - -void set_result_offset26(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[26] = (uint64_t) data; -} - -void set_result_offset27(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[27] = (uint64_t) data; -} - -void set_result_offset28(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[28] = (uint64_t) data; -} - -void set_result_offset29(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[29] = (uint64_t) data; -} - -void set_result_offset30(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[30] = (uint64_t) data; -} - -void set_result_offset31(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[31] = (uint64_t) data; -} - -void set_result_offset32(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[32] = (uint64_t) data; -} - -void set_result_offset33(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[33] = (uint64_t) data; -} - -void set_result_offset34(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[34] = (uint64_t) data; -} - -void set_result_offset35(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[35] = (uint64_t) data; -} - -void set_result_offset36(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[36] = (uint64_t) data; -} - -void set_result_offset37(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[37] = (uint64_t) data; -} - -void set_result_offset38(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[38] = (uint64_t) data; -} - -void set_result_offset39(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[39] = (uint64_t) data; -} - -void set_result_offset40(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[40] = (uint64_t) data; -} - -void set_result_offset41(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[41] = (uint64_t) data; -} - -void set_result_offset42(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[42] = (uint64_t) data; -} - -void set_result_offset43(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[43] = (uint64_t) data; -} - -void set_result_offset44(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[44] = (uint64_t) data; -} - -void set_result_offset45(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[45] = (uint64_t) data; -} - -void set_result_offset46(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[46] = (uint64_t) data; -} - -void set_result_offset47(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[47] = (uint64_t) data; -} - -void set_result_offset48(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[48] = (uint64_t) data; -} - -void set_result_offset49(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[49] = (uint64_t) data; -} - -void set_result_offset50(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[50] = (uint64_t) data; -} - -void set_result_offset51(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[51] = (uint64_t) data; -} - -void set_result_offset52(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[52] = (uint64_t) data; -} - -void set_result_offset53(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[53] = (uint64_t) data; -} - -void set_result_offset54(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[54] = (uint64_t) data; -} - -void set_result_offset55(GenericPointer ptr, GenericPointer data) { - uint64_t* result = (uint64_t *) ptr; - result[55] = (uint64_t) data; -} - -static void (*setter_functions[])(GenericPointer, GenericPointer) = { - set_result_offset0, - set_result_offset1, - set_result_offset2, - set_result_offset3, - set_result_offset4, - set_result_offset5, - set_result_offset6, - set_result_offset7, - set_result_offset8, - set_result_offset9, - set_result_offset10, - set_result_offset11, - set_result_offset12, - set_result_offset13, - set_result_offset14, - set_result_offset15, - set_result_offset16, - set_result_offset17, - set_result_offset18, - set_result_offset19, - set_result_offset20, - set_result_offset21, - set_result_offset22, - set_result_offset23, - set_result_offset24, - set_result_offset25, - set_result_offset26, - set_result_offset27, - set_result_offset28, - set_result_offset29, - set_result_offset30, - set_result_offset31, - set_result_offset32, - set_result_offset33, - set_result_offset34, - set_result_offset35, - set_result_offset36, - set_result_offset37, - set_result_offset38, - set_result_offset39, - set_result_offset40, - set_result_offset41, - set_result_offset42, - set_result_offset43, - set_result_offset44, - set_result_offset45, - set_result_offset46, - set_result_offset47, - set_result_offset48, - set_result_offset49, - set_result_offset50, - set_result_offset51, - set_result_offset52, - set_result_offset53, - set_result_offset54, - set_result_offset55, -}; - diff --git a/src/meminfo_option.sh b/src/meminfo_option.sh new file mode 100644 index 0000000..54a2c6e --- /dev/null +++ b/src/meminfo_option.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> + +MEMINFO_PATH="/proc/meminfo" + +FUNCTION_TEMPLATE="void set_result_offset%s(GenericPointer ptr, GenericPointer data) +{ + uint64_t* result = (uint64_t *) ptr; + result[%s] = (uint64_t) data; +}\n\n" + +nb_counters=0 + +echo '#include <inttypes.h>' +echo "#include <info_reader.h>" +echo + +echo 'static char *memory_counters[] = {' +while read line; do + nb_counters=$(expr $nb_counters + 1) + word=$(echo $line | awk '{print $1}') + echo " \"${word::-1}\"," +done <$MEMINFO_PATH +echo "};" +echo + +echo "#define NB_COUNTERS $nb_counters" +echo + +count=0 +while [ $count -lt $nb_counters ]; do + printf "$FUNCTION_TEMPLATE" $count $count + count=$(expr $count + 1) +done + +echo "static void (*setter_functions[])(GenericPointer, GenericPointer) = {" +count=0 +while [ $count -lt $nb_counters ]; do + echo " set_result_offset$count," + count=$(expr $count + 1) +done +echo "};" +echo + diff --git a/src/memory_extra.c b/src/memory_counters.c similarity index 89% rename from src/memory_extra.c rename to src/memory_counters.c index f616870..4572ff0 100644 --- a/src/memory_extra.c +++ b/src/memory_counters.c @@ -16,7 +16,7 @@ KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) { KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); for (unsigned int i = 0; i < count; i++) { unsigned int idx = indexes[i]; - KeyFinder key = {.key = meminfo_words[idx], + KeyFinder key = {.key = memory_counters[idx], .delimiter = ":", .copy = long_allocator, .set = setter_functions[i]}; @@ -34,20 +34,20 @@ void memory_list(char *memory_string, unsigned int *count, memory_string = NULL; unsigned int i; - for (i = 0; i < meminfo_count; i++) { - if (strcmp(meminfo_words[i], token) == 0) { + for (i = 0; i < NB_COUNTERS; i++) { + if (strcmp(memory_counters[i], token) == 0) { (*count)++; indexes[*count - 1] = i; break; } } - if (i == meminfo_count) { + if (i == NB_COUNTERS) { fprintf(stderr, "Unknown memory counter: %s\n", token); exit(EXIT_FAILURE); } - if ((*count) > meminfo_count) { + if ((*count) > NB_COUNTERS) { fprintf(stderr, "Too much counters, there are probably duplicates\n"); exit(EXIT_FAILURE); } @@ -61,7 +61,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - unsigned int indexes[meminfo_count]; + unsigned int indexes[NB_COUNTERS]; unsigned int count = 0; memory_list(argv[1], &count, indexes); -- GitLab From db433cca717ddc0ec8842eb6a3c155817e95a7fc Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 10:00:50 +0200 Subject: [PATCH 219/229] update: create api --- src/memory_counters.c | 74 +++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/memory_counters.c b/src/memory_counters.c index 4572ff0..7225352 100644 --- a/src/memory_counters.c +++ b/src/memory_counters.c @@ -1,4 +1,6 @@ #include "meminfo_option.h" +#include <bits/stdint-uintn.h> +#include <fcntl.h> #include <info_reader.h> #include <inttypes.h> #include <stdio.h> @@ -7,6 +9,12 @@ static const char *path = "/proc/meminfo"; +typedef struct { + KeyFinder *keys; + unsigned int count; + FILE *file; +} MemoryCounters; + GenericPointer long_allocator(char *s) { long value = atol(s); return (GenericPointer)value; @@ -54,42 +62,48 @@ void memory_list(char *memory_string, unsigned int *count, } } -int main(int argc, char **argv) { - - if (argc != 2) { - fprintf(stderr, "Usage ... [elem1,elem2...]\n"); - exit(EXIT_FAILURE); - } - +unsigned int init_memory_counters(char *args, void **ptr) { unsigned int indexes[NB_COUNTERS]; unsigned int count = 0; - memory_list(argv[1], &count, indexes); - - printf("%d, count \n", count); + memory_list(args, &count, indexes); KeyFinder *keys = build_keyfinder(count, indexes); - uint64_t value[count]; + FILE *file = fopen(path, "r"); - // -- Init the parser - Parser parser = {.storage = (GenericPointer)&value, - .capacity = 1, - .storage_struct_size = sizeof(uint64_t) * count, - .keys = keys, - .nb_keys = count, - .file = fopen(path, "r")}; - - // -- Parse the file - while (1) { - parse(&parser); - for (unsigned int i = 0; i < count; i++) { - printf("%s: %" PRIu64 "\n", keys[i].key, value[i]); - } - } + MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); + counters->keys = keys; + counters->count = count; + counters->file = file; - free(keys); + *ptr = (void *)counters; + return count; +} - // Print and free the results +unsigned int get_memory_counters(uint64_t *results, void *ptr) { + MemoryCounters *counters = (MemoryCounters *)ptr; + fseek(counters->file, 0, SEEK_SET); + Parser parser = {.storage = (GenericPointer)results, + .capacity = 1, + .nb_stored = 0, + .storage_struct_size = sizeof(uint64_t) * counters->count, + .keys = counters->keys, + .nb_keys = counters->count, + .file = counters->file}; + + parse(&parser); + return counters->count; +} + +void label_memory_counters(char **labels, void *ptr) { + MemoryCounters *counters = (MemoryCounters *)ptr; + for (unsigned int i = 0; i < counters->count; i++) { + labels[i] = counters->keys[i].key; + } +} - fclose(parser.file); - return 0; +void clean_memory_counters(void *ptr) { + MemoryCounters *counters = (MemoryCounters *)ptr; + fclose(counters->file); + free(counters->keys); + free(ptr); } -- GitLab From f1348876b0dd2f8872f0ebf0bab6b9f80ca63f79 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 10:11:08 +0200 Subject: [PATCH 220/229] update header --- src/memory_counters.c | 13 ++++++++++- src/memory_counters.h | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/memory_counters.h diff --git a/src/memory_counters.c b/src/memory_counters.c index 7225352..23e3f96 100644 --- a/src/memory_counters.c +++ b/src/memory_counters.c @@ -1,5 +1,5 @@ #include "meminfo_option.h" -#include <bits/stdint-uintn.h> +#include "util.h" #include <fcntl.h> #include <info_reader.h> #include <inttypes.h> @@ -107,3 +107,14 @@ void clean_memory_counters(void *ptr) { free(counters->keys); free(ptr); } + +void *show_all_memory_counters(void *none1, size_t none2) { + for (unsigned int i = 0; i < NB_COUNTERS; i++) { + printf("%s\n", memory_counters[i]); + } + + UNUSED(none1); + UNUSED(none2); + exit(EXIT_SUCCESS); + return NULL; /* not reached */ +} diff --git a/src/memory_counters.h b/src/memory_counters.h new file mode 100644 index 0000000..a066c42 --- /dev/null +++ b/src/memory_counters.h @@ -0,0 +1,54 @@ +/******************************************************* + 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_memory_counters(char *args, void **ptr); +unsigned int get_memory_counters(uint64_t *results, void *ptr); +void label_memory_counters(char **labels, void *ptr); +void clean_memory_counters(void *ptr); +void *show_all_memory_counters(void *, size_t); + +sensor memory_counters = { + .init = init_memory_counters, + .get = get_memory_counters, + .clean = clean_memory_counters, + .label = label_memory_counters, + .nb_opt = 2, +}; + +Optparse memory_counters_opt[2] = { + { + .longname = "memory-counters", + .shortname = 'M', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<memory_list>", + .usage_msg = + "memory counters\n" + "\tmemory_list is a coma separated list of memory counters.\n" + "\tEx: Zswap,Zswapped", + }, + { + .longname = "memory-list", + .shortname = 'L', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "list the available performance counters and quit", + .fn = show_all_memory_counters, + }, +}; -- GitLab From a9496a7f8861c9bbe7994b110f89a93f2d6bfdd5 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 10:28:33 +0200 Subject: [PATCH 221/229] update: add in autoconf --- .gitignore | 2 +- configure.sh | 1 + makefile | 6 +++++- src/memory_counters.h | 2 +- src/{meminfo_option.sh => memory_option.sh} | 0 5 files changed, 8 insertions(+), 3 deletions(-) rename src/{meminfo_option.sh => memory_option.sh} (100%) mode change 100644 => 100755 diff --git a/.gitignore b/.gitignore index eb6940e..d652549 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ doc/info_reader_ex doc/mojitos.1 tests/run src/counters_option.h -src/meminfo_option.h +src/memory_option.h src/sensors.h sensors.mk bin diff --git a/configure.sh b/configure.sh index 7e10ec3..56abf93 100755 --- a/configure.sh +++ b/configure.sh @@ -117,6 +117,7 @@ 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" + [ -r /proc/meminfo ] && hdr_whitelist="${hdr_whitelist}|memory_counters" if [ "$(uname -r | cut -d "." -f 1)" -gt "2" ]; then hdr_whitelist="${hdr_whitelist}|memory" diff --git a/makefile b/makefile index f25d563..63fa983 100644 --- a/makefile +++ b/makefile @@ -40,8 +40,9 @@ $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o $(OBJ): $(OBJ_DIR) $(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h +$(OBJ_DIR)/memory_counters.o: $(SRC_DIR)/memory_option.h -$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(SRC_DIR)/counters_option.h +$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(SRC_DIR)/counters_option.h $(SRC_DIR)/memory_counters.h $(CC) $(CFLAGS) -c $< -o $@ $(OBJ_DIR)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h @@ -50,6 +51,9 @@ $(OBJ_DIR)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h $(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh sh ./$(SRC_DIR)/counters_option.sh > $(SRC_DIR)/counters_option.h +$(SRC_DIR)/memory_option.h: $(SRC_DIR)/memory_option.sh + sh ./$(SRC_DIR)/memory_option.sh > $(SRC_DIR)/memory_option.h + $(OBJ_DIR): mkdir -p $(OBJ_DIR) diff --git a/src/memory_counters.h b/src/memory_counters.h index a066c42..a0b9613 100644 --- a/src/memory_counters.h +++ b/src/memory_counters.h @@ -24,7 +24,7 @@ void label_memory_counters(char **labels, void *ptr); void clean_memory_counters(void *ptr); void *show_all_memory_counters(void *, size_t); -sensor memory_counters = { +Sensor memory_counters = { .init = init_memory_counters, .get = get_memory_counters, .clean = clean_memory_counters, diff --git a/src/meminfo_option.sh b/src/memory_option.sh old mode 100644 new mode 100755 similarity index 100% rename from src/meminfo_option.sh rename to src/memory_option.sh -- GitLab From 0e090d56181052a6fd014377602915efd8d69c7c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 10:29:39 +0200 Subject: [PATCH 222/229] fix header name --- src/memory_counters.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory_counters.c b/src/memory_counters.c index 23e3f96..8e8e916 100644 --- a/src/memory_counters.c +++ b/src/memory_counters.c @@ -1,4 +1,4 @@ -#include "meminfo_option.h" +#include "memory_option.h" #include "util.h" #include <fcntl.h> #include <info_reader.h> -- GitLab From e969987e3c39fdd4e7ddcdbc084a89fb00431cda Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 10:43:45 +0200 Subject: [PATCH 223/229] fix: clean, usage --- makefile | 1 + src/memory_counters.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 63fa983..a57eca2 100644 --- a/makefile +++ b/makefile @@ -75,6 +75,7 @@ format: clean: \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \ $(SRC_DIR)/counters_option.h \ + $(SRC_DIR)/memory_option.h \ $(TESTS_DIR)/run \ $(DOC_DIR)/test_main_ex \ $(DOC_DIR)/info_reader_ex diff --git a/src/memory_counters.h b/src/memory_counters.h index a0b9613..50e0be3 100644 --- a/src/memory_counters.h +++ b/src/memory_counters.h @@ -48,7 +48,7 @@ Optparse memory_counters_opt[2] = { .shortname = 'L', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "list the available performance counters and quit", + .usage_msg = "list the available memory counters and quit", .fn = show_all_memory_counters, }, }; -- GitLab From aa98e7f8ce29bd899fd484883bb3865d063d4d97 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 28 Mar 2023 10:52:08 +0200 Subject: [PATCH 224/229] format --- src/memory_counters.c | 180 ++++++++++++++++++++++-------------------- src/memory_counters.h | 6 +- 2 files changed, 98 insertions(+), 88 deletions(-) diff --git a/src/memory_counters.c b/src/memory_counters.c index 8e8e916..185f454 100644 --- a/src/memory_counters.c +++ b/src/memory_counters.c @@ -10,111 +10,121 @@ static const char *path = "/proc/meminfo"; typedef struct { - KeyFinder *keys; - unsigned int count; - FILE *file; + KeyFinder *keys; + unsigned int count; + FILE *file; } MemoryCounters; -GenericPointer long_allocator(char *s) { - long value = atol(s); - return (GenericPointer)value; +GenericPointer long_allocator(char *s) +{ + long value = atol(s); + return (GenericPointer)value; } -KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) { - KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); - for (unsigned int i = 0; i < count; i++) { - unsigned int idx = indexes[i]; - KeyFinder key = {.key = memory_counters[idx], - .delimiter = ":", - .copy = long_allocator, - .set = setter_functions[i]}; - memcpy(&keys[i], &key, sizeof(KeyFinder)); - } - return keys; +KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) +{ + KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); + for (unsigned int i = 0; i < count; i++) { + unsigned int idx = indexes[i]; + KeyFinder key = {.key = memory_counters[idx], + .delimiter = ":", + .copy = long_allocator, + .set = setter_functions[i] + }; + memcpy(&keys[i], &key, sizeof(KeyFinder)); + } + return keys; } void memory_list(char *memory_string, unsigned int *count, - unsigned int *indexes) { - char *token; - *count = 0; - - while ((token = strtok(memory_string, ",")) != NULL) { - memory_string = NULL; - - unsigned int i; - for (i = 0; i < NB_COUNTERS; i++) { - if (strcmp(memory_counters[i], token) == 0) { - (*count)++; - indexes[*count - 1] = i; - break; - } - } - - if (i == NB_COUNTERS) { - fprintf(stderr, "Unknown memory counter: %s\n", token); - exit(EXIT_FAILURE); + unsigned int *indexes) +{ + char *token; + *count = 0; + + while ((token = strtok(memory_string, ",")) != NULL) { + memory_string = NULL; + + unsigned int i; + for (i = 0; i < NB_COUNTERS; i++) { + if (strcmp(memory_counters[i], token) == 0) { + (*count)++; + indexes[*count - 1] = i; + break; + } + } + + if (i == NB_COUNTERS) { + fprintf(stderr, "Unknown memory counter: %s\n", token); + exit(EXIT_FAILURE); + } + + if ((*count) > NB_COUNTERS) { + fprintf(stderr, "Too much counters, there are probably duplicates\n"); + exit(EXIT_FAILURE); + } } - - if ((*count) > NB_COUNTERS) { - fprintf(stderr, "Too much counters, there are probably duplicates\n"); - exit(EXIT_FAILURE); - } - } } -unsigned int init_memory_counters(char *args, void **ptr) { - unsigned int indexes[NB_COUNTERS]; - unsigned int count = 0; - memory_list(args, &count, indexes); +unsigned int init_memory_counters(char *args, void **ptr) +{ + unsigned int indexes[NB_COUNTERS]; + unsigned int count = 0; + memory_list(args, &count, indexes); - KeyFinder *keys = build_keyfinder(count, indexes); - FILE *file = fopen(path, "r"); + KeyFinder *keys = build_keyfinder(count, indexes); + FILE *file = fopen(path, "r"); - MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); - counters->keys = keys; - counters->count = count; - counters->file = file; + MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); + counters->keys = keys; + counters->count = count; + counters->file = file; - *ptr = (void *)counters; - return count; + *ptr = (void *)counters; + return count; } -unsigned int get_memory_counters(uint64_t *results, void *ptr) { - MemoryCounters *counters = (MemoryCounters *)ptr; - fseek(counters->file, 0, SEEK_SET); - Parser parser = {.storage = (GenericPointer)results, - .capacity = 1, - .nb_stored = 0, - .storage_struct_size = sizeof(uint64_t) * counters->count, - .keys = counters->keys, - .nb_keys = counters->count, - .file = counters->file}; - - parse(&parser); - return counters->count; +unsigned int get_memory_counters(uint64_t *results, void *ptr) +{ + MemoryCounters *counters = (MemoryCounters *)ptr; + fseek(counters->file, 0, SEEK_SET); + Parser parser = {.storage = (GenericPointer)results, + .capacity = 1, + .nb_stored = 0, + .storage_struct_size = sizeof(uint64_t) * counters->count, + .keys = counters->keys, + .nb_keys = counters->count, + .file = counters->file + }; + + parse(&parser); + return counters->count; } -void label_memory_counters(char **labels, void *ptr) { - MemoryCounters *counters = (MemoryCounters *)ptr; - for (unsigned int i = 0; i < counters->count; i++) { - labels[i] = counters->keys[i].key; - } +void label_memory_counters(char **labels, void *ptr) +{ + MemoryCounters *counters = (MemoryCounters *)ptr; + for (unsigned int i = 0; i < counters->count; i++) { + labels[i] = counters->keys[i].key; + } } -void clean_memory_counters(void *ptr) { - MemoryCounters *counters = (MemoryCounters *)ptr; - fclose(counters->file); - free(counters->keys); - free(ptr); +void clean_memory_counters(void *ptr) +{ + MemoryCounters *counters = (MemoryCounters *)ptr; + fclose(counters->file); + free(counters->keys); + free(ptr); } -void *show_all_memory_counters(void *none1, size_t none2) { - for (unsigned int i = 0; i < NB_COUNTERS; i++) { - printf("%s\n", memory_counters[i]); - } +void *show_all_memory_counters(void *none1, size_t none2) +{ + for (unsigned int i = 0; i < NB_COUNTERS; i++) { + printf("%s\n", memory_counters[i]); + } - UNUSED(none1); - UNUSED(none2); - exit(EXIT_SUCCESS); - return NULL; /* not reached */ + UNUSED(none1); + UNUSED(none2); + exit(EXIT_SUCCESS); + return NULL; /* not reached */ } diff --git a/src/memory_counters.h b/src/memory_counters.h index 50e0be3..eaf9f36 100644 --- a/src/memory_counters.h +++ b/src/memory_counters.h @@ -39,9 +39,9 @@ Optparse memory_counters_opt[2] = { .argtype = OPTPARSE_REQUIRED, .usage_arg = "<memory_list>", .usage_msg = - "memory counters\n" - "\tmemory_list is a coma separated list of memory counters.\n" - "\tEx: Zswap,Zswapped", + "memory counters\n" + "\tmemory_list is a coma separated list of memory counters.\n" + "\tEx: Zswap,Zswapped", }, { .longname = "memory-list", -- GitLab From b6fb43a0eb175610ea618bcee8ab765e511c3c05 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Thu, 30 Mar 2023 15:58:48 +0200 Subject: [PATCH 225/229] modify memory_option.sh --- src/memory_option.sh | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/memory_option.sh b/src/memory_option.sh index 54a2c6e..30a3831 100755 --- a/src/memory_option.sh +++ b/src/memory_option.sh @@ -3,9 +3,9 @@ # SPDX-License-Identifier: GPL-3.0-or-later # Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> -MEMINFO_PATH="/proc/meminfo" +meminfo_path=/proc/meminfo -FUNCTION_TEMPLATE="void set_result_offset%s(GenericPointer ptr, GenericPointer data) +function_template="void set_result_offset%s(GenericPointer ptr, GenericPointer data) { uint64_t* result = (uint64_t *) ptr; result[%s] = (uint64_t) data; @@ -14,16 +14,15 @@ FUNCTION_TEMPLATE="void set_result_offset%s(GenericPointer ptr, GenericPointer d nb_counters=0 echo '#include <inttypes.h>' -echo "#include <info_reader.h>" +echo '#include <info_reader.h>' echo echo 'static char *memory_counters[] = {' while read line; do - nb_counters=$(expr $nb_counters + 1) - word=$(echo $line | awk '{print $1}') - echo " \"${word::-1}\"," -done <$MEMINFO_PATH -echo "};" + : $((nb_counters += 1)) + echo "$line" | awk -F ':' '{printf(" \"%s\",\n", $1)}' +done < "$meminfo_path" +echo '};' echo echo "#define NB_COUNTERS $nb_counters" @@ -31,16 +30,16 @@ echo count=0 while [ $count -lt $nb_counters ]; do - printf "$FUNCTION_TEMPLATE" $count $count - count=$(expr $count + 1) + printf "$function_template" $count $count + : $((count += 1)) done -echo "static void (*setter_functions[])(GenericPointer, GenericPointer) = {" +echo 'static void (*setter_functions[])(GenericPointer, GenericPointer) = {' count=0 while [ $count -lt $nb_counters ]; do echo " set_result_offset$count," - count=$(expr $count + 1) + : $((count += 1)) done -echo "};" +echo '};' echo -- GitLab From 2ad61f79f7eb594e04afb260db8839cb0be5ec53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Flor=C3=A9al=20Risso?= <floreal.risso@univ-tlse3.fr> Date: Wed, 19 Apr 2023 08:48:51 +0200 Subject: [PATCH 226/229] fix: make dependency --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index a57eca2..3997f40 100644 --- a/makefile +++ b/makefile @@ -42,7 +42,7 @@ $(OBJ): $(OBJ_DIR) $(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h $(OBJ_DIR)/memory_counters.o: $(SRC_DIR)/memory_option.h -$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(SRC_DIR)/counters_option.h $(SRC_DIR)/memory_counters.h +$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(CC) $(CFLAGS) -c $< -o $@ $(OBJ_DIR)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h -- GitLab From a7c3287ae184633e49b732938eaf4d6ecfd0dd56 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Thu, 20 Apr 2023 10:05:05 +0200 Subject: [PATCH 227/229] fix make --- README.md | 14 ++- configure.sh | 4 +- lib/info_reader.c | 146 ++++++++++++++++++++++++++ lib/info_reader.h | 236 ++++++++++-------------------------------- makefile | 15 ++- src/memory_counters.c | 180 +++++++++++++++----------------- 6 files changed, 313 insertions(+), 282 deletions(-) create mode 100644 lib/info_reader.c diff --git a/README.md b/README.md index 9fee622..4c0b186 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The following is an exhaustive list of all the sensors (it is very likely that one will not have all the sensors activated in his build): ```bash SENSORS: --a|--amd-rapl +-r|--amd-rapl AMD RAPL -p|--perf-list <perf_list> performance counters @@ -41,8 +41,20 @@ SENSORS: system load -d|--net-dev <net_dev> network monitoring (if network_device is X, tries to detect it automatically) +-n|--nvidia-gpu + provides basic gpu information [clocks, memory, utilization, power, temperature]. -r|--intel-rapl INTEL RAPL +-c|--cpu-temp + processor temperature +-m|--memory + Retrieves information about the memory via the syscall 'sysinfo(2)'. +-M|--memory-counters <memory_list> + memory counters + memory_list is a coma separated list of memory counters. + Ex: Zswap,Zswapped +-L|--memory-list + list the available memory counters and quit ``` ## Installation Instructions diff --git a/configure.sh b/configure.sh index 56abf93..1246b0c 100755 --- a/configure.sh +++ b/configure.sh @@ -29,7 +29,7 @@ debug=0 target_hdr=src/sensors.h target_mk=sensors.mk -nonsensor='counters_option|sensors|util' +nonsensor='counters_option|memory_option|sensors|util' hdr_blacklist=$nonsensor hdr_whitelist='' @@ -157,6 +157,8 @@ detect_caps() { case $1 in --all | -a) all=1 + NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml" + NVML_IFLAGS="-I/usr/local/cuda/include" ;; esac diff --git a/lib/info_reader.c b/lib/info_reader.c new file mode 100644 index 0000000..d23f554 --- /dev/null +++ b/lib/info_reader.c @@ -0,0 +1,146 @@ +#include <info_reader.h> + + 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); +} + + 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; +} + + unsigned int move_to_next(Parser *parser) +{ + parser->nb_stored += 1; + if (parser->nb_stored >= parser->capacity) { + return 0; + } + return 1; +} + + +#define PAGE_SIZE 4096 +ssize_t buffer_getline(char **lineptr, FILE *stream) { + ssize_t num_chars_read = 0; + static char buffer[PAGE_SIZE] = {0}; + + if (!lineptr || !stream) { + return -1; + } + + while (1) { + int ch = fgetc(stream); + if (ch == EOF) { + if (num_chars_read == 0) { + return -1; + } else { + break; + } + } + + if (num_chars_read == PAGE_SIZE - 1) { + return -1; + } + + buffer[num_chars_read++] = ch; + if (ch == '\n') { + break; + } + } + + buffer[num_chars_read] = '\0'; + *lineptr = buffer; + + return num_chars_read; +} + + + unsigned int parse(Parser *parser) +{ + char *line = NULL; + ssize_t read; + unsigned int key_assigned = 0; + + while ((read = buffer_getline(&line, 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++; + } + return 1; +} + + + + 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; + } + } +} + + 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; + } +} + +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; + } +} diff --git a/lib/info_reader.h b/lib/info_reader.h index 15a077c..403bb19 100644 --- a/lib/info_reader.h +++ b/lib/info_reader.h @@ -21,36 +21,42 @@ #ifndef _INFO_READER_H #define _INFO_READER_H -#include <string.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> /** * @struct Parser * @brief The parser struct - * The struct containing all the necessary informations and functions to parse a file + * 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 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 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 + * 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; /** @@ -68,20 +74,24 @@ typedef struct KeyFinder KeyFinder; * @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); +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. + * @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. + * 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,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); +void replace_first(char *string, char from, char to); /** * @brief Check if a string starts with a prefix. @@ -89,21 +99,25 @@ static void replace_first(char *string, char from, char to); * @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. + * @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); +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. + * @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); +unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, + char **raw_value); /** * @brief Reads a line of text from a file stream and stores it in a static @@ -111,7 +125,8 @@ static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, ch * This function reads a line of text from the input stream pointed to by * 'stream'. The line of text is stored in a static buffer with a maximum size of -* PAGE_SIZE. The function updates the pointer pointed to by 'lineptr' to point to +* PAGE_SIZE. The function updates the pointer pointed to by 'lineptr' to point +to * the buffer containing the line of text. If the line of text is longer than the * buffer, the function returns -1. If an error occurs, @@ -123,174 +138,35 @@ static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, ch */ ssize_t buffer_getline(char **lineptr, FILE *stream); +/** + * @brief Parse with the configured parser. + * + * @param parser the parser. + */ +unsigned int parse(Parser *parser); + typedef size_t GenericPointer; -typedef GenericPointer (CopyAllocator) (char *string); -typedef void (Setter) (GenericPointer storage, GenericPointer value); +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 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; -} - - -#define PAGE_SIZE 4096 -ssize_t buffer_getline(char **lineptr, FILE *stream) { - ssize_t num_chars_read = 0; - static char buffer[PAGE_SIZE] = {0}; - - if (!lineptr || !stream) { - return -1; - } - - while (1) { - int ch = fgetc(stream); - if (ch == EOF) { - if (num_chars_read == 0) { - return -1; - } else { - break; - } - } - - if (num_chars_read == PAGE_SIZE - 1) { - return -1; - } - - buffer[num_chars_read++] = ch; - if (ch == '\n') { - break; - } - } - - buffer[num_chars_read] = '\0'; - *lineptr = buffer; - - return num_chars_read; -} - - -static unsigned int parse(Parser *parser) -{ - char *line = NULL; - ssize_t read; - unsigned int key_assigned = 0; - - while ((read = buffer_getline(&line, 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++; - } - 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 3997f40..4dcbce4 100644 --- a/makefile +++ b/makefile @@ -3,6 +3,7 @@ SRC_DIR = src DOC_DIR = doc OBJ_DIR = obj +LIB_DIR = lib BIN_DIR = bin TESTS_DIR = tests @@ -25,8 +26,9 @@ NVML_IFLAGS = include ./sensors.mk OBJ = \ - $(CAPTOR_OBJ) \ - $(OBJ_DIR)/util.o + $(OBJ_DIR)/util.o \ + $(OBJ_DIR)/info_reader.o \ + $(CAPTOR_OBJ) options: @echo BIN: $(BIN) @@ -48,6 +50,9 @@ $(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(OBJ_DIR)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h $(CC) $(CFLAGS) -c $< -o $@ +$(OBJ_DIR)/info_reader.o: $(LIB_DIR)/info_reader.c + $(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 @@ -63,8 +68,8 @@ $(BIN_DIR): debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og debug: $(BIN) -tests: - $(CC) $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run +tests: $(OBJ_DIR)/util.o $(OBJ_DIR)/info_reader.o + $(CC) $(CPPFLAGS) $(OBJ_DIR)/util.o $(OBJ_DIR)/info_reader.o $(TESTS_DIR)/main.c -o $(TESTS_DIR)/run $(TESTS_DIR)/run format: @@ -80,7 +85,7 @@ clean: $(DOC_DIR)/test_main_ex \ $(DOC_DIR)/info_reader_ex -readme: $(BIN) +readme: sh ./tools/update-readme-usage.sh man: $(BIN) diff --git a/src/memory_counters.c b/src/memory_counters.c index 185f454..8e8e916 100644 --- a/src/memory_counters.c +++ b/src/memory_counters.c @@ -10,121 +10,111 @@ static const char *path = "/proc/meminfo"; typedef struct { - KeyFinder *keys; - unsigned int count; - FILE *file; + KeyFinder *keys; + unsigned int count; + FILE *file; } MemoryCounters; -GenericPointer long_allocator(char *s) -{ - long value = atol(s); - return (GenericPointer)value; +GenericPointer long_allocator(char *s) { + long value = atol(s); + return (GenericPointer)value; } -KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) -{ - KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); - for (unsigned int i = 0; i < count; i++) { - unsigned int idx = indexes[i]; - KeyFinder key = {.key = memory_counters[idx], - .delimiter = ":", - .copy = long_allocator, - .set = setter_functions[i] - }; - memcpy(&keys[i], &key, sizeof(KeyFinder)); - } - return keys; +KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) { + KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); + for (unsigned int i = 0; i < count; i++) { + unsigned int idx = indexes[i]; + KeyFinder key = {.key = memory_counters[idx], + .delimiter = ":", + .copy = long_allocator, + .set = setter_functions[i]}; + memcpy(&keys[i], &key, sizeof(KeyFinder)); + } + return keys; } void memory_list(char *memory_string, unsigned int *count, - unsigned int *indexes) -{ - char *token; - *count = 0; - - while ((token = strtok(memory_string, ",")) != NULL) { - memory_string = NULL; - - unsigned int i; - for (i = 0; i < NB_COUNTERS; i++) { - if (strcmp(memory_counters[i], token) == 0) { - (*count)++; - indexes[*count - 1] = i; - break; - } - } - - if (i == NB_COUNTERS) { - fprintf(stderr, "Unknown memory counter: %s\n", token); - exit(EXIT_FAILURE); - } - - if ((*count) > NB_COUNTERS) { - fprintf(stderr, "Too much counters, there are probably duplicates\n"); - exit(EXIT_FAILURE); - } + unsigned int *indexes) { + char *token; + *count = 0; + + while ((token = strtok(memory_string, ",")) != NULL) { + memory_string = NULL; + + unsigned int i; + for (i = 0; i < NB_COUNTERS; i++) { + if (strcmp(memory_counters[i], token) == 0) { + (*count)++; + indexes[*count - 1] = i; + break; + } + } + + if (i == NB_COUNTERS) { + fprintf(stderr, "Unknown memory counter: %s\n", token); + exit(EXIT_FAILURE); } + + if ((*count) > NB_COUNTERS) { + fprintf(stderr, "Too much counters, there are probably duplicates\n"); + exit(EXIT_FAILURE); + } + } } -unsigned int init_memory_counters(char *args, void **ptr) -{ - unsigned int indexes[NB_COUNTERS]; - unsigned int count = 0; - memory_list(args, &count, indexes); +unsigned int init_memory_counters(char *args, void **ptr) { + unsigned int indexes[NB_COUNTERS]; + unsigned int count = 0; + memory_list(args, &count, indexes); - KeyFinder *keys = build_keyfinder(count, indexes); - FILE *file = fopen(path, "r"); + KeyFinder *keys = build_keyfinder(count, indexes); + FILE *file = fopen(path, "r"); - MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); - counters->keys = keys; - counters->count = count; - counters->file = file; + MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); + counters->keys = keys; + counters->count = count; + counters->file = file; - *ptr = (void *)counters; - return count; + *ptr = (void *)counters; + return count; } -unsigned int get_memory_counters(uint64_t *results, void *ptr) -{ - MemoryCounters *counters = (MemoryCounters *)ptr; - fseek(counters->file, 0, SEEK_SET); - Parser parser = {.storage = (GenericPointer)results, - .capacity = 1, - .nb_stored = 0, - .storage_struct_size = sizeof(uint64_t) * counters->count, - .keys = counters->keys, - .nb_keys = counters->count, - .file = counters->file - }; - - parse(&parser); - return counters->count; +unsigned int get_memory_counters(uint64_t *results, void *ptr) { + MemoryCounters *counters = (MemoryCounters *)ptr; + fseek(counters->file, 0, SEEK_SET); + Parser parser = {.storage = (GenericPointer)results, + .capacity = 1, + .nb_stored = 0, + .storage_struct_size = sizeof(uint64_t) * counters->count, + .keys = counters->keys, + .nb_keys = counters->count, + .file = counters->file}; + + parse(&parser); + return counters->count; } -void label_memory_counters(char **labels, void *ptr) -{ - MemoryCounters *counters = (MemoryCounters *)ptr; - for (unsigned int i = 0; i < counters->count; i++) { - labels[i] = counters->keys[i].key; - } +void label_memory_counters(char **labels, void *ptr) { + MemoryCounters *counters = (MemoryCounters *)ptr; + for (unsigned int i = 0; i < counters->count; i++) { + labels[i] = counters->keys[i].key; + } } -void clean_memory_counters(void *ptr) -{ - MemoryCounters *counters = (MemoryCounters *)ptr; - fclose(counters->file); - free(counters->keys); - free(ptr); +void clean_memory_counters(void *ptr) { + MemoryCounters *counters = (MemoryCounters *)ptr; + fclose(counters->file); + free(counters->keys); + free(ptr); } -void *show_all_memory_counters(void *none1, size_t none2) -{ - for (unsigned int i = 0; i < NB_COUNTERS; i++) { - printf("%s\n", memory_counters[i]); - } +void *show_all_memory_counters(void *none1, size_t none2) { + for (unsigned int i = 0; i < NB_COUNTERS; i++) { + printf("%s\n", memory_counters[i]); + } - UNUSED(none1); - UNUSED(none2); - exit(EXIT_SUCCESS); - return NULL; /* not reached */ + UNUSED(none1); + UNUSED(none2); + exit(EXIT_SUCCESS); + return NULL; /* not reached */ } -- GitLab From 079b25060bce14922749bc006e2dd8b08486baa1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Thu, 20 Apr 2023 10:15:52 +0200 Subject: [PATCH 228/229] format --- doc/info_reader_ex.c | 85 +++++++++++++------- src/memory_counters.c | 180 ++++++++++++++++++++++-------------------- 2 files changed, 152 insertions(+), 113 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index f1e6d96..d99e916 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -18,8 +18,10 @@ *******************************************************/ +// ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex +// info_reader_ex.c ./../src/util.c && ./info_reader_ex -// ~/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.c" #include "./../lib/info_reader.h" #define MAX_PROCS 64 @@ -40,7 +42,7 @@ typedef struct { GenericPointer int_allocator(char *s) { unsigned int value = atoi(s); - return (GenericPointer) value; + return (GenericPointer)value; } // -- Define the behaviour if the attempted value is a string @@ -48,49 +50,49 @@ GenericPointer string_allocator(char *s) { char *value = malloc(strlen(s) + 1); strcpy(value, s); - return (GenericPointer) value; + return (GenericPointer)value; } // -- Define the processor setter void set_processor(GenericPointer storage, GenericPointer data) { - Cpu *cpu = (Cpu *) storage; + 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; + 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 *cpu = (Cpu *)storage; cpu->family = data; } // -- Define the core_id setter void set_core_id(GenericPointer storage, GenericPointer data) { - Cpu *cpu = (Cpu *) storage; + 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 *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; + Cpu *cpu = (Cpu *)storage; + cpu->model_name = (char *)data; } int main() @@ -98,26 +100,54 @@ 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} + 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); + 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") - }; + 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); @@ -137,4 +167,3 @@ int main() printf("==============================\n"); return 0; } - diff --git a/src/memory_counters.c b/src/memory_counters.c index 8e8e916..185f454 100644 --- a/src/memory_counters.c +++ b/src/memory_counters.c @@ -10,111 +10,121 @@ static const char *path = "/proc/meminfo"; typedef struct { - KeyFinder *keys; - unsigned int count; - FILE *file; + KeyFinder *keys; + unsigned int count; + FILE *file; } MemoryCounters; -GenericPointer long_allocator(char *s) { - long value = atol(s); - return (GenericPointer)value; +GenericPointer long_allocator(char *s) +{ + long value = atol(s); + return (GenericPointer)value; } -KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) { - KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); - for (unsigned int i = 0; i < count; i++) { - unsigned int idx = indexes[i]; - KeyFinder key = {.key = memory_counters[idx], - .delimiter = ":", - .copy = long_allocator, - .set = setter_functions[i]}; - memcpy(&keys[i], &key, sizeof(KeyFinder)); - } - return keys; +KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes) +{ + KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder)); + for (unsigned int i = 0; i < count; i++) { + unsigned int idx = indexes[i]; + KeyFinder key = {.key = memory_counters[idx], + .delimiter = ":", + .copy = long_allocator, + .set = setter_functions[i] + }; + memcpy(&keys[i], &key, sizeof(KeyFinder)); + } + return keys; } void memory_list(char *memory_string, unsigned int *count, - unsigned int *indexes) { - char *token; - *count = 0; - - while ((token = strtok(memory_string, ",")) != NULL) { - memory_string = NULL; - - unsigned int i; - for (i = 0; i < NB_COUNTERS; i++) { - if (strcmp(memory_counters[i], token) == 0) { - (*count)++; - indexes[*count - 1] = i; - break; - } - } - - if (i == NB_COUNTERS) { - fprintf(stderr, "Unknown memory counter: %s\n", token); - exit(EXIT_FAILURE); + unsigned int *indexes) +{ + char *token; + *count = 0; + + while ((token = strtok(memory_string, ",")) != NULL) { + memory_string = NULL; + + unsigned int i; + for (i = 0; i < NB_COUNTERS; i++) { + if (strcmp(memory_counters[i], token) == 0) { + (*count)++; + indexes[*count - 1] = i; + break; + } + } + + if (i == NB_COUNTERS) { + fprintf(stderr, "Unknown memory counter: %s\n", token); + exit(EXIT_FAILURE); + } + + if ((*count) > NB_COUNTERS) { + fprintf(stderr, "Too much counters, there are probably duplicates\n"); + exit(EXIT_FAILURE); + } } - - if ((*count) > NB_COUNTERS) { - fprintf(stderr, "Too much counters, there are probably duplicates\n"); - exit(EXIT_FAILURE); - } - } } -unsigned int init_memory_counters(char *args, void **ptr) { - unsigned int indexes[NB_COUNTERS]; - unsigned int count = 0; - memory_list(args, &count, indexes); +unsigned int init_memory_counters(char *args, void **ptr) +{ + unsigned int indexes[NB_COUNTERS]; + unsigned int count = 0; + memory_list(args, &count, indexes); - KeyFinder *keys = build_keyfinder(count, indexes); - FILE *file = fopen(path, "r"); + KeyFinder *keys = build_keyfinder(count, indexes); + FILE *file = fopen(path, "r"); - MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); - counters->keys = keys; - counters->count = count; - counters->file = file; + MemoryCounters *counters = calloc(1, sizeof(MemoryCounters)); + counters->keys = keys; + counters->count = count; + counters->file = file; - *ptr = (void *)counters; - return count; + *ptr = (void *)counters; + return count; } -unsigned int get_memory_counters(uint64_t *results, void *ptr) { - MemoryCounters *counters = (MemoryCounters *)ptr; - fseek(counters->file, 0, SEEK_SET); - Parser parser = {.storage = (GenericPointer)results, - .capacity = 1, - .nb_stored = 0, - .storage_struct_size = sizeof(uint64_t) * counters->count, - .keys = counters->keys, - .nb_keys = counters->count, - .file = counters->file}; - - parse(&parser); - return counters->count; +unsigned int get_memory_counters(uint64_t *results, void *ptr) +{ + MemoryCounters *counters = (MemoryCounters *)ptr; + fseek(counters->file, 0, SEEK_SET); + Parser parser = {.storage = (GenericPointer)results, + .capacity = 1, + .nb_stored = 0, + .storage_struct_size = sizeof(uint64_t) * counters->count, + .keys = counters->keys, + .nb_keys = counters->count, + .file = counters->file + }; + + parse(&parser); + return counters->count; } -void label_memory_counters(char **labels, void *ptr) { - MemoryCounters *counters = (MemoryCounters *)ptr; - for (unsigned int i = 0; i < counters->count; i++) { - labels[i] = counters->keys[i].key; - } +void label_memory_counters(char **labels, void *ptr) +{ + MemoryCounters *counters = (MemoryCounters *)ptr; + for (unsigned int i = 0; i < counters->count; i++) { + labels[i] = counters->keys[i].key; + } } -void clean_memory_counters(void *ptr) { - MemoryCounters *counters = (MemoryCounters *)ptr; - fclose(counters->file); - free(counters->keys); - free(ptr); +void clean_memory_counters(void *ptr) +{ + MemoryCounters *counters = (MemoryCounters *)ptr; + fclose(counters->file); + free(counters->keys); + free(ptr); } -void *show_all_memory_counters(void *none1, size_t none2) { - for (unsigned int i = 0; i < NB_COUNTERS; i++) { - printf("%s\n", memory_counters[i]); - } +void *show_all_memory_counters(void *none1, size_t none2) +{ + for (unsigned int i = 0; i < NB_COUNTERS; i++) { + printf("%s\n", memory_counters[i]); + } - UNUSED(none1); - UNUSED(none2); - exit(EXIT_SUCCESS); - return NULL; /* not reached */ + UNUSED(none1); + UNUSED(none2); + exit(EXIT_SUCCESS); + return NULL; /* not reached */ } -- GitLab From 1dc25900b97a9bb08a29929a00674d6cad485fc4 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 24 Apr 2023 10:35:19 +0200 Subject: [PATCH 229/229] configure: no capability detection with `-u` flag --- configure.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/configure.sh b/configure.sh index 1246b0c..4d0eb76 100755 --- a/configure.sh +++ b/configure.sh @@ -130,8 +130,8 @@ detect_caps() { if [ -e /usr/local/cuda/lib64 ] && [ -e /usr/local/cuda/include ]; then hdr_whitelist="${hdr_whitelist}|nvidia_gpu" - NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml" - NVML_IFLAGS="-I/usr/local/cuda/include" + NVML_LDFLAGS='-L/usr/local/cuda/lib64 -lnvidia-ml' + NVML_IFLAGS='-I/usr/local/cuda/include' fi vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) @@ -160,9 +160,14 @@ case $1 in NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml" NVML_IFLAGS="-I/usr/local/cuda/include" ;; +--unique | -u) + unique=1 + ;; esac -[ "$all" ] || detect_caps +if ! [ "$all" ] && ! [ "$unique" ]; then + detect_caps +fi [ "$all" ] || while [ "$1" ]; do -- GitLab