1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0.  If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 #include <stdlib.h>
15 #include <unistd.h>
16 
17 #include <isc/managers.h>
18 #include <isc/mem.h>
19 #include <isc/print.h>
20 #include <isc/task.h>
21 #include <isc/time.h>
22 #include <isc/timer.h>
23 #include <isc/util.h>
24 
25 isc_mem_t *mctx = NULL;
26 
27 static void
my_callback(isc_task_t * task,isc_event_t * event)28 my_callback(isc_task_t *task, isc_event_t *event) {
29 	int i, j;
30 	char *name = event->ev_arg;
31 
32 	j = 0;
33 	for (i = 0; i < 1000000; i++) {
34 		j += 100;
35 	}
36 	printf("task %s (%p): %d\n", name, task, j);
37 	isc_event_free(&event);
38 }
39 
40 static void
my_shutdown(isc_task_t * task,isc_event_t * event)41 my_shutdown(isc_task_t *task, isc_event_t *event) {
42 	char *name = event->ev_arg;
43 
44 	printf("shutdown %s (%p)\n", name, task);
45 	isc_event_free(&event);
46 }
47 
48 static void
my_tick(isc_task_t * task,isc_event_t * event)49 my_tick(isc_task_t *task, isc_event_t *event) {
50 	char *name = event->ev_arg;
51 
52 	printf("task %p tick %s\n", task, name);
53 	isc_event_free(&event);
54 }
55 
56 static char one[] = "1";
57 static char two[] = "2";
58 static char three[] = "3";
59 static char four[] = "4";
60 static char foo[] = "foo";
61 static char bar[] = "bar";
62 
63 int
main(int argc,char * argv[])64 main(int argc, char *argv[]) {
65 	isc_nm_t *netmgr = NULL;
66 	isc_taskmgr_t *taskmgr = NULL;
67 	isc_task_t *t1 = NULL, *t2 = NULL;
68 	isc_task_t *t3 = NULL, *t4 = NULL;
69 	isc_event_t *event;
70 	unsigned int workers;
71 	isc_timermgr_t *timgr;
72 	isc_timer_t *ti1, *ti2;
73 	struct isc_interval interval;
74 
75 	if (argc > 1) {
76 		workers = atoi(argv[1]);
77 		if (workers < 1) {
78 			workers = 1;
79 		}
80 		if (workers > 8192) {
81 			workers = 8192;
82 		}
83 	} else {
84 		workers = 2;
85 	}
86 	printf("%u workers\n", workers);
87 
88 	isc_mem_create(&mctx);
89 
90 	RUNTIME_CHECK(isc_managers_create(mctx, workers, 0, &netmgr,
91 					  &taskmgr) == ISC_R_SUCCESS);
92 
93 	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &t1) == ISC_R_SUCCESS);
94 	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &t2) == ISC_R_SUCCESS);
95 	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &t3) == ISC_R_SUCCESS);
96 	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &t4) == ISC_R_SUCCESS);
97 
98 	RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, one) ==
99 		      ISC_R_SUCCESS);
100 	RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, two) ==
101 		      ISC_R_SUCCESS);
102 	RUNTIME_CHECK(isc_task_onshutdown(t3, my_shutdown, three) ==
103 		      ISC_R_SUCCESS);
104 	RUNTIME_CHECK(isc_task_onshutdown(t4, my_shutdown, four) ==
105 		      ISC_R_SUCCESS);
106 
107 	timgr = NULL;
108 	RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);
109 	ti1 = NULL;
110 
111 	isc_interval_set(&interval, 1, 0);
112 	RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
113 				       &interval, t1, my_tick, foo,
114 				       &ti1) == ISC_R_SUCCESS);
115 
116 	ti2 = NULL;
117 	isc_interval_set(&interval, 1, 0);
118 	RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
119 				       &interval, t2, my_tick, bar,
120 				       &ti2) == ISC_R_SUCCESS);
121 
122 	printf("task 1 = %p\n", t1);
123 	printf("task 2 = %p\n", t2);
124 #ifndef WIN32
125 	sleep(2);
126 #else  /* ifndef WIN32 */
127 	Sleep(2000);
128 #endif /* ifndef WIN32 */
129 
130 	/*
131 	 * Note:  (void *)1 is used as a sender here, since some compilers
132 	 * don't like casting a function pointer to a (void *).
133 	 *
134 	 * In a real use, it is more likely the sender would be a
135 	 * structure (socket, timer, task, etc) but this is just a test
136 	 * program.
137 	 */
138 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
139 				   sizeof(*event));
140 	isc_task_send(t1, &event);
141 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
142 				   sizeof(*event));
143 	isc_task_send(t1, &event);
144 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
145 				   sizeof(*event));
146 	isc_task_send(t1, &event);
147 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
148 				   sizeof(*event));
149 	isc_task_send(t1, &event);
150 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
151 				   sizeof(*event));
152 	isc_task_send(t1, &event);
153 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
154 				   sizeof(*event));
155 	isc_task_send(t1, &event);
156 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
157 				   sizeof(*event));
158 	isc_task_send(t1, &event);
159 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
160 				   sizeof(*event));
161 	isc_task_send(t1, &event);
162 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
163 				   sizeof(*event));
164 	isc_task_send(t1, &event);
165 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, two,
166 				   sizeof(*event));
167 	isc_task_send(t2, &event);
168 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, three,
169 				   sizeof(*event));
170 	isc_task_send(t3, &event);
171 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, four,
172 				   sizeof(*event));
173 	isc_task_send(t4, &event);
174 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, two,
175 				   sizeof(*event));
176 	isc_task_send(t2, &event);
177 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, three,
178 				   sizeof(*event));
179 	isc_task_send(t3, &event);
180 	event = isc_event_allocate(mctx, (void *)1, 1, my_callback, four,
181 				   sizeof(*event));
182 	isc_task_send(t4, &event);
183 	isc_task_purgerange(t3, NULL, ISC_EVENTTYPE_FIRSTEVENT,
184 			    ISC_EVENTTYPE_LASTEVENT, NULL);
185 
186 	isc_task_detach(&t1);
187 	isc_task_detach(&t2);
188 	isc_task_detach(&t3);
189 	isc_task_detach(&t4);
190 
191 #ifndef WIN32
192 	sleep(10);
193 #else  /* ifndef WIN32 */
194 	Sleep(10000);
195 #endif /* ifndef WIN32 */
196 	printf("destroy\n");
197 	isc_timer_detach(&ti1);
198 	isc_timer_detach(&ti2);
199 	isc_timermgr_destroy(&timgr);
200 	isc_managers_destroy(&netmgr, &taskmgr);
201 	printf("destroyed\n");
202 
203 	isc_mem_stats(mctx, stdout);
204 	isc_mem_destroy(&mctx);
205 
206 	return (0);
207 }
208