blob: b5fac884176ebc5ee12bbd79f6b4514aaf438718 [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>
Willy Tarreau0108d902018-11-25 19:14:37 +010017#include <common/initcall.h>
Willy Tarreau609aad92018-11-22 08:31:09 +010018#include <types/activity.h>
Willy Tarreau75c62c22018-11-22 11:02:09 +010019#include <proto/channel.h>
20#include <proto/cli.h>
Willy Tarreau609aad92018-11-22 08:31:09 +010021#include <proto/freq_ctr.h>
Willy Tarreau75c62c22018-11-22 11:02:09 +010022#include <proto/stream_interface.h>
23
24
25/* bit field of profiling options. Beware, may be modified at runtime! */
26unsigned int profiling;
Willy Tarreau609aad92018-11-22 08:31:09 +010027
28/* One struct per thread containing all collected measurements */
29struct activity activity[MAX_THREADS] __attribute__((aligned(64))) = { };
30
31
32/* Updates the current thread's statistics about stolen CPU time. The unit for
33 * <stolen> is half-milliseconds.
34 */
35void report_stolen_time(uint64_t stolen)
36{
37 activity[tid].cpust_total += stolen;
38 update_freq_ctr(&activity[tid].cpust_1s, stolen);
39 update_freq_ctr_period(&activity[tid].cpust_15s, 15000, stolen);
40}
Willy Tarreau75c62c22018-11-22 11:02:09 +010041
42/* config parser for global "profiling.tasks", accepts "on" or "off" */
43static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *curpx,
44 struct proxy *defpx, const char *file, int line,
45 char **err)
46{
47 if (too_many_args(1, args, err, NULL))
48 return -1;
49
50 if (strcmp(args[1], "on") == 0)
51 profiling |= HA_PROF_TASKS;
52 else if (strcmp(args[1], "off") == 0)
53 profiling &= ~HA_PROF_TASKS;
54 else {
55 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
56 return -1;
57 }
58 return 0;
59}
60
61/* parse a "set profiling" command. It always returns 1. */
62static int cli_parse_set_profiling(char **args, char *payload, struct appctx *appctx, void *private)
63{
64 unsigned int bit = 0;
65
66 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
67 return 1;
68
69 if (strcmp(args[2], "tasks") == 0)
70 bit = HA_PROF_TASKS;
71 else {
72 appctx->ctx.cli.severity = LOG_ERR;
73 appctx->ctx.cli.msg = "Expects 'tasks'.\n";
74 appctx->st0 = CLI_ST_PRINT;
75 return 1;
76 }
77
78 if (strcmp(args[3], "on") == 0)
Olivier Houchard0823ca82019-03-08 18:48:58 +010079 _HA_ATOMIC_OR(&profiling, bit);
Willy Tarreau75c62c22018-11-22 11:02:09 +010080 else if (strcmp(args[3], "off") == 0)
Olivier Houchard0823ca82019-03-08 18:48:58 +010081 _HA_ATOMIC_AND(&profiling, ~bit);
Willy Tarreau75c62c22018-11-22 11:02:09 +010082 else {
83 appctx->ctx.cli.severity = LOG_ERR;
84 appctx->ctx.cli.msg = "Expects either 'on' or 'off'.\n";
85 appctx->st0 = CLI_ST_PRINT;
86 return 1;
87 }
88 return 1;
89}
90
91/* This function dumps all profiling settings. It returns 0 if the output
92 * buffer is full and it needs to be called again, otherwise non-zero.
93 */
94static int cli_io_handler_show_profiling(struct appctx *appctx)
95{
96 struct stream_interface *si = appctx->owner;
97
98 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
99 return 1;
100
101 chunk_reset(&trash);
102
103 chunk_printf(&trash, "Per-task CPU profiling : %s # set profiling tasks {on|off}\n",
104 (profiling & HA_PROF_TASKS) ? "on" : "off");
105
106 if (ci_putchk(si_ic(si), &trash) == -1) {
107 /* failed, try again */
108 si_rx_room_blk(si);
109 return 0;
110 }
111 return 1;
112}
113
114/* config keyword parsers */
115static struct cfg_kw_list cfg_kws = {ILH, {
116 { CFG_GLOBAL, "profiling.tasks", cfg_parse_prof_tasks },
117 { 0, NULL, NULL }
118}};
119
Willy Tarreau0108d902018-11-25 19:14:37 +0100120INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
121
Willy Tarreau75c62c22018-11-22 11:02:09 +0100122/* register cli keywords */
123static struct cli_kw_list cli_kws = {{ },{
124 { { "show", "profiling", NULL }, "show profiling : show CPU profiling options", NULL, cli_io_handler_show_profiling, NULL },
125 { { "set", "profiling", NULL }, "set profiling : enable/disable CPU profiling", cli_parse_set_profiling, NULL },
126 {{},}
127}};
128
Willy Tarreau0108d902018-11-25 19:14:37 +0100129INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);