summaryrefslogtreecommitdiff
path: root/hurd/activity.h
blob: d26a2330f7770969840a92c14f51ac7414e02ca8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* activity.h - Activity definitions.
   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
   Written by Neal H. Walfield <neal@gnu.org>.

   This file is part of the GNU Hurd.

   GNU Hurd is free software: you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as
   published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   GNU Hurd 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with GNU Hurd.  If not, see
   <http://www.gnu.org/licenses/>.  */

#ifndef _HURD_ACTIVITY_H
#define _HURD_ACTIVITY_H 1

#include <hurd/types.h>
#include <hurd/startup.h>
#include <hurd/addr.h>

enum
  {
    RM_activity_policy = 700,
    RM_activity_stats,
  };

struct activity_memory_policy
{
  uint16_t weight;
  uint16_t priority;
};

#define ACTIVITY_MEMORY_POLICY(__amp_weight, __amp_priority) \
  (struct activity_memory_policy) { __amp_weight, __amp_priority }
#define ACTIVITY_MEMORY_POLICY_VOID ACTIVITY_MEMORY_POLICY(0, 0)

struct activity_policy
{
  /* This policy is typically set by the parent to reflect how
     available memory should be distributed among its immediate
     children.  It may only be set via an activity control
     capability.  */
  struct activity_memory_policy sibling_rel;

  /* This policy is typically set by the activity user and controls
     how the memory allocated *directly* to this activity is managed
     relative to the memory allocated to this activity's children.
     That is, if the activity has been choosen as a victim, this
     provides a policy to determine whether the memory allocated
     directly to the activity or that to a child activity should be
     evicted.  */
  struct activity_memory_policy child_rel;

  /* Number of folios.  Zero means no limit.  (This does not mean that
     there is no limit, just that this activity does not impose a
     limit.  The parent activity, for instance, may impose a limit.)
     May only be set via an activity control capability.  */
  uint32_t folios;
};

/* Activity statistics.  These are approximate and in some cases
   represent averages.  */
#define ACTIVITY_STATS_PERIODS 2
struct activity_stats
{
  /* The period during which this statistic was generated.  */
  uint32_t period;

  /* The maximum number of frames this activity could currently
     allocate assuming other allocations do not otherwise change.
     This implies stealing from others.  */
  uint32_t available;
  uint32_t available_local;
  
  /* The maximum amount of memory that the user of this activity ought
     to allocate in the next few seconds.  If negative, the amount of
     memory the activity ought to consider freeing.  */
  int32_t damping_factor;

  /* If pressure is non-zero, then this activity is causing PRESSURE.

     PRESSURE is calculated as follows: if 

       1) this activity is within its entitlement
       2) its working set is significantly smaller than its allocation
          (as determined by the size of inactive relative to active), and
       3) other activities are being held back (i.e., paging) due to this
          activity,

     then this represents the amount of memory it would be nice to see
     this activity free.  This activity will not be penalized by the
     system if it does not yield memory.  However, if the activity has
     memory which is yielding a low return, it would be friendly of it
     to return it.  */
  uint32_t pressure;

  /* The number of clean and dirty frames that are accounted to this
     activity.  (Does not include frames scheduled for eviction.)  The
     total number of frames accounted to this activity is thus CLEAN +
     DIRTY.  */
  uint32_t clean;
  uint32_t dirty;
  /* Number of frames pending eviction.  */
  uint32_t pending_eviction;


  /* Based on recency information, the number of active frames
     accounted to this activity and its children.  The number of
     inactive frames is approximately CLEAN + DIRTY - ACTIVE.  */
  uint32_t active;
  /* Likewise, but excluding its children.  */
  uint32_t active_local;

  /* Number of frames that were active in the last period that become
     inactive in this period.  */
  uint32_t became_active;
  /* Number of frames that were inactive in the last period that
     become active in this period.  */
  uint32_t became_inactive;


  /* Number of frames that were not accounted to this activity in the
     last period and are now accounted to it.  */
  uint32_t claimed;
  /* Number of frames that were accounted to this activity in the last
     period and are no longer accounted to it.  */
  uint32_t disowned;

  /* The number of frames that this activity referenced but which are
     accounted to some other activity.  */
  uint32_t freeloading;
  /* The sum of the references by other processes to the frames that
     are accounted to this activity.  (A single frame may account
     for multiple references.)  */
  uint32_t freeloaded;


  /* Number of frames that were accounted to this activity and
     scheduled for eviction.  */
  uint32_t evicted;
  /* Number of frames that were accounted to this activity (not its
     children), had the discarded bit set, and were discarded.  */
  uint32_t discarded;
  /* Number of frames paged-in on behalf of this activity.  This does
     not include pages marked empty that do not require disk
     activity.  */
  uint32_t pagedin;
  /* Number of frames that were referenced before being completely
     freed.  (If evicted is significant and saved approximates
     evicted, then the process is trashing.)  */
  uint32_t saved;
};
struct activity_stats_buffer
{
  struct activity_stats stats[ACTIVITY_STATS_PERIODS];
};

#define ACTIVITY_POLICY(__ap_sibling_rel, __ap_child_rel, __ap_storage) \
  (struct activity_policy) { __ap_sibling_rel, __ap_child_rel, __ap_storage }
#define ACTIVITY_POLICY_VOID			\
  ACTIVITY_POLICY(ACTIVITY_MEMORY_POLICY_VOID,	\
		  ACTIVITY_MEMORY_POLICY_VOID,	\
		  0)

#define RPC_STUB_PREFIX rm
#define RPC_ID_PREFIX RM
#undef RPC_TARGET_NEED_ARG
#define RPC_TARGET \
  ({ \
    extern struct hurd_startup_data *__hurd_startup_data; \
    __hurd_startup_data->rm; \
  })

#include <hurd/rpc.h>

enum
{
  ACTIVITY_POLICY_CHILD_REL_PRIORITY_SET = 1 << 0,
  ACTIVITY_POLICY_CHILD_REL_WEIGHT_SET = 1 << 1,
  ACTIVITY_POLICY_SIBLING_REL_PRIORITY_SET = 1 << 2,
  ACTIVITY_POLICY_SIBLING_REL_WEIGHT_SET = 1 << 3,
  ACTIVITY_POLICY_STORAGE_SET = 1 << 4,

  ACTIVITY_POLICY_CHILD_REL_SET = (ACTIVITY_POLICY_CHILD_REL_PRIORITY_SET
				   | ACTIVITY_POLICY_CHILD_REL_WEIGHT_SET),

  ACTIVITY_POLICY_SIBLING_REL_SET = (ACTIVITY_POLICY_SIBLING_REL_PRIORITY_SET
				     | ACTIVITY_POLICY_SIBLING_REL_WEIGHT_SET),
};

/* Get ACTIVITY's policy and set according to FLAGS and IN.  */
RPC (activity_policy, 3, 1, addr_t, activity,
     uintptr_t, flags, struct activity_policy, in,
     /* Out: */
     struct activity_policy, out);

/* Return statistics about activity ACTIVITY.  Waits until the current
   period is older than UNTIL_PERIOD.  (This can be used to register a
   callback that is sent when the statistics are next available.  For
   example, call with until_period is 0 to get the current statistics
   and then examine the period field.  Use this as the base for the
   next call.)  COUNT is the number of returned samples.  Samples are
   ordered by recency with the youngest towards the start of the
   buffer.  */
RPC (activity_stats, 2, 2, addr_t, activity, uintptr_t, until_period,
     /* Out: */
     struct activity_stats_buffer, stats, int, count)

#undef RPC_STUB_PREFIX
#undef RPC_ID_PREFIX
#undef RPC_TARGET

#endif