meine PID threads müssen sowohl durchlaufen können (sich selbst überlassen) als auch von außen beendet werden können, falls nötig.
Wie das gehen soll, ist im Prinzip auch "Verhandlungssache" (gewaltsam oder über einen Semaphor, s.u.).
Wer dann hinterher aufräumt, ist mir wurscht, am praktischsten ntl, wenn es automatisch geht
A-Bär: wenn er einmal beendet ist, muss er (bzw. sein Nachfolger mit derselben port-Nr) ntl jederzeit wieder neu gestartet werden können, für die nächste PID-Annäherung. Ob er dann vom OS eine neue pthread-ID zugewiesen bekommt, ist aber ntl auch wieder egal.

Was das Joinen bewirkt, ist mir nicht ganz klar, ich hatte es so verstanden, dass ihre Timeslice wieder mit der von main() vereinigt wird.
Alle PID-Tasks sollen so gleichartig behandelt werden, während meine Tasks, die von main() am Anfang gestartet werden, so bleiben können wie bisher:
hier muss ich nichts unbedingt gewaltsam beenden, und wenn, dann funktioniert das dort über eine globale Variable (Semaphor) _TASKS_ACTIVE_ :
sobald die iwo auf false gesetzt wird, beenden sich alle Haupt-Threads dann selbsttätig und werden dann in main() gejoint:


Code:
// ***SNIP***


void* thread3Go (void* ) {       //  highest priority:  100µs encoder timer
   while(_TASKS_ACTIVE_) {   
      updateEncoders();
      usleep(100);
   }
   return NULL;
}



void* thread4Go (void* ) {       //  medium  priority: UART
    while(_TASKS_ACTIVE_) {   
      UARTcomm();
   }
    return NULL;
}


// ***SNIP***



int main() {
    char  sbuf[128];
    int err;
 
    // wiringPi   
    err = wiringPiSetup();   
    if( err == -1 ) return 1;     
       
    // UART Serial com port
    fserialRemote = serialOpen (usb0, UARTclock);            //  UART baud rate     
       
    initarrays();       
    setupDpins();
    setupI2C();
   
    pthread_t thread0, thread1, thread2, thread3, thread4, thread5;
    struct  sched_param  param;

    pthread_create(&thread0, NULL, thread0Go, NULL);     // lowest priority task: screen output
    param.sched_priority = 10;
    pthread_setschedparam(thread0, SCHED_RR, &param);
   
    pthread_create(&thread1, NULL, thread1Go, NULL);     // low priority: keyboard monitoring (stop program)
    param.sched_priority = 20;
    pthread_setschedparam(thread1, SCHED_RR, &param);
   
    pthread_create(&thread2, NULL, thread2Go, NULL);     // medium  priority: motor control
    param.sched_priority = 40;
    pthread_setschedparam(thread2, SCHED_RR, &param);
   
    pthread_create(&thread3, NULL, thread3Go, NULL);     // highest priority: encoder reading     
    param.sched_priority = 80;
    pthread_setschedparam(thread3, SCHED_FIFO, &param);
   
    pthread_create(&thread4, NULL, thread4Go, NULL);     // medium priority:  UART comm   <<< test !!
    param.sched_priority = 40;
    pthread_setschedparam(thread4, SCHED_FIFO, &param);
   
    pthread_create(&thread5, NULL, thread5Go, NULL);     // medium priority: navigation
    param.sched_priority = 40;
    pthread_setschedparam(thread5, SCHED_FIFO, &param);
   


    while(_TASKS_ACTIVE_) { delay(1); }
     
    // wait for threads to join before exiting
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);
    pthread_join(thread5, NULL);
   
    serialClose( fserialRemote);
   
    exit(0);
}

falls es das irgendwie einfacher macht, könnte man auch die PID-threads auf diese Weise mit einer zusätzlichen Abbruchbedingung stoppen!