1: /*
2: * $Id: heavy-thread.c,v 1.1.1.2 2016/11/02 10:09:12 misho Exp $
3: *
4: * This file is part of Quagga.
5: *
6: * Quagga is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2, or (at your option) any
9: * later version.
10: *
11: * Quagga is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with Quagga; see the file COPYING. If not, write to the Free
18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19: * 02111-1307, USA.
20: */
21:
22: /* This programme shows the effects of 'heavy' long-running functions
23: * on the cooperative threading model, as demonstrated by heavy.c, and how
24: * they can be mitigated using a background thread.
25: *
26: * Run it with a config file containing 'password whatever', telnet to it
27: * (it defaults to port 4000) and enter the 'clear foo string' command.
28: * then type whatever and observe that, unlike heavy.c, the vty interface
29: * remains responsive.
30: */
31: #include <zebra.h>
32: #include <math.h>
33:
34: #include "thread.h"
35: #include "vty.h"
36: #include "command.h"
37: #include "memory.h"
38: #include "log.h"
39:
40: #include "tests.h"
41:
42: extern struct thread_master *master;
43:
44: enum
45: {
46: ITERS_FIRST = 0,
47: ITERS_ERR = 100,
48: ITERS_LATER = 400,
49: ITERS_PRINT = 10,
50: ITERS_MAX = 1000,
51: };
52:
53: struct work_state {
54: struct vty *vty;
55: char *str;
56: int i;
57: };
58:
59: static void
60: slow_func (struct vty *vty, const char *str, const int i)
61: {
62: double x = 1;
63: int j;
64:
65: for (j = 0; j < 300; j++)
66: x += sin(x)*j;
67:
68: if ((i % ITERS_LATER) == 0)
69: printf ("%s: %d, temporary error, save this somehow and do it later..\n",
70: __func__, i);
71:
72: if ((i % ITERS_ERR) == 0)
73: printf ("%s: hard error\n", __func__);
74:
75: if ((i % ITERS_PRINT) == 0)
76: printf ("%s did %d, x = %g\n", str, i, x);
77: }
78:
79: static int
80: clear_something (struct thread *thread)
81: {
82: struct work_state *ws = THREAD_ARG(thread);
83:
84: /* this could be like iterating through 150k of route_table
85: * or worse, iterating through a list of peers, to bgp_stop them with
86: * each having 150k route tables to process...
87: */
88: while (ws->i < ITERS_MAX)
89: {
90: slow_func(ws->vty, ws->str, ws->i);
91: ws->i++;
92: if (thread_should_yield(thread))
93: {
94: thread_add_background(master, clear_something, ws, 0);
95: return 0;
96: }
97: }
98:
99: /* All done! */
100: XFREE (MTYPE_TMP, ws->str);
101: XFREE (MTYPE_TMP, ws);
102: return 0;
103: }
104:
105: DEFUN (clear_foo,
106: clear_foo_cmd,
107: "clear foo .LINE",
108: "clear command\n"
109: "arbitrary string\n")
110: {
111: char *str;
112: struct work_state *ws;
113:
114: if (!argc)
115: {
116: vty_out (vty, "%% string argument required%s", VTY_NEWLINE);
117: return CMD_WARNING;
118: }
119:
120: str = argv_concat (argv, argc, 0);
121:
122: if ((ws = XMALLOC(MTYPE_TMP, sizeof(*ws))) == NULL)
123: {
124: zlog_err ("%s: unable to allocate work_state", __func__);
125: return CMD_WARNING;
126: }
127:
128: if (!(ws->str = XSTRDUP (MTYPE_TMP, str)))
129: {
130: zlog_err ("%s: unable to xstrdup", __func__);
131: XFREE (MTYPE_TMP, ws);
132: return CMD_WARNING;
133: }
134:
135: ws->vty = vty;
136: ws->i = ITERS_FIRST;
137:
138: thread_add_background(master, clear_something, ws, 0);
139:
140: return CMD_SUCCESS;
141: }
142:
143: void
144: test_init()
145: {
146: install_element (VIEW_NODE, &clear_foo_cmd);
147: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>