[Debburn-changes] r828 - cdrkit/trunk/genisoimage
Steve McIntyre
93sam at alioth.debian.org
Wed May 13 23:30:00 UTC 2009
Author: 93sam
Date: 2009-05-13 23:29:59 +0000 (Wed, 13 May 2009)
New Revision: 828
Modified:
cdrkit/trunk/genisoimage/CMakeLists.txt
cdrkit/trunk/genisoimage/checksum.c
Log:
genisoimage: checksumming with lots of algorithms can be very
time-consuming, so split it out into multiple threads if possible.
Modified: cdrkit/trunk/genisoimage/CMakeLists.txt
===================================================================
--- cdrkit/trunk/genisoimage/CMakeLists.txt 2009-05-11 00:27:09 UTC (rev 827)
+++ cdrkit/trunk/genisoimage/CMakeLists.txt 2009-05-13 23:29:59 UTC (rev 828)
@@ -12,6 +12,12 @@
SET(MAGICLIBS magic)
ENDIF(USE_MAGIC)
+CHECK_INCLUDE_FILES("pthread.h" USE_PTHREAD)
+IF(USE_PTHREAD)
+ ADD_DEFINITIONS(-DTHREADED_CHECKSUMS)
+ LIST(APPEND EXTRA_LIBS "pthread")
+ENDIF(USE_PTHREAD)
+
IF(HAVE_ICONV_H)
ADD_DEFINITIONS(-DUSE_ICONV)
#INCLUDE(CheckLibraryExists)
Modified: cdrkit/trunk/genisoimage/checksum.c
===================================================================
--- cdrkit/trunk/genisoimage/checksum.c 2009-05-11 00:27:09 UTC (rev 827)
+++ cdrkit/trunk/genisoimage/checksum.c 2009-05-13 23:29:59 UTC (rev 828)
@@ -20,6 +20,10 @@
#include "sha512.h"
#include "checksum.h"
+#ifdef THREADED_CHECKSUMS
+# include <pthread.h>
+#endif
+
static void md5_init(void *context)
{
mk_MD5Init(context);
@@ -125,17 +129,33 @@
struct algo_context
{
- void *context;
- unsigned char *digest;
- int enabled;
- int finalised;
- char *hexdump;
+ void *context;
+ unsigned char *digest;
+ int enabled;
+ int finalised;
+ char *hexdump;
+#ifdef THREADED_CHECKSUMS
+ unsigned char const *buf;
+ unsigned int len;
+ int which;
+ pthread_t thread;
+ struct _checksum_context *parent;
+ pthread_mutex_t start_mutex;
+ pthread_cond_t start_cv;
+#endif
};
struct _checksum_context
{
- char *owner;
- struct algo_context algo[NUM_CHECKSUMS];
+#ifdef THREADED_CHECKSUMS
+ unsigned int index;
+ unsigned int threads_running;
+ unsigned int threads_desired;
+ pthread_mutex_t done_mutex;
+ pthread_cond_t done_cv;
+#endif
+ char *owner;
+ struct algo_context algo[NUM_CHECKSUMS];
};
struct checksum_info *checksum_information(enum checksum_types which)
@@ -154,10 +174,52 @@
p += sprintf(p, "%2.2x", buf[i]);
}
+#ifdef THREADED_CHECKSUMS
+static void *checksum_thread(void *arg)
+{
+ struct algo_context *a = arg;
+ struct _checksum_context *c = a->parent;
+ int num_blocks_summed = 0;
+
+ while (1)
+ {
+ /* wait to be given some work to do */
+ pthread_mutex_lock(&a->start_mutex);
+ while (a->buf == NULL)
+ {
+ pthread_cond_wait(&a->start_cv, &a->start_mutex);
+ }
+ pthread_mutex_unlock(&a->start_mutex);
+
+ /* if we're given a zero-length buffer, then that means we're
+ * done */
+ if (a->len == 0)
+ break;
+
+ /* actually do the checksum on the supplied buffer */
+ algorithms[a->which].update(a->context, a->buf, a->len);
+ num_blocks_summed++;
+ a->buf = NULL;
+
+ /* and tell the main thread that we're done with that
+ * buffer */
+ pthread_mutex_lock(&c->done_mutex);
+ c->threads_running--;
+ if (c->threads_running == 0)
+ pthread_cond_signal(&c->done_cv);
+ pthread_mutex_unlock(&c->done_mutex);
+ }
+
+ pthread_exit(0);
+}
+#endif
+
checksum_context_t *checksum_init_context(int checksums, const char *owner)
{
int i = 0;
- struct _checksum_context *context = malloc(sizeof(struct _checksum_context));
+ int ret = 0;
+ struct _checksum_context *context = calloc(1, sizeof(struct _checksum_context));
+
if (!context)
return NULL;
@@ -168,25 +230,62 @@
return NULL;
}
+#ifdef THREADED_CHECKSUMS
+ pthread_mutex_init(&context->done_mutex, NULL);
+ pthread_cond_init(&context->done_cv, NULL);
+ context->index = 0;
+ context->threads_running = 0;
+ context->threads_desired = 0;
+
for (i = 0; i < NUM_CHECKSUMS; i++)
+ if ( (1 << i) & checksums)
+ context->threads_desired++;
+#endif
+
+ for (i = 0; i < NUM_CHECKSUMS; i++)
{
+ struct algo_context *a = &context->algo[i];
if ( (1 << i) & checksums)
{
- context->algo[i].context = malloc(algorithms[i].context_size);
- if (!context->algo[i].context)
+ a->context = malloc(algorithms[i].context_size);
+ if (!a->context)
+ {
+ checksum_free_context(context);
return NULL;
- context->algo[i].digest = malloc(algorithms[i].digest_size);
- if (!context->algo[i].digest)
- return NULL;
- context->algo[i].hexdump = malloc(1 + (2*algorithms[i].digest_size));
- if (!context->algo[i].hexdump)
- return NULL;
- algorithms[i].init(context->algo[i].context);
- context->algo[i].enabled = 1;
- context->algo[i].finalised = 0;
+ }
+ a->digest = malloc(algorithms[i].digest_size);
+ if (!a->digest)
+ {
+ checksum_free_context(context);
+ return NULL;
+ }
+ a->hexdump = malloc(1 + (2*algorithms[i].digest_size));
+ if (!a->hexdump)
+ {
+ checksum_free_context(context);
+ return NULL;
+ }
+ algorithms[i].init(a->context);
+ a->enabled = 1;
+ a->finalised = 0;
+#ifdef THREADED_CHECKSUMS
+ a->which = i;
+ a->parent = context;
+ a->buf = NULL;
+ a->len = 0;
+ pthread_mutex_init(&a->start_mutex, NULL);
+ pthread_cond_init(&a->start_cv, NULL);
+ ret = pthread_create(&a->thread, NULL, checksum_thread, a);
+ if (ret != 0)
+ {
+ fprintf(stderr, "failed to create new thread: %d\n", ret);
+ checksum_free_context(context);
+ return NULL;
+ }
+#endif
}
else
- context->algo[i].enabled = 0;
+ a->enabled = 0;
}
return context;
@@ -199,41 +298,116 @@
for (i = 0; i < NUM_CHECKSUMS; i++)
{
- free(c->algo[i].context);
- free(c->algo[i].digest);
- free(c->algo[i].hexdump);
+ struct algo_context *a = &c->algo[i];
+
+#ifdef THREADED_CHECKSUMS
+ if (a->thread)
+ {
+ void *ret;
+ pthread_cancel(a->thread);
+ pthread_join(a->thread, &ret);
+ a->thread = 0;
+ }
+#endif
+ free(a->context);
+ free(a->digest);
+ free(a->hexdump);
}
free(c->owner);
free(c);
}
+#ifdef THREADED_CHECKSUMS
void checksum_update(checksum_context_t *context,
unsigned char const *buf, unsigned int len)
{
int i = 0;
struct _checksum_context *c = context;
+ static int index = 0;
+
+ index++;
+
+ c->threads_running = c->threads_desired;
+ for (i = 0; i < NUM_CHECKSUMS; i++)
+ {
+ if (c->algo[i].enabled)
+ {
+ struct algo_context *a = &c->algo[i];
+ pthread_mutex_lock(&a->start_mutex);
+ a->len = len;
+ a->buf = buf;
+ pthread_cond_signal(&a->start_cv);
+ pthread_mutex_unlock(&a->start_mutex);
+ }
+ }
+
+ /* Should now all be running, wait on them all to return */
+ pthread_mutex_lock(&c->done_mutex);
+ while (c->threads_running > 0)
+ {
+ pthread_cond_wait(&c->done_cv, &c->done_mutex);
+ }
+ pthread_mutex_unlock(&c->done_mutex);
+}
+
+#else // THREADED_CHECKSUMS
+
+void checksum_update(checksum_context_t *context,
+ unsigned char const *buf, unsigned int len)
+{
+ int i = 0;
+ struct _checksum_context *c = context;
for (i = 0; i < NUM_CHECKSUMS; i++)
{
if (c->algo[i].enabled)
- algorithms[i].update(c->algo[i].context, buf, len);
+ {
+ struct algo_context *a = &c->algo[i];
+ algorithms[i].update(a->context, buf, len);
+ }
}
}
+#endif // THREADED_CHECKSUMS
+
void checksum_final(checksum_context_t *context)
{
int i = 0;
struct _checksum_context *c = context;
+#ifdef THREADED_CHECKSUMS
+ void *thread_ret;
+ /* Clean up the threads */
+ c->threads_running = c->threads_desired;
+
for (i = 0; i < NUM_CHECKSUMS; i++)
{
if (c->algo[i].enabled)
{
- algorithms[i].final(c->algo[i].digest, c->algo[i].context);
- hex_dump_to_buffer(c->algo[i].hexdump, c->algo[i].digest, algorithms[i].digest_size);
- c->algo[i].finalised = 1;
+ void *ret = 0;
+ struct algo_context *a = &c->algo[i];
+
+ pthread_mutex_lock(&a->start_mutex);
+ a->len = 0;
+ a->buf = (unsigned char *)-1;
+ pthread_cond_signal(&a->start_cv);
+ pthread_mutex_unlock(&a->start_mutex);
+ pthread_join(a->thread, &ret);
+ a->thread = 0;
}
}
+#endif
+
+ for (i = 0; i < NUM_CHECKSUMS; i++)
+ {
+ struct algo_context *a = &c->algo[i];
+ if (a->enabled)
+ {
+ algorithms[i].final(a->digest, a->context);
+ hex_dump_to_buffer(a->hexdump, a->digest, algorithms[i].digest_size);
+ a->finalised = 1;
+ }
+ }
}
void checksum_copy(checksum_context_t *context,
More information about the Debburn-changes
mailing list