Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/util/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/thread.c')
-rw-r--r--src/util/thread.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/util/thread.c b/src/util/thread.c
new file mode 100644
index 0000000..f3ef4a7
--- /dev/null
+++ b/src/util/thread.c
@@ -0,0 +1,221 @@
+#ifndef _plan9_
+#include <signal.h>
+#include <stdio.h>
+#endif
+#include <xthread.h>
+#ifndef __BEOS__
+struct taskinfo definfo = {
+ 0,
+};
+
+#ifndef nthreads
+
+#define getrange1(range,ncpu) ((range)*(ncpu))/nthreads
+#define getrange2(range,ncpu) getrange1(range,(ncpu)+1)
+
+int ethreads = 0;
+int nthreads = 1;
+
+#ifdef USE_PTHREAD
+
+/* Well conde follows is probably very ugly, since this is
+ * my absolutely first application for threads. Please let
+ * me know how to improvie it
+ */
+
+static pthread_cond_t synccond, startcond;
+static struct taskinfo infos[MAXTHREADS];
+static pthread_mutex_t synccondmutex, startcondmutex;
+pthread_mutex_t semaphors[MAXSEMAPHORS];
+pthread_cond_t conds[MAXCONDS];
+
+/*This loop is executed whole time in slave threads.
+ Its function is following:
+ 1) wait for message
+ 2) call function from message
+ 3) syncronize
+ 4) again
+
+ To invoke this mechanizm main thread(#1) should call
+ xth_function
+ xth_synchronize forces forces thread to wait for others
+ */
+
+static int nfinished;
+static int npending;
+static int counter;
+static int bcounter;
+static int bcounter1;
+static int range;
+static void *data;
+static xfunction function;
+static void *control_routine(void *i)
+{
+ struct taskinfo *info = i;
+ int mycounter = 0;
+ int r;
+ void *d;
+ xfunction f;
+ while (1) {
+ /* quite a lot pthread calls. Please if you are
+ * reading this code and crying "OH NO!" so ugly
+ * handling! Why so much calls? Stop crying, I am
+ * newbie in threads. Please rewrite my code and
+ * send me better and faster version.
+ *
+ * This function comunicates with pth_function from main loop
+ * as follows: it uses startcond to wait for order start function!
+ * Counter is used to ensure that main function did not give
+ * order whie control_routine was busy
+ *
+ * after order is received, function adress is readed from global
+ * variables and started. Pth_function then executes its
+ * own part of calculation. After that it waits counter
+ * nfinished to reach number of thasks-1. This is done
+ * using cond synccond and synccondmutex. Quite complex
+ * but it seems to work. Looking forward for someone, who
+ * should reduce number of _lock/_unlock
+ */
+ pthread_mutex_lock(&synccondmutex);
+ nfinished++;
+ pthread_cond_signal(&synccond);
+ pthread_mutex_unlock(&synccondmutex);
+
+ pthread_mutex_lock(&startcondmutex);
+ while (mycounter >= counter) {
+ if (bcounter > bcounter1) {
+ /*Well we are already locked using start lock..should be OK */
+ mycounter--;
+ bcounter1++;
+ break;
+ }
+ pthread_cond_wait(&startcond, &startcondmutex);
+ }
+ r = range;
+ d = data;
+ f = function;
+ npending--;
+ pthread_mutex_unlock(&startcondmutex);
+ mycounter++;
+ f(d, info, getrange1(r, info->n), getrange2(r, info->n));
+ }
+ return NULL;
+}
+
+void pth_init(int nthreads1)
+{
+ int i;
+ pthread_attr_t attr;
+ if (ethreads)
+ return;
+
+ if (nthreads1 == 1 || nthreads1 == 0)
+ return; /*use nothreads_* calls */
+ if (nthreads1 > MAXTHREADS)
+ nthreads1 = MAXTHREADS;
+ nthreads = nthreads1;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (pthread_cond_init(&synccond, NULL))
+ exit(1);
+ if (pthread_cond_init(&startcond, NULL))
+ exit(1);
+ if (pthread_mutex_init(&synccondmutex, NULL))
+ exit(1);
+ if (pthread_mutex_init(&startcondmutex, NULL))
+ exit(1);
+
+ infos[0].n = 0;
+ /*infos[0].id = pthread_self(); */
+
+ for (i = 0; i < MAXSEMAPHORS; i++) {
+ pthread_mutex_init(semaphors + i, NULL);
+ }
+ for (i = 0; i < MAXCONDS; i++) {
+ pthread_cond_init(conds + i, NULL);
+ }
+
+ nfinished = 0;
+ for (i = 0; i < nthreads - 1; i++) {
+ if (pthread_create
+ (&infos[i + 1].id, &attr, control_routine, infos + i + 1)) {
+ nthreads = i + 1;
+ break;
+ }
+ infos[i + 1].n = i + 1;
+ }
+ if (nthreads != 1)
+ ethreads = 1;
+}
+
+void pth_synchronize()
+{
+ /*Our job is done, synchronize now */
+ if (nfinished < nthreads - 1) {
+ pthread_mutex_lock(&synccondmutex);
+ while (nfinished < nthreads - 1) {
+ pthread_cond_wait(&synccond, &synccondmutex);
+ }
+ pthread_mutex_unlock(&synccondmutex);
+ }
+ /*Ok job is done, lets continue :) */
+}
+
+void pth_bgjob(xfunction f, void *d)
+{
+ pthread_mutex_lock(&startcondmutex);
+ if (npending) {
+ printf("Collision!\n"); /*FIXME:remove this..I just want to know how often this happends */
+ pthread_mutex_unlock(&startcondmutex);
+ f(d, infos, 0, 0);
+ }
+ if (bcounter < bcounter1) {
+ printf("Internal error\a\n");
+ }
+ if (!nfinished) {
+ pthread_mutex_unlock(&startcondmutex);
+ /*no more CPU available :( */
+ f(d, infos, 0, 0);
+ }
+ data = d;
+ range = 0;
+ function = f;
+ bcounter++;
+ nfinished--;
+ npending++;
+ pthread_cond_signal(&startcond);
+ pthread_mutex_unlock(&startcondmutex);
+}
+
+void pth_function(xfunction f, void *d, int r)
+{
+ pth_synchronize();
+ pthread_mutex_lock(&startcondmutex);
+ data = d;
+ range = r;
+ function = f;
+ /*And lets start it:) */
+ nfinished = 0;
+ npending = nthreads - 1;
+ counter++;
+ if (nthreads == 2)
+ pthread_cond_signal(&startcond);
+ else
+ pthread_cond_broadcast(&startcond);
+ pthread_mutex_unlock(&startcondmutex);
+
+ function(data, infos, getrange1(range, 0), getrange2(range, 0));
+}
+
+void pth_uninit()
+{
+ /*Should be empty for now since all threads will be killed after exit call */
+ /*FIXME should be added something if necessary :) */
+ nthreads = 1;
+ ethreads = 0;
+}
+#endif /*POSIX threads */
+#endif /*nthreads */
+#endif /*__BEOS__*/