aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2008-07-17 11:45:58 +0000
committerMartin Willi <martin@strongswan.org>2008-07-17 11:45:58 +0000
commitbd07b59079d22f75add9889eec6e4f84ce0b2678 (patch)
treee0e75692e423672872c361c44f7d75ddc88fe0b9
parent5353f22ed7a0568f32d880331a6d56f3632ccc8e (diff)
downloadstrongswan-bd07b59079d22f75add9889eec6e4f84ce0b2678.tar.bz2
strongswan-bd07b59079d22f75add9889eec6e4f84ce0b2678.tar.xz
avoid heap allocation in bus->signal for performance reasons
-rw-r--r--src/charon/bus/bus.c81
-rw-r--r--src/charon/bus/bus.h4
2 files changed, 51 insertions, 34 deletions
diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c
index 5f813e781..1c57fcc40 100644
--- a/src/charon/bus/bus.c
+++ b/src/charon/bus/bus.c
@@ -253,46 +253,67 @@ static void set_sa(private_bus_t *this, ike_sa_t *ike_sa)
pthread_setspecific(this->thread_sa, ike_sa);
}
-
/**
- * Implementation of bus_t.vsignal.
+ * data associated to a signal, passed to callback
*/
-static void vsignal(private_bus_t *this, signal_t signal, level_t level,
- char* format, va_list args)
-{
- iterator_t *iterator;
- entry_t *entry;
+typedef struct {
+ /** associated IKE_SA */
ike_sa_t *ike_sa;
+ /** invoking thread */
long thread;
-
- this->mutex->lock(this->mutex);
- ike_sa = pthread_getspecific(this->thread_sa);
- thread = get_thread_number(this);
-
- iterator = this->listeners->create_iterator(this->listeners, TRUE);
- while (iterator->iterate(iterator, (void**)&entry))
+ /** signal type */
+ signal_t signal;
+ /** signal level */
+ level_t level;
+ /** format string */
+ char *format;
+ /** argument list */
+ va_list args;
+} signal_data_t;
+
+/**
+ * listener invocation as a list remove callback
+ */
+static bool signal_cb(entry_t *entry, signal_data_t *data)
+{
+ if (!entry->listener->signal(entry->listener, data->signal, data->level,
+ data->thread, data->ike_sa, data->format, data->args))
{
- va_list args_copy;
- va_copy(args_copy, args);
- if (!entry->listener->signal(entry->listener, signal, level, thread,
- ike_sa, format, args_copy))
+ if (entry->blocker)
{
- iterator->remove(iterator);
- if (entry->blocker)
- {
- entry->blocker = FALSE;
- entry->condvar->signal(entry->condvar);
- }
- else
- {
- entry_destroy(entry);
- }
+ entry->blocker = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ else
+ {
+ entry_destroy(entry);
}
- va_end(args_copy);
+ return TRUE;
}
- iterator->destroy(iterator);
+ return FALSE;
+}
+
+/**
+ * Implementation of bus_t.vsignal.
+ */
+static void vsignal(private_bus_t *this, signal_t signal, level_t level,
+ char* format, va_list args)
+{
+ signal_data_t data;
+
+ data.ike_sa = pthread_getspecific(this->thread_sa);
+ data.thread = get_thread_number(this);
+ data.signal = signal;
+ data.level = level;
+ data.format = format;
+ va_copy(data.args, args);
+ this->mutex->lock(this->mutex);
+ /* we use the remove() method to invoke all listeners with small overhead */
+ this->listeners->remove(this->listeners, &data, (void*)signal_cb);
this->mutex->unlock(this->mutex);
+
+ va_end(data.args);
}
/**
diff --git a/src/charon/bus/bus.h b/src/charon/bus/bus.h
index 678bf37d4..6ceac4c51 100644
--- a/src/charon/bus/bus.h
+++ b/src/charon/bus/bus.h
@@ -320,10 +320,6 @@ struct bus_t {
*
* Same as bus_t.signal(), but uses va_list argument list.
*
- * @todo Improve performace of vsignal implementation. This method is
- * called extensively and therefore shouldn't allocate heap memory or
- * do other expensive tasks!
- *
* @param singal kind of the signal (up, down, rekeyed, ...)
* @param level verbosity level of the signal
* @param format printf() style format string