/****************************************************************************** * * Copyright © International Business Machines Corp., 2006, 2008 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NAME * async_handler_jk.c * * DESCRIPTION * This test mimics an async event handler in a real-time JVM * An async event server thread is created that goes to sleep waiting * to be woken up to do some work. * * A user thread is created that simulates the firing of an event by * signalling the async handler thread to do some work. * * USAGE: * Use run_auto.sh script in current directory to build and run test. * * AUTHOR * John Kacur <jkacur@ca.ibm.com> * * HISTORY * 2006-Nov-20: Initial Version by John Kacur <jkacur@ca.ibm.com> * *****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <librttest.h> #include <libstats.h> // This is the normal priority for an event handler if not specified. #define NORMAL_PRIORITY 43 #define THREAD_FLAG_SUSPENDED 8 #define PASS_US 100 long start, end; /* Function Prototypes */ void *async_event_server(void *arg); void *handler1(void *arg); void usage(void) { rt_help(); printf("async_handler_jk specific options:\n"); } int parse_args(int c, char *v) { int handled = 1; switch (c) { case 'h': usage(); exit(0); default: handled = 0; break; } return handled; } void *async_event_server(void *arg) { int err = 0; struct thread *thread = ((struct thread *)arg); thread->func = NULL; // entrypoint thread->flags |= THREAD_FLAG_SUSPENDED; for (;;) { if ((err = pthread_mutex_lock(&thread->mutex))) return (void *)(intptr_t) err; /* Go to sleep and wait for work */ while (thread->flags & THREAD_FLAG_SUSPENDED) pthread_cond_wait(&thread->cond, &thread->mutex); pthread_mutex_unlock(&thread->mutex); /* The JVM would be able to dynamically choose a handler */ thread->func = handler1; if (thread->func != NULL) thread->func(arg); // Reset Priority to original async server priority set_thread_priority(thread->pthread, thread->priority); thread->flags |= THREAD_FLAG_SUSPENDED; } // Go back to sleep and wait for next command } void *user_thread(void *arg) { struct thread *thread = ((struct thread *)arg); struct thread *server = (struct thread *)thread->arg; start = rt_gettime(); /* Change the async server thread priority to be the priority of the user_thread. (event thread) */ set_thread_priority(server->pthread, thread->priority); /* Clear the THREAD_FLAG_SUSPENDED flag of the server before signal */ server->flags &= ~THREAD_FLAG_SUSPENDED; /* Signal the async server thread - simulates firing of an event */ pthread_cond_broadcast(&server->cond); return NULL; } void *handler1(void *arg) { end = rt_gettime(); return NULL; } int main(int argc, char *argv[]) { int aes_id; // asynchronous event server id int user_id; // User thread - that fires the event long delta; struct thread *server; setup(); pass_criteria = PASS_US; rt_init("h", parse_args, argc, argv); aes_id = create_fifo_thread(async_event_server, NULL, 83); server = get_thread(aes_id); user_id = create_fifo_thread(user_thread, (void *)server, NORMAL_PRIORITY); usleep(1000); pthread_detach(server->pthread); join_thread(user_id); join_threads(); delta = (end - start) / NS_PER_US; printf("delta = %ld us\n", delta); printf("\nCriteria: latencies < %d\n", (int)pass_criteria); printf("Result: %s\n", delta > pass_criteria ? "FAIL" : "PASS"); return 0; }