cvsuser 04/01/18 01:52:24
Modified: src events.c
Log:
event-handling-18
* fix a race: the interpreter sometimes processed events already
while the event thread was still looking at that event, which
was NULL in the meantime
* cleanup - separate process_events func
Revision Changes Path
1.21 +95 -68 parrot/src/events.c
Index: events.c
===================================================================
RCS file: /cvs/public/parrot/src/events.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -w -r1.20 -r1.21
--- events.c 17 Jan 2004 19:59:19 -0000 1.20
+++ events.c 18 Jan 2004 09:52:23 -0000 1.21
@@ -1,7 +1,7 @@
/* events.c
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: events.c,v 1.20 2004/01/17 19:59:19 leo Exp $
+ * $Id: events.c,v 1.21 2004/01/18 09:52:23 leo Exp $
* Overview:
* Event handling stuff
* Data Structure and Algorithms:
@@ -213,14 +213,21 @@
Parrot_schedule_event(NULL, ev);
}
+/*
+ * put a queue entry into the interpreters task queue
+ */
void
Parrot_schedule_interp_qentry(Parrot_Interp interpreter, QUEUE_ENTRY* entry)
{
parrot_event* event;
- push_entry(interpreter->task_queue, entry);
event = entry->data;
if (event->type != EVENT_TYPE_SLEEP)
enable_event_checking(interpreter);
+ /*
+ * do push_entry last - this signales the queue condition so the
+ * interpreter might starting process that event immediately
+ */
+ push_entry(interpreter->task_queue, entry);
}
/*
@@ -240,48 +247,23 @@
event->u.timer_event.abs_time = now + event->u.timer_event.interval;
return new_entry;
}
+
/*
- * The event_thread is started by the first interpreter.
- * It handles all events for all interpreters.
+ * do something, when an event arrived caller has locked the mutex
+ * returns 0 if event thread terminates
*/
-static void*
-event_thread(void *data)
+static int
+process_events(QUEUE* event_q)
{
- QUEUE* event_q = (QUEUE*) data;
- parrot_event* event;
+ FLOATVAL now;
QUEUE_ENTRY *entry;
+ parrot_event* event;
- LOCK(event_q->queue_mutex);
- while (1) {
- entry = peek_entry(event_q);
- if (!entry) {
- /* wait infinite until entry arrives */
- queue_wait(event_q);
- }
- else if (entry->type == QUEUE_ENTRY_TYPE_TIMED_EVENT) {
- /* do a_timedwait for entry */
- struct timespec abs_time;
- FLOATVAL when;
- event = (parrot_event* )entry->data;
- when = event->u.timer_event.abs_time;
- abs_time.tv_sec = (time_t) when;
- abs_time.tv_nsec = (when - abs_time.tv_sec) * (1000L*1000L*1000L);
-
- queue_timedwait(event_q, &abs_time);
- }
- else {
- /* we shouldn't get here probably
- * - the event queue terminating event is seen here
- */
-
- }
+ while (( entry = peek_entry(event_q))) {
/*
* one or more entries arrived - we hold the mutex again
* so we have to use the nonsyc_pop_entry to pop off event entries
*/
- while (( entry = peek_entry(event_q))) {
- FLOATVAL now;
-
event = NULL;
switch (entry->type) {
case QUEUE_ENTRY_TYPE_EVENT:
@@ -297,7 +279,7 @@
* wait until we get at it again when time has elapsed
*/
if (now < event->u.timer_event.abs_time)
- goto again;
+ return 1;
entry = nosync_pop_entry(event_q);
/*
* if event is repeated dup and reinsert it
@@ -314,17 +296,16 @@
default:
internal_exception(1, "Unknown queue entry");
}
- /*
- * TODO check for a stop event to do cleanup
- */
assert(event);
if (event->type == EVENT_TYPE_NONE) {
mem_sys_free(entry);
+ mem_sys_free(event);
continue;
}
else if (event->type == EVENT_TYPE_EVENT_TERMINATE) {
mem_sys_free(entry);
- goto out;
+ mem_sys_free(event);
+ return 0;
}
/*
* now insert entry in interpreter task queue
@@ -337,16 +318,62 @@
* TODO broadcast or deliver to first interp
*/
mem_sys_free(entry);
+ mem_sys_free(event);
}
} /* while events */
-again:
- ;
+ return 1;
+}
+
+/*
+ * The event_thread is started by the first interpreter.
+ * It handles all events for all interpreters.
+ */
+static void*
+event_thread(void *data)
+{
+ QUEUE* event_q = (QUEUE*) data;
+ parrot_event* event;
+ QUEUE_ENTRY *entry;
+ int running = 1;
+
+ LOCK(event_q->queue_mutex);
+ /*
+ * we might already have an event in the queue
+ */
+ if (peek_entry(event_q))
+ running = process_events(event_q);
+ while (running) {
+ entry = peek_entry(event_q);
+ if (!entry) {
+ /* wait infinite until entry arrives */
+ queue_wait(event_q);
+ }
+ else if (entry->type == QUEUE_ENTRY_TYPE_TIMED_EVENT) {
+ /* do a_timedwait for entry */
+ struct timespec abs_time;
+ FLOATVAL when;
+ event = (parrot_event* )entry->data;
+ when = event->u.timer_event.abs_time;
+ abs_time.tv_sec = (time_t) when;
+ abs_time.tv_nsec = (when - abs_time.tv_sec) * (1000L*1000L*1000L);
+
+ queue_timedwait(event_q, &abs_time);
+ }
+ else {
+ /* we shouldn't get here probably
+ */
+ internal_exception(1, "Spurious event");
+
+ }
+ /*
+ * one or more entries arrived - we hold the mutex again
+ * so we have to use the nonsyc_pop_entry to pop off event entries
+ */
+ running = process_events(event_q);
} /* event loop */
-out:
/*
* the main interpreter is dying
*/
- mem_sys_free(event);
UNLOCK(event_q->queue_mutex);
queue_destroy(event_q);
return NULL;