1 /******************************************************************************
2 *
3 * Copyright © International Business Machines Corp., 2006, 2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * NAME
20 * async_handler_jk.c
21 *
22 * DESCRIPTION
23 * This test mimics an async event handler in a real-time JVM
24 * An async event server thread is created that goes to sleep waiting
25 * to be woken up to do some work.
26 *
27 * A user thread is created that simulates the firing of an event by
28 * signalling the async handler thread to do some work.
29 *
30 * USAGE:
31 * Use run_auto.sh script in current directory to build and run test.
32 *
33 * AUTHOR
34 * John Kacur <jkacur@ca.ibm.com>
35 *
36 * HISTORY
37 * 2006-Nov-20: Initial Version by John Kacur <jkacur@ca.ibm.com>
38 *
39 *****************************************************************************/
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <math.h>
44 #include <librttest.h>
45 #include <libstats.h>
46
47 // This is the normal priority for an event handler if not specified.
48 #define NORMAL_PRIORITY 43
49 #define THREAD_FLAG_SUSPENDED 8
50 #define PASS_US 100
51
52 long start, end;
53
54 /* Function Prototypes */
55 void *async_event_server(void *arg);
56 void *handler1(void *arg);
57
usage(void)58 void usage(void)
59 {
60 rt_help();
61 printf("async_handler_jk specific options:\n");
62 }
63
parse_args(int c,char * v)64 int parse_args(int c, char *v)
65 {
66
67 int handled = 1;
68 switch (c) {
69 case 'h':
70 usage();
71 exit(0);
72 default:
73 handled = 0;
74 break;
75 }
76 return handled;
77 }
78
async_event_server(void * arg)79 void *async_event_server(void *arg)
80 {
81 int err = 0;
82 struct thread *thread = ((struct thread *)arg);
83
84 thread->func = NULL; // entrypoint
85 thread->flags |= THREAD_FLAG_SUSPENDED;
86
87 for (;;) {
88 if ((err = pthread_mutex_lock(&thread->mutex)))
89 return (void *)(intptr_t) err;
90
91 /* Go to sleep and wait for work */
92 while (thread->flags & THREAD_FLAG_SUSPENDED)
93 pthread_cond_wait(&thread->cond, &thread->mutex);
94
95 pthread_mutex_unlock(&thread->mutex);
96
97 /* The JVM would be able to dynamically choose a handler */
98 thread->func = handler1;
99
100 if (thread->func != NULL)
101 thread->func(arg);
102
103 // Reset Priority to original async server priority
104 set_thread_priority(thread->pthread, thread->priority);
105
106 thread->flags |= THREAD_FLAG_SUSPENDED;
107 } // Go back to sleep and wait for next command
108 }
109
user_thread(void * arg)110 void *user_thread(void *arg)
111 {
112 struct thread *thread = ((struct thread *)arg);
113 struct thread *server = (struct thread *)thread->arg;
114
115 start = rt_gettime();
116
117 /* Change the async server thread priority to be the priority
118 of the user_thread. (event thread) */
119 set_thread_priority(server->pthread, thread->priority);
120
121 /* Clear the THREAD_FLAG_SUSPENDED flag of the server before signal */
122 server->flags &= ~THREAD_FLAG_SUSPENDED;
123
124 /* Signal the async server thread - simulates firing of an event */
125 pthread_cond_broadcast(&server->cond);
126
127 return NULL;
128 }
129
handler1(void * arg)130 void *handler1(void *arg)
131 {
132 end = rt_gettime();
133 return NULL;
134 }
135
main(int argc,char * argv[])136 int main(int argc, char *argv[])
137 {
138 int aes_id; // asynchronous event server id
139 int user_id; // User thread - that fires the event
140 long delta;
141 struct thread *server;
142 setup();
143
144 pass_criteria = PASS_US;
145 rt_init("h", parse_args, argc, argv);
146
147 aes_id = create_fifo_thread(async_event_server, NULL, 83);
148 server = get_thread(aes_id);
149
150 user_id =
151 create_fifo_thread(user_thread, (void *)server, NORMAL_PRIORITY);
152
153 usleep(1000);
154 pthread_detach(server->pthread);
155 join_thread(user_id);
156 join_threads();
157 delta = (end - start) / NS_PER_US;
158
159 printf("delta = %ld us\n", delta);
160 printf("\nCriteria: latencies < %d\n", (int)pass_criteria);
161 printf("Result: %s\n", delta > pass_criteria ? "FAIL" : "PASS");
162
163 return 0;
164 }
165