4242
4343import static com .oracle .graal .python .runtime .exception .PythonErrorType .ValueError ;
4444
45- import java .lang .management .ManagementFactory ;
46- import java .lang .management .MemoryMXBean ;
47- import java .lang .management .MemoryUsage ;
48- import java .lang .management .ThreadMXBean ;
4945import java .util .List ;
5046
51- import org .graalvm .nativeimage .ImageInfo ;
52-
5347import com .oracle .graal .python .builtins .Builtin ;
5448import com .oracle .graal .python .builtins .CoreFunctions ;
5549import com .oracle .graal .python .builtins .Python3Core ;
5650import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
5751import com .oracle .graal .python .builtins .PythonBuiltins ;
58- import com .oracle .graal .python .builtins .objects .thread . PThread ;
52+ import com .oracle .graal .python .builtins .objects .exception . OSErrorEnum ;
5953import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
6054import com .oracle .graal .python .builtins .objects .tuple .StructSequence ;
6155import com .oracle .graal .python .nodes .ErrorMessages ;
56+ import com .oracle .graal .python .nodes .PConstructAndRaiseNode ;
6257import com .oracle .graal .python .nodes .PRaiseNode ;
6358import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
6459import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
60+ import com .oracle .graal .python .runtime .PosixConstants ;
61+ import com .oracle .graal .python .runtime .PosixSupport ;
62+ import com .oracle .graal .python .runtime .PosixSupportLibrary ;
63+ import com .oracle .graal .python .runtime .PosixSupportLibrary .PosixException ;
64+ import com .oracle .graal .python .runtime .PosixSupportLibrary .RusageResult ;
6565import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
66- import com .oracle .truffle .api .CompilerDirectives . TruffleBoundary ;
66+ import com .oracle .truffle .api .dsl . Bind ;
6767import com .oracle .truffle .api .dsl .Cached ;
68- import com .oracle .truffle .api .dsl .Fallback ;
6968import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
7069import com .oracle .truffle .api .dsl .ImportStatic ;
7170import com .oracle .truffle .api .dsl .NodeFactory ;
7271import com .oracle .truffle .api .dsl .Specialization ;
72+ import com .oracle .truffle .api .frame .VirtualFrame ;
73+ import com .oracle .truffle .api .library .CachedLibrary ;
74+ import com .oracle .truffle .api .nodes .Node ;
7375
7476@ CoreFunctions (defineModule = "resource" )
7577public final class ResourceModuleBuiltins extends PythonBuiltins {
7678
77- static int RUSAGE_CHILDREN = -1 ;
78- static int RUSAGE_SELF = 0 ;
79- static int RUSAGE_THREAD = 1 ;
80-
8179 static int RLIMIT_CPU = 0 ;
8280 static int RLIMIT_FSIZE = 1 ;
8381 static int RLIMIT_DATA = 2 ;
@@ -129,9 +127,13 @@ public void initialize(Python3Core core) {
129127
130128 addBuiltinConstant ("error" , PythonBuiltinClassType .OSError );
131129
132- addBuiltinConstant ("RUSAGE_CHILDREN" , RUSAGE_CHILDREN );
133- addBuiltinConstant ("RUSAGE_SELF" , RUSAGE_SELF );
134- addBuiltinConstant ("RUSAGE_THREAD" , RUSAGE_THREAD );
130+ if (PosixConstants .RUSAGE_CHILDREN .defined ) {
131+ addBuiltinConstant ("RUSAGE_CHILDREN" , PosixConstants .RUSAGE_CHILDREN .getValueIfDefined ());
132+ }
133+ addBuiltinConstant ("RUSAGE_SELF" , PosixConstants .RUSAGE_SELF .value );
134+ if (PosixConstants .RUSAGE_THREAD .defined ) {
135+ addBuiltinConstant ("RUSAGE_THREAD" , PosixConstants .RUSAGE_THREAD .getValueIfDefined ());
136+ }
135137
136138 addBuiltinConstant ("RLIMIT_CPU" , RLIMIT_CPU );
137139 addBuiltinConstant ("RLIMIT_FSIZE" , RLIMIT_FSIZE );
@@ -154,119 +156,29 @@ public void initialize(Python3Core core) {
154156 @ ImportStatic (ResourceModuleBuiltins .class )
155157 abstract static class GetRuUsageNode extends PythonBuiltinNode {
156158
157- @ Specialization (guards = {"who == RUSAGE_THREAD" })
158- @ TruffleBoundary
159- PTuple getruusageThread (@ SuppressWarnings ("unused" ) int who ) {
160- long id = PThread .getThreadId (Thread .currentThread ());
161- Runtime runtime = Runtime .getRuntime ();
162-
163- double ru_utime = 0 ; // time in user mode (float)
164- double ru_stime = 0 ; // time in system mode (float)
165- long ru_maxrss ; // maximum resident set size
166-
167- if (!ImageInfo .inImageCode ()) {
168- ThreadMXBean threadMXBean = ManagementFactory .getThreadMXBean ();
169- if (threadMXBean .isCurrentThreadCpuTimeSupported ()) {
170- ru_utime = threadMXBean .getThreadUserTime (id ) / 1000000000.0 ;
171- ru_stime = Math .max (0 , (threadMXBean .getThreadCpuTime (id ) - threadMXBean .getThreadUserTime (id ))) / 1000000000.0 ;
172- }
173-
174- if (threadMXBean instanceof com .sun .management .ThreadMXBean ) {
175- com .sun .management .ThreadMXBean thMxBean = (com .sun .management .ThreadMXBean ) threadMXBean ;
176- ru_maxrss = thMxBean .getThreadAllocatedBytes (id );
159+ @ Specialization
160+ static PTuple getruusage (VirtualFrame frame , int who ,
161+ @ Bind ("this" ) Node inliningTarget ,
162+ @ CachedLibrary (limit = "1" ) PosixSupportLibrary posixLib ,
163+ @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ,
164+ @ Cached PRaiseNode .Lazy raiseNode ) {
165+ PosixSupport posixSupport = PosixSupport .get (inliningTarget );
166+ RusageResult rusage ;
167+ try {
168+ rusage = posixLib .getrusage (posixSupport , who );
169+ } catch (PosixException e ) {
170+ if (e .getErrorCode () == OSErrorEnum .EINVAL .getNumber ()) {
171+ throw raiseNode .get (inliningTarget ).raise (ValueError , ErrorMessages .RUSAGE_INVALID_WHO );
177172 } else {
178- ru_maxrss = runtime . maxMemory ( );
173+ throw constructAndRaiseNode . get ( inliningTarget ). raiseOSErrorFromPosixException ( frame , e );
179174 }
180- } else {
181- ru_maxrss = runtime .maxMemory ();
182- }
183-
184- String osName = System .getProperty ("os.name" );
185- if (osName .contains ("Linux" )) {
186- // peak memory usage (kilobytes on Linux
187- ru_maxrss /= 1024 ;
188175 }
189176
190- long ru_ixrss = -1 ; // shared memory size
191- long ru_idrss = -1 ; // unshared memory size
192- long ru_isrss = -1 ; // unshared stack size
193- long ru_minflt = -1 ; // page faults not requiring I/O
194- long ru_majflt = -1 ; // page faults requiring I/O
195- long ru_nswap = -1 ; // number of swap outs
196- long ru_inblock = -1 ; // block input operations
197- long ru_oublock = -1 ; // block output operations
198- long ru_msgsnd = -1 ; // messages sent
199- long ru_msgrcv = -1 ; // messages received
200- long ru_nsignals = -1 ; // signals received
201- long ru_nvcsw = -1 ; // voluntary context switches
202- long ru_nivcsw = -1 ; // nvoluntary context switches
203- return PythonObjectFactory .getUncached ().createStructSeq (STRUCT_RUSAGE_DESC , ru_utime , ru_stime , ru_maxrss , ru_ixrss , ru_idrss , ru_isrss ,
204- ru_minflt , ru_majflt , ru_nswap , ru_inblock , ru_oublock , ru_msgsnd , ru_msgrcv , ru_nsignals ,
205- ru_nvcsw , ru_nivcsw );
206- }
207-
208- @ Specialization (guards = {"who == RUSAGE_SELF" })
209- @ TruffleBoundary
210- PTuple getruusageSelf (@ SuppressWarnings ("unused" ) int who ) {
211- Runtime runtime = Runtime .getRuntime ();
212-
213- double ru_utime = 0 ; // time in user mode (float)
214- double ru_stime = 0 ; // time in system mode (float)
215- long ru_maxrss ;
216-
217- if (!ImageInfo .inImageCode ()) {
218- ThreadMXBean threadMXBean = ManagementFactory .getThreadMXBean ();
219- if (threadMXBean .isThreadCpuTimeSupported ()) {
220- for (long thId : threadMXBean .getAllThreadIds ()) {
221- long tu = threadMXBean .getThreadUserTime (thId );
222- long tc = threadMXBean .getThreadCpuTime (thId );
223-
224- if (tu != -1 ) {
225- ru_utime += tu / 1000000000.0 ;
226- }
227-
228- if (tu != -1 && tc != -1 ) {
229- ru_stime += Math .max (0 , tc - tu ) / 1000000000.0 ;
230- }
231- }
232- }
233-
234- MemoryMXBean memoryMXBean = ManagementFactory .getMemoryMXBean ();
235- MemoryUsage heapMemoryUsage = memoryMXBean .getHeapMemoryUsage ();
236- MemoryUsage nonHeapMemoryUsage = memoryMXBean .getNonHeapMemoryUsage ();
237- ru_maxrss = heapMemoryUsage .getCommitted () + nonHeapMemoryUsage .getCommitted ();
238- } else {
239- ru_maxrss = runtime .maxMemory ();
240- }
241-
242- String osName = System .getProperty ("os.name" );
243- if (osName .contains ("Linux" )) {
244- // peak memory usage (kilobytes on Linux
245- ru_maxrss /= 1024 ;
246- }
247-
248- long ru_ixrss = -1 ; // shared memory size
249- long ru_idrss = -1 ; // unshared memory size
250- long ru_isrss = -1 ; // unshared stack size
251- long ru_minflt = -1 ; // page faults not requiring I/O
252- long ru_majflt = -1 ; // page faults requiring I/O
253- long ru_nswap = -1 ; // number of swap outs
254- long ru_inblock = -1 ; // block input operations
255- long ru_oublock = -1 ; // block output operations
256- long ru_msgsnd = -1 ; // messages sent
257- long ru_msgrcv = -1 ; // messages received
258- long ru_nsignals = -1 ; // signals received
259- long ru_nvcsw = -1 ; // voluntary context switches
260- long ru_nivcsw = -1 ; // nvoluntary context switches
261- return PythonObjectFactory .getUncached ().createStructSeq (STRUCT_RUSAGE_DESC , ru_utime , ru_stime , ru_maxrss , ru_ixrss , ru_idrss , ru_isrss ,
262- ru_minflt , ru_majflt , ru_nswap , ru_inblock , ru_oublock , ru_msgsnd , ru_msgrcv , ru_nsignals ,
263- ru_nvcsw , ru_nivcsw );
264- }
265-
266- @ Fallback
267- static PTuple getruusage (@ SuppressWarnings ("unused" ) Object who ,
268- @ Cached PRaiseNode raiseNode ) {
269- throw raiseNode .raise (ValueError , ErrorMessages .RUSAGE_NOT_YET_IMPLEMENED );
177+ return PythonObjectFactory .getUncached ().createStructSeq (STRUCT_RUSAGE_DESC ,
178+ rusage .ru_utime (), rusage .ru_stime (),
179+ rusage .ru_maxrss (), rusage .ru_ixrss (), rusage .ru_idrss (), rusage .ru_isrss (),
180+ rusage .ru_minflt (), rusage .ru_majflt (), rusage .ru_nswap (), rusage .ru_inblock (), rusage .ru_oublock (),
181+ rusage .ru_msgsnd (), rusage .ru_msgrcv (), rusage .ru_nsignals (), rusage .ru_nvcsw (), rusage .ru_nivcsw ());
270182 }
271183 }
272184
0 commit comments