]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/resource.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / resource.cc
1 /* resource.cc: getrusage () and friends.
2
3 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010,
4 2011, 2012 Red Hat, Inc.
5
6 Written by Steve Chamberlain (sac@cygnus.com), Doug Evans (dje@cygnus.com),
7 Geoffrey Noer (noer@cygnus.com) of Cygnus Support.
8 Rewritten by Sergey S. Okhapkin (sos@prospect.com.ru)
9
10 This file is part of Cygwin.
11
12 This software is a copyrighted work licensed under the terms of the
13 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 details. */
15
16 #include "winsup.h"
17 #include <unistd.h>
18 #include <sys/param.h>
19 #include "pinfo.h"
20 #include "psapi.h"
21 #include "cygtls.h"
22 #include "path.h"
23 #include "fhandler.h"
24 #include "pinfo.h"
25 #include "dtable.h"
26 #include "cygheap.h"
27 #include "ntdll.h"
28
29 /* add timeval values */
30 static void
31 add_timeval (struct timeval *tv1, struct timeval *tv2)
32 {
33 tv1->tv_sec += tv2->tv_sec;
34 tv1->tv_usec += tv2->tv_usec;
35 if (tv1->tv_usec >= 1000000)
36 {
37 tv1->tv_usec -= 1000000;
38 tv1->tv_sec++;
39 }
40 }
41
42 /* add rusage values of r2 to r1 */
43 void __stdcall
44 add_rusage (struct rusage *r1, struct rusage *r2)
45 {
46 add_timeval (&r1->ru_utime, &r2->ru_utime);
47 add_timeval (&r1->ru_stime, &r2->ru_stime);
48 r1->ru_maxrss += r2->ru_maxrss;
49 r1->ru_ixrss += r2->ru_ixrss;
50 r1->ru_idrss += r2->ru_idrss;
51 r1->ru_isrss += r2->ru_isrss;
52 r1->ru_minflt += r2->ru_minflt;
53 r1->ru_majflt += r2->ru_majflt;
54 r1->ru_nswap += r2->ru_nswap;
55 r1->ru_inblock += r2->ru_inblock;
56 r1->ru_oublock += r2->ru_oublock;
57 r1->ru_msgsnd += r2->ru_msgsnd;
58 r1->ru_msgrcv += r2->ru_msgrcv;
59 r1->ru_nsignals += r2->ru_nsignals;
60 r1->ru_nvcsw += r2->ru_nvcsw;
61 r1->ru_nivcsw += r2->ru_nivcsw;
62 }
63
64 /* FIXME: what about other fields? */
65 void __stdcall
66 fill_rusage (struct rusage *r, HANDLE h)
67 {
68 FILETIME creation_time = {0,0};
69 FILETIME exit_time = {0,0};
70 FILETIME kernel_time = {0,0};
71 FILETIME user_time = {0,0};
72
73 struct timeval tv;
74
75 memset (r, 0, sizeof (*r));
76 GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time);
77 totimeval (&tv, &kernel_time, 0, 0);
78 add_timeval (&r->ru_stime, &tv);
79 totimeval (&tv, &user_time, 0, 0);
80 add_timeval (&r->ru_utime, &tv);
81
82 VM_COUNTERS vmc;
83 NTSTATUS status = NtQueryInformationProcess (h, ProcessVmCounters, &vmc,
84 sizeof vmc, NULL);
85 if (NT_SUCCESS (status))
86 {
87 r->ru_maxrss += (long) (vmc.WorkingSetSize / 1024);
88 r->ru_majflt += vmc.PageFaultCount;
89 }
90 }
91
92 extern "C" int
93 getrusage (int intwho, struct rusage *rusage_in)
94 {
95 int res = 0;
96 struct rusage r;
97
98 if (intwho == RUSAGE_SELF)
99 {
100 memset (&r, 0, sizeof (r));
101 fill_rusage (&r, GetCurrentProcess ());
102 *rusage_in = r;
103 }
104 else if (intwho == RUSAGE_CHILDREN)
105 *rusage_in = myself->rusage_children;
106 else
107 {
108 set_errno (EINVAL);
109 res = -1;
110 }
111
112 syscall_printf ("%R = getrusage(%d, %p)", res, intwho, rusage_in);
113 return res;
114 }
115
116 extern "C" int
117 getrlimit (int resource, struct rlimit *rlp)
118 {
119 MEMORY_BASIC_INFORMATION m;
120
121 myfault efault;
122 if (efault.faulted (EFAULT))
123 return -1;
124
125 rlp->rlim_cur = RLIM_INFINITY;
126 rlp->rlim_max = RLIM_INFINITY;
127
128 switch (resource)
129 {
130 case RLIMIT_CPU:
131 case RLIMIT_FSIZE:
132 case RLIMIT_DATA:
133 case RLIMIT_AS:
134 break;
135 case RLIMIT_STACK:
136 if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
137 debug_printf ("couldn't get stack info, returning def.values. %E");
138 else
139 {
140 rlp->rlim_cur = (rlim_t) &m - (rlim_t) m.AllocationBase;
141 rlp->rlim_max = (rlim_t) m.BaseAddress + m.RegionSize
142 - (rlim_t) m.AllocationBase;
143 }
144 break;
145 case RLIMIT_NOFILE:
146 rlp->rlim_cur = getdtablesize ();
147 if (rlp->rlim_cur < OPEN_MAX)
148 rlp->rlim_cur = OPEN_MAX;
149 rlp->rlim_max = OPEN_MAX_MAX;
150 break;
151 case RLIMIT_CORE:
152 rlp->rlim_cur = cygheap->rlim_core;
153 break;
154 default:
155 set_errno (EINVAL);
156 return -1;
157 }
158 return 0;
159 }
160
161 extern "C" int
162 setrlimit (int resource, const struct rlimit *rlp)
163 {
164 myfault efault;
165 if (efault.faulted (EFAULT))
166 return -1;
167
168 struct rlimit oldlimits;
169
170 // Check if the request is to actually change the resource settings.
171 // If it does not result in a change, take no action and do not
172 // fail.
173 if (getrlimit (resource, &oldlimits) < 0)
174 return -1;
175
176 if (oldlimits.rlim_cur == rlp->rlim_cur &&
177 oldlimits.rlim_max == rlp->rlim_max)
178 // No change in resource requirements, succeed immediately
179 return 0;
180
181 switch (resource)
182 {
183 case RLIMIT_CORE:
184 cygheap->rlim_core = rlp->rlim_cur;
185 break;
186 case RLIMIT_NOFILE:
187 if (rlp->rlim_cur != RLIM_INFINITY)
188 return setdtablesize (rlp->rlim_cur);
189 break;
190 default:
191 set_errno (EINVAL);
192 return -1;
193 }
194 return 0;
195 }
This page took 0.043472 seconds and 5 git commands to generate.