001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <hwcore/irq.h>
020 #include <sos/kmalloc.h>
021 #include <sos/assert.h>
022 #include <sos/calcload.h>
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050 #define SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR 10
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072 #define NB_SECS 900
073
074
075
076 struct load_entry
077 {
078 sos_ui32_t nb_ticks;
079
080 sos_ui32_t nb_user_running;
081 sos_ui32_t nb_kernel_running;
082
083 sos_ui32_t nb_user_ready;
084 sos_ui32_t nb_kernel_ready;
085 };
086
087 struct load_entry current_load_entry;
088
089
090
091 struct recorded_loads
092 {
093 sos_ui32_t most_recent;
094 sos_ui32_t max_entries;
095
096 struct load_entry *load_entries;
097 };
098
099 #define LOAD_GET_ENTRY(loads,age) \
100 (&((loads).load_entries[( (loads).max_entries + (loads).most_recent - (age))\
101 % ((loads).max_entries)]))
102
103
104 struct sliding_window
105 {
106 sos_ui32_t max_entries;
107 sos_ui32_t nb_entries;
108
109 sos_ui32_t sigma_nb_ticks;
110 sos_ui32_t sigma_nb_user_running;
111 sos_ui32_t sigma_nb_kernel_running;
112 sos_ui32_t sigma_nb_user_ready;
113 sos_ui32_t sigma_nb_kernel_ready;
114 };
115
116
117
118 static struct recorded_loads recorded_loads;
119
120
121 static struct sliding_window load_1mn, load_5mn, load_15mn;
122
123
124 static struct sos_timeout_action calcload_timeout;
125 static void calcload_routine(struct sos_timeout_action *a);
126
127
128 static void _reinit_load_subsystem()
129 {
130 memset(& recorded_loads, 0x0, sizeof(recorded_loads));
131 memset(& current_load_entry, 0x0, sizeof(struct load_entry));
132 memset(& load_1mn, 0x0, sizeof(load_1mn));
133 memset(& load_5mn, 0x0, sizeof(load_5mn));
134 memset(& load_15mn, 0x0, sizeof(load_15mn));
135 }
136
137
138 sos_ret_t sos_load_subsystem_setup(void)
139 {
140 struct sos_time period;
141 _reinit_load_subsystem();
142
143 if (recorded_loads.load_entries)
144 sos_kfree((sos_vaddr_t) recorded_loads.load_entries);
145 _reinit_load_subsystem();
146
147
148
149 recorded_loads.max_entries = NB_SECS;
150 recorded_loads.load_entries
151 = (struct load_entry*) sos_kmalloc(NB_SECS * sizeof(struct load_entry),
152 0);
153 if (! recorded_loads.load_entries)
154 {
155 return -SOS_ENOMEM;
156 }
157
158
159 load_1mn.max_entries = 60;
160 load_5mn.max_entries = 300;
161 load_15mn.max_entries = 900;
162
163
164 sos_time_init_action(& calcload_timeout);
165 period.sec = 1; period.nanosec = 0;
166 return sos_time_register_action_relative(& calcload_timeout,
167 & period,
168 calcload_routine,
169 NULL);
170 }
171
172
173
174 static void update_sliding_window(struct sliding_window *w)
175 {
176
177
178
179
180
181 w->sigma_nb_ticks += current_load_entry.nb_ticks;
182 w->sigma_nb_user_running += current_load_entry.nb_user_running;
183 w->sigma_nb_kernel_running += current_load_entry.nb_kernel_running;
184 w->sigma_nb_user_ready += current_load_entry.nb_user_ready;
185 w->sigma_nb_kernel_ready += current_load_entry.nb_kernel_ready;
186
187
188
189 if (w->nb_entries < w->max_entries)
190 {
191 w->nb_entries ++;
192 }
193 else
194 {
195 struct load_entry * oldest_entry;
196 oldest_entry = LOAD_GET_ENTRY(recorded_loads, w->nb_entries - 1);
197 w->sigma_nb_ticks -= oldest_entry->nb_ticks;
198 w->sigma_nb_user_running -= oldest_entry->nb_user_running;
199 w->sigma_nb_kernel_running -= oldest_entry->nb_kernel_running;
200 w->sigma_nb_user_ready -= oldest_entry->nb_user_ready;
201 w->sigma_nb_kernel_ready -= oldest_entry->nb_kernel_ready;
202 }
203 }
204
205
206
207 static void calcload_routine(struct sos_timeout_action *a)
208 {
209 struct load_entry * new_head;
210 struct sos_time delay;
211
212 if (! recorded_loads.load_entries)
213 return;
214
215
216 update_sliding_window(& load_1mn);
217 update_sliding_window(& load_5mn);
218 update_sliding_window(& load_15mn);
219
220
221 recorded_loads.most_recent
222 = (recorded_loads.most_recent + 1) % recorded_loads.max_entries;
223
224
225 new_head = & recorded_loads.load_entries[recorded_loads.most_recent];
226 memcpy(new_head, & current_load_entry, sizeof(current_load_entry));
227
228
229 memset(& current_load_entry, 0x0, sizeof(current_load_entry));
230
231
232 delay.sec = 1;
233 delay.nanosec = 0;
234 sos_time_register_action_relative(a, & delay, calcload_routine, NULL);
235 }
236
237
238 sos_ret_t sos_load_do_timer_tick(sos_bool_t cur_is_user,
239 sos_ui32_t nb_user_ready,
240 sos_ui32_t nb_kernel_ready)
241 {
242 sos_ui32_t flags;
243
244 sos_disable_IRQs(flags);
245 current_load_entry.nb_ticks ++;
246 current_load_entry.nb_user_ready += nb_user_ready;
247 current_load_entry.nb_kernel_ready += nb_kernel_ready;
248 if (cur_is_user)
249 current_load_entry.nb_user_running ++;
250 else
251 current_load_entry.nb_kernel_running ++;
252 sos_restore_IRQs(flags);
253
254 return SOS_OK;
255 }
256
257
258 void sos_load_to_string(char dest[11], sos_ui32_t load_value)
259 {
260 sos_bool_t print0 = FALSE;
261 sos_ui32_t d;
262
263 #define PUTCH(c) ({ *dest = (c); dest ++; })
264
265 for (d = 1000000000UL ; d > 0 ; d /= 10)
266 {
267 sos_ui32_t digit = (load_value / d) % 10;
268
269 if (digit > 0)
270 {
271 PUTCH(digit + '0');
272 print0 = TRUE;
273 }
274 else if (print0)
275 PUTCH('0');
276
277 if (d == SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR)
278 {
279 if (! print0)
280 PUTCH('0');
281
282 PUTCH('.');
283 print0 = TRUE;
284 }
285 }
286 *dest = '\0';
287 }
288
289
290 void sos_load_get_uload(sos_ui32_t * _load_1mn,
291 sos_ui32_t * _load_5mn,
292 sos_ui32_t * _load_15mn)
293 {
294 sos_ui32_t flags;
295
296 if (load_1mn.sigma_nb_ticks < 1)
297 return;
298
299 sos_disable_IRQs(flags);
300 *_load_1mn = ( load_1mn.sigma_nb_user_ready
301 + load_1mn.sigma_nb_user_running)
302 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
303 / load_1mn.sigma_nb_ticks;
304 *_load_5mn = ( load_5mn.sigma_nb_user_ready
305 + load_5mn.sigma_nb_user_running)
306 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
307 / load_5mn.sigma_nb_ticks;
308 *_load_15mn = ( load_15mn.sigma_nb_user_ready
309 + load_15mn.sigma_nb_user_running)
310 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
311 / load_15mn.sigma_nb_ticks;
312 sos_restore_IRQs(flags);
313 }
314
315
316 void sos_load_get_sload(sos_ui32_t * _load_1mn,
317 sos_ui32_t * _load_5mn,
318 sos_ui32_t * _load_15mn)
319 {
320 sos_ui32_t flags;
321
322 if (load_1mn.sigma_nb_ticks < 1)
323 return;
324
325
326 SOS_ASSERT_FATAL(load_1mn.sigma_nb_kernel_ready
327 + load_1mn.sigma_nb_kernel_running
328 >= load_1mn.sigma_nb_ticks);
329
330
331 sos_disable_IRQs(flags);
332 *_load_1mn = ( load_1mn.sigma_nb_kernel_ready
333 + load_1mn.sigma_nb_kernel_running
334 - load_1mn.sigma_nb_ticks)
335 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
336 / load_1mn.sigma_nb_ticks;
337 *_load_5mn = ( load_5mn.sigma_nb_kernel_ready
338 + load_5mn.sigma_nb_kernel_running
339 - load_5mn.sigma_nb_ticks)
340 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
341 / load_5mn.sigma_nb_ticks;
342 *_load_15mn = ( load_15mn.sigma_nb_kernel_ready
343 + load_15mn.sigma_nb_kernel_running
344 - load_15mn.sigma_nb_ticks)
345 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
346 / load_15mn.sigma_nb_ticks;
347 sos_restore_IRQs(flags);
348 }
349
350
351 void sos_load_get_uratio(sos_ui32_t * _load_1mn,
352 sos_ui32_t * _load_5mn,
353 sos_ui32_t * _load_15mn)
354 {
355 sos_ui32_t flags;
356
357 if (load_1mn.sigma_nb_ticks < 1)
358 return;
359
360 sos_disable_IRQs(flags);
361 *_load_1mn = load_1mn.sigma_nb_user_running
362 * 100 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
363 / load_1mn.sigma_nb_ticks;
364 *_load_5mn = load_5mn.sigma_nb_user_running
365 * 100 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
366 / load_5mn.sigma_nb_ticks;
367 *_load_15mn = load_15mn.sigma_nb_user_running
368 * 100 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
369 / load_15mn.sigma_nb_ticks;
370 sos_restore_IRQs(flags);
371 }
372
373
374 void sos_load_get_sratio(sos_ui32_t * _load_1mn,
375 sos_ui32_t * _load_5mn,
376 sos_ui32_t * _load_15mn)
377 {
378 sos_ui32_t flags;
379
380 if (load_1mn.sigma_nb_ticks < 1)
381 return;
382
383
384
385 sos_disable_IRQs(flags);
386 *_load_1mn = load_1mn.sigma_nb_kernel_running
387 * 100 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
388 / load_1mn.sigma_nb_ticks;
389 *_load_5mn = load_5mn.sigma_nb_kernel_running
390 * 100 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
391 / load_5mn.sigma_nb_ticks;
392 *_load_15mn = load_15mn.sigma_nb_kernel_running
393 * 100 * SOS_LOAD_DISPLAY_MULTIPLICATION_FACTOR
394 / load_15mn.sigma_nb_ticks;
395 sos_restore_IRQs(flags);
396 }