1/**
2 * \file
3 * \brief A simple test for checking if lpc_timer works
4 * It tests periodic timers implemented by timer library.
5 * test_A: When no arguments are given, then timer_test will run test_A
6 * which starts two periodic timers and stops them after 100 callbacks
7 * from each of them.
8 *
9 * test_B: When there are command line arguments given, then timer_test
10 * will run test_B.  This test registers three periodic timer and stops
11 * when 100 callbacks are received from all three timers.
12 *
13 * It is advised to run both test_A and test_B at same time.  It can be
14 * done by inserting following lines into the menu.lst
15 * module	/x86_64/sbin/lpc_timer core=1
16 * module	/x86_64/sbin/timer_test core=2
17 * module	/x86_64/sbin/timer_test core=3 B
18 *
19 */
20
21/*
22 * Copyright (c) 2007, 2008, ETH Zurich.
23 * All rights reserved.
24 *
25 * This file is distributed under the terms in the attached LICENSE file.
26 * If you do not find this file, copies can be found by writing to:
27 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
28 */
29
30#include <stdio.h>
31#include <barrelfish/barrelfish.h>
32#include <timer/timer.h>
33
34/* Real life example */
35//#define DHCP_FINE_TIMER 	20000000  /* client_1 callback_1 */
36//#define DHCP_CORSE_TIMER 	60000000  /* client_1 callback_2 */
37
38//#define TCP_INTERVAL 	250000 		/* client_2 callback_1 */
39//#define RPC_INTERVAL 	5000  		/* client_2 callback_2 */
40//#define CACHE_INTERVAL 	9000000		/* client_2 callback_3 */
41
42#define SMALL_INTERVAL 		200000  /* client_1 callback_1 */
43#define LARGE_INTERVAL 		700000  /* client_1 callback_2 */
44
45#define MEDIAM_INTERVAL 	450000 		/* client_2 callback_1 */
46#define SMALLEST_INTERVAL 	11000  		/* client_2 callback_2 */
47#define LARGEST_INTERVAL 	900000		/* client_2 callback_3 */
48
49#define MAX_LEN 512
50struct client_data{
51	struct timer *timer;
52	char *client_name;
53	char *timer_name;
54	long interval;
55	long counter;
56	long limit;
57	int is_stopped;
58};
59
60static int stopped_counter = 0;
61
62//#define DHCP_FINE_TIMER 	200000  /* client_1 callback_1 */
63//#define DHCP_CORSE_TIMER 	600000  /* client_1 callback_2 */
64
65
66//#define TCP_INTERVAL 	250000 		/* client_2 callback_1 */
67//#define RPC_INTERVAL 	5000  		/* client_2 callback_2 */
68//#define CACHE_INTERVAL 	9000000		/* client_2 callback_3 */
69
70static int l_debug = 0;
71
72static int is_stopped(struct client_data *cl)
73{
74	if(l_debug) printf("is_stopped called %s -> %s %ld callback counter %ld\n",
75			cl->client_name, cl->timer_name, cl->interval, cl->counter);
76
77	if(cl->is_stopped){
78		return cl->is_stopped;
79	}
80
81	if(cl->counter >= cl->limit){
82		printf("Stopping %s -> %s %ld callback counter %ld reached it's limit %ld.\n",
83				cl->client_name, cl->timer_name, cl->interval,
84				cl->counter, cl->limit);
85		timer_stop(cl->timer);
86//		timer_destroy(cl->timer);
87//		printf("### timer destroyed\n");
88		cl->is_stopped = 1;
89		++stopped_counter;
90//		printf("#### %s: stop_counter = %d\n", cl->client_name, stopped_counter);
91		return cl->is_stopped;
92	}
93
94	return cl->is_stopped;
95
96} /* end function : is_running */
97
98static void callback(struct timer *timer, void *data)
99{
100	struct client_data *cl = (struct client_data *)data;
101	assert(cl != NULL);
102	cl->counter = cl->counter + 1;
103
104	if(l_debug) printf("%s -> %s %ld callback counter %ld\n",
105    		cl->client_name, cl->timer_name, cl->interval, cl->counter);
106
107} /* end function: callback */
108
109static void setup_and_start_timer(struct client_data *ptr, char *c_name,
110		char *t_name, long interval, long limit)
111{
112    ptr->client_name = c_name;
113    ptr->timer_name = t_name;
114    ptr->interval = interval;
115    ptr->counter = 0;
116    ptr->limit = limit;
117    ptr->is_stopped = 0;
118    ptr->timer = timer_create(interval, true, callback, ptr);
119    timer_start(ptr->timer);
120}
121
122static void client_A(void)
123{
124    errval_t err;
125    char client_name[512];
126    snprintf(client_name, sizeof(client_name), "Client_A_%d",
127    		disp_get_core_id());
128    printf("%s: client A test running\n", client_name);
129
130    err = timer_init();
131    if (err_is_fail(err)) {
132    	printf("%s: timer_init failed\n", client_name);
133        USER_PANIC_ERR(err, "timer_init failed");
134    }
135
136    struct client_data for_t1;
137    setup_and_start_timer(&for_t1, client_name, "SMALL_INTERVAL",
138    		SMALL_INTERVAL, 100);
139
140    struct client_data for_t2;
141    setup_and_start_timer(&for_t2, client_name, "LARGE_INTERVAL",
142    		LARGE_INTERVAL, 100);
143
144    int r1, r2;
145    while(1){
146		r1 = is_stopped(&for_t1);
147		r2 = is_stopped(&for_t2);
148		if(r1 && r2){
149			return;
150		}
151		messages_wait_and_handle_next();
152	} /* end while: */
153}
154
155
156static void client_B(void)
157{
158    errval_t err;
159    char client_name[512];
160    snprintf(client_name, sizeof(client_name), "Client_B_%d",
161    		disp_get_core_id());
162    printf("%s: client B test running\n", client_name);
163
164    err = timer_init();
165    if (err_is_fail(err)) {
166    	printf("%s: timer_init failed\n", client_name);
167        USER_PANIC_ERR(err, "timer_init failed");
168    }
169
170    struct client_data for_t1;
171    setup_and_start_timer(&for_t1, client_name,
172    		"MEDIAM_INTERVAL", MEDIAM_INTERVAL, 100);
173
174    struct client_data for_t2;
175    setup_and_start_timer(&for_t2, client_name,
176    		"SMALLEST_INTERVAL", SMALLEST_INTERVAL, 100);
177
178    struct client_data for_t3;
179    setup_and_start_timer(&for_t3, client_name,
180    		"LARGEST_INTERVAL", LARGEST_INTERVAL, 100);
181
182    int r1, r2, r3;
183    while(1){
184
185    	r1 = is_stopped(&for_t1);
186		r2 = is_stopped(&for_t2);
187		r3 = is_stopped(&for_t3);
188
189		if(r1 && r2 && r3){
190			return;
191		}
192		messages_wait_and_handle_next();
193	} /* end while: */
194}
195
196
197int main(int argc, char *argv[])
198{
199    stopped_counter = 0;
200	printf("For core %d, argc = %d\n", disp_get_core_id(), argc);
201	if(argc == 1) {
202		client_A();
203		printf("Done with test for client_A\n");
204	} else {
205		client_B();
206		printf("Done with test for client_B\n");
207	}
208	while(stopped_counter < 2){
209		messages_wait_and_handle_next();
210	}
211    return 0;
212}
213