blob: 9460a8a7e95a9071ea8c994c976154a24a7935a3 [file] [log] [blame]
Willy Tarreau609aad92018-11-22 08:31:09 +01001/*
2 * activity measurement functions.
3 *
4 * Copyright 2000-2018 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreau75c62c22018-11-22 11:02:09 +010013#include <common/cfgparse.h>
Willy Tarreau609aad92018-11-22 08:31:09 +010014#include <common/config.h>
15#include <common/standard.h>
16#include <common/hathreads.h>
17#include <types/activity.h>
Willy Tarreau75c62c22018-11-22 11:02:09 +010018#include <proto/channel.h>
19#include <proto/cli.h>
Willy Tarreau609aad92018-11-22 08:31:09 +010020#include <proto/freq_ctr.h>
Willy Tarreau75c62c22018-11-22 11:02:09 +010021#include <proto/stream_interface.h>
22
23
24/* bit field of profiling options. Beware, may be modified at runtime! */
25unsigned int profiling;
Willy Tarreau609aad92018-11-22 08:31:09 +010026
27/* One struct per thread containing all collected measurements */
28struct activity activity[MAX_THREADS] __attribute__((aligned(64))) = { };
29
30
31/* Updates the current thread's statistics about stolen CPU time. The unit for
32 * <stolen> is half-milliseconds.
33 */
34void report_stolen_time(uint64_t stolen)
35{
36 activity[tid].cpust_total += stolen;
37 update_freq_ctr(&activity[tid].cpust_1s, stolen);
38 update_freq_ctr_period(&activity[tid].cpust_15s, 15000, stolen);
39}
Willy Tarreau75c62c22018-11-22 11:02:09 +010040
41/* config parser for global "profiling.tasks", accepts "on" or "off" */
42static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *curpx,
43 struct proxy *defpx, const char *file, int line,
44 char **err)
45{
46 if (too_many_args(1, args, err, NULL))
47 return -1;
48
49 if (strcmp(args[1], "on") == 0)
50 profiling |= HA_PROF_TASKS;
51 else if (strcmp(args[1], "off") == 0)
52 profiling &= ~HA_PROF_TASKS;
53 else {
54 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
55 return -1;
56 }
57 return 0;
58}
59
60/* parse a "set profiling" command. It always returns 1. */
61static int cli_parse_set_profiling(char **args, char *payload, struct appctx *appctx, void *private)
62{
63 unsigned int bit = 0;
64
65 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
66 return 1;
67
68 if (strcmp(args[2], "tasks") == 0)
69 bit = HA_PROF_TASKS;
70 else {
71 appctx->ctx.cli.severity = LOG_ERR;
72 appctx->ctx.cli.msg = "Expects 'tasks'.\n";
73 appctx->st0 = CLI_ST_PRINT;
74 return 1;
75 }
76
77 if (strcmp(args[3], "on") == 0)
78 HA_ATOMIC_OR(&profiling, bit);
79 else if (strcmp(args[3], "off") == 0)
80 HA_ATOMIC_AND(&profiling, ~bit);
81 else {
82 appctx->ctx.cli.severity = LOG_ERR;
83 appctx->ctx.cli.msg = "Expects either 'on' or 'off'.\n";
84 appctx->st0 = CLI_ST_PRINT;
85 return 1;
86 }
87 return 1;
88}
89
90/* This function dumps all profiling settings. It returns 0 if the output
91 * buffer is full and it needs to be called again, otherwise non-zero.
92 */
93static int cli_io_handler_show_profiling(struct appctx *appctx)
94{
95 struct stream_interface *si = appctx->owner;
96
97 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
98 return 1;
99
100 chunk_reset(&trash);
101
102 chunk_printf(&trash, "Per-task CPU profiling : %s # set profiling tasks {on|off}\n",
103 (profiling & HA_PROF_TASKS) ? "on" : "off");
104
105 if (ci_putchk(si_ic(si), &trash) == -1) {
106 /* failed, try again */
107 si_rx_room_blk(si);
108 return 0;
109 }
110 return 1;
111}
112
113/* config keyword parsers */
114static struct cfg_kw_list cfg_kws = {ILH, {
115 { CFG_GLOBAL, "profiling.tasks", cfg_parse_prof_tasks },
116 { 0, NULL, NULL }
117}};
118
119/* register cli keywords */
120static struct cli_kw_list cli_kws = {{ },{
121 { { "show", "profiling", NULL }, "show profiling : show CPU profiling options", NULL, cli_io_handler_show_profiling, NULL },
122 { { "set", "profiling", NULL }, "set profiling : enable/disable CPU profiling", cli_parse_set_profiling, NULL },
123 {{},}
124}};
125
126__attribute__((constructor))
127static void __activity_init(void)
128{
129 cfg_register_keywords(&cfg_kws);
130 cli_register_kw(&cli_kws);
131}