Hallo HaWe,

also nachdem ich mir dein Mindstrom Code angesehen habe, wäre wohl der erste Schritt Deine Berechnungsroutinen "task_PID_[ABC]" so umzuscheiben, das sie als Parameter einen Zeiger auf eine struct eines PIDs bekommen. Ansonsten landest Du wieder bei der Code-Redundanz, wie Du sie im Mindstorm-Projekt hast.

Code:
#include <stdio.h>
#include <pthread.h>

struct PID {
  pthread_t tid;
  char* name;

  float p;
  float i;
  float d;
};

struct PID pids[] = { 
  {0, "Task A", 0.015, 0.2, 0.7 },
  {0, "Task B", 0.3, 0.5, 0.80 }
};;

/* thread main */
void *calc_pid(void *arg) {
  struct pid* PID = (struct pid*)arg;
  int idx = 0;

  for(idx = 0; idx < 8; idx++) {
    pid->p += .03;
    printf("[%d]: %s, p=%f, i=%f, d=%f\n", idx, pid->name, pid->p, 
	   pid->i, pid->d);
  }

  return 0;
}

int main(int argc, char** argv) {
  int idx  = 0;
  int size = sizeof(pids)/sizeof(struct pid);

  /* Konfig fuer eine Aktion beider Motoren,
     wie immer die aussehen mag */

  for(idx = 0; idx < size; idx++)
    if(pthread_create(&pids[idx].tid, 0, calc_pid, &pids[idx])) {
      perror("pthread not creatable ");
      return 1;
    }

  for(idx = size - 1; idx >= 0; idx--) {
    if(pthread_join(pids[idx].tid, 0)) {
      fprintf(stderr, "Couldn't join thread for task %s ", pids[idx].name);
      perror(" ");
      continue;
    }
    pids[idx].tid = 0;
  }

  return 0;
}
Das was in dem einfachen Beispiel in der main() steht würdest du halt für jede Motoraktion (Rotate, Continue etc...) durchimplementieren müssen. Auch müßtest Du den Zeiger auf die einzelne struct ordentlich an die anderen Funktionen weiterreichen, damit diese immer nur auf dieser einen Variable operieren und so keine Wettbewerbsbedingungen entstehen.
Der Nachteil ist IHMO, dass Threads erzeugt und wieder vernichtet werden, was Resourcen kostet.

Ein anderer Ansatz wäre, für jeden PID einmal einen Thread anzulegen, der aus einer synchronisierten Schlange für einen Motor Kommandos liest, ausführt und zurück meldet das es fertig ist. Dann gäbe es einen Thread der den anderen sagt was zu tun ist - quasi das Kommando über sie hat.
Nachteil hier ist, das Du einen Synchronisationsmechanismus implementieren müßtest.

Auch könntest du dir vielleicht mal die OMP Threading-Variante anschauen, dann hättest du weniger mit Synchronisationsaufwand zu tun und ist möglicher Weise der übersichtlichere Weg für dich.

Das sind so meine Ideen zu deinem Problem.

Gruß
botty