Newsgroup: it.comp.os.linux.development
Titolo: dubbi sui pthreads

Salve,
Ho un dubbio (non l'unico del resto) circa il funzionamento dei pthreads
in linux(RedHat 6.1).
Nel programmino riportato sotto, creo due threads che eseguono dei loops
infiniti senza sospensioni intermedie (niente syscalls).
Mi aspetto che dopo un secondo di sleeping il processo padre si
risvegli terminando il tutto.
Invece il PC si inchioda e sono costretto ad un reset HW.
Qualche idea?
Massimo Bertani
-----------------------------------------------------------------------
#include <stdio.h>
#include <sys/mman.h>
#include <pthread.h>
static volatile unsigned end;
static unsigned counter1;
static unsigned counter2;
void *task1(void *args)
{
    printf("\nSTARTING TASK 1\n");
    while(!end) { counter1++; }
}
void *task2(void *args)
{
    printf("\nSTARTING TASK 2\n");
    while(!end) { counter2++; }
}
int main(void)
{
    pthread_t thid1, thid2;
    struct sched_param mysched;
    mysched.sched_priority = 99;
    if( sched_setscheduler( 0, SCHED_FIFO, &mysched ) == -1 )
    {
     printf("\nERROR IN SETTING UP TASK0 POSIX FIFO SCHEDULER\n");
        return;
    }
    mlockall(MCL_CURRENT | MCL_FUTURE);
    printf("\nCREATING TASK 1\n");
    if (pthread_create(&thid1, NULL, task1, NULL)) {
     printf("\nERROR IN PTHREAD_CREATE FOR TASK1\n");
        return;
    }
    printf("\nCREATING TASK 2\n");
    if (pthread_create(&thid2, NULL, task2, NULL)) {
     printf("\nERROR IN PTHREAD_CREATE FOR TASK2\n");
 return;
    }
    printf("\nTASK 0 WAITS 1 SEC.\n");
    sleep(1);
    printf("\nTASK 0 RESUMES AND ENDS ALL THE TASKS\n");
    end = 1;
}

     if( sched_setscheduler( 0, SCHED_FIFO, &mysched ) == -1 )
...
Sicuramente uno dei problemi è che crei una struttura sched_param come se
volessi assegnare la priorità 99 ai thread, ma poi non la usi in
pthread_init.
Ciao!

 Invece il PC si inchioda e sono costretto ad un reset HW.
eccert...
da man sched_setscheduler:
       SCHED_FIFO can only be used with static priorities  higher
       than  0,  that  means  that  when  a  SCHED_FIFO processes
       becomes runnable, it will always preempt  immediately  any
       currently  running  normal SCHED_OTHER process.
       [...]
       SCHED_FIFO process runs until either it
       is  blocked by an I/O request, it is preempted by a higher
       priority process, or it calls sched_yield.
Praticamente il processo padre non verrā mai pių risvegliato, da come
hai fatto tu il programma. Ho dubbi anche sul fatto che il secondo
thread venga mai attivato, a questo punto.
Ma a che cavolo ti serve una cosa cosė?
Ciao,
Fabio Alemagna

Daniele Pallastrelli wrote:

Scusa ma cos'e' pthread_init? se faccio "man pthread_init" non mi trova
niente. Non
e' che forse dovrei chiamare sched_setscheduler() anche all'interno dei
threads assegnando priorita' piu' basse?


E' una storia lunga legata a RTAI (
www.aero.polimi.it
).
Il fatto che il secondo thread non giri in effetti lo immaginavo gia
Secondo te potrei
risolvere la situazione chiamando sched_setscheduler() all'interno dei thread
figli
assegnando loro SCHED_FIFO e priorita' piu' basse di 99? (100,101...).
Grazie
Massimo

in linux(RedHat 6.1). [...]
Tutti gli accessi a risorse condivise devono essere protetti da
semafori o mutexes, anche nel caso in cui un solo processo o
thread scrive mentre tutti gli altri leggono soltanto.
Chiaramente, meno codice c'e' all'interno del blocco protetto
e meglio e'.
Ecco un piccolo esempio. Per brevita' manca di alcuni controlli
di errori, ma funziona.
Per essre piu' puliti, comunque, sarebbe meglio definire una
struttura contenente tutti i dati di un thread, eventualmente
accodarla a quelle degli altri thread in una lista (o un array)
e fornirne un puntatore di partenza alle thread functions.
Idem per i dati condivisi.
PS. Il modello "crea un thread che fa qualcosa, poi ammazzalo
quando ha finito, o lascialo morire" e' concettualmente sbagliato
(provato sulla mia pelle:-). Meglio creare da subito N threads,
porli in attesa di un segnale, assegnare loro il lavoro quando
serve e quindi svegliarli. Quando uno dei threads ha finito, non
muore ma si pone in attesa di altro lavoro (hint: un function
pointer diverso nel punto in cui la thread function va a pescare
il codice da eseguire).
Guardati le varie pthread_cond_wait(), pthread_cond_signal(), ecc.
PPS. I cicli a vuoto ammazzano di lavoro il sistema; prova a far
girare l'esempio con la usleep commentata.
/* thd.c */
/* cc -o thd thd.c -pthread -Wall -ansi -pedantic */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#define N_THD 100
pthread_mutex_t n_mux,end_mux;
unsigned char thd_n=0,end=0;
void usleep(unsigned long);
void *thdfunc(void*);
int main(void)
{
int i=0,rc=0;
pthread_t tid;
pthread_attr_t attr;
pthread_mutex_init(&n_mux,NULL);
pthread_mutex_init(&end_mux,NULL);
rc=pthread_attr_init(&attr);
  for (i=0;i<N_THD;++i)
    rc=pthread_create(&tid, &attr, thdfunc, NULL);
  sleep(1);
  pthread_mutex_lock(&end_mux);
  ++end;
  pthread_mutex_unlock(&end_mux);
  sleep(1);
  exit(EXIT_SUCCESS);
}
void *thdfunc(void* arg)
{
  unsigned char end_local=0,thd_n_local=0;
  pthread_mutex_lock(&n_mux);
  thd_n_local=++thd_n;
  pthread_mutex_unlock(&n_mux);
  printf("Thread %d started\n",thd_n_local);
  while(!end_local)
  {
    pthread_mutex_lock(&end_mux);
    end_local=end;
    pthread_mutex_unlock(&end_mux);
    usleep(10);
  }
  printf("Thread %d finished\n",thd_n_local);
  pthread_exit(NULL);
}
~
~
-- 
sr - null...@PAMflashnet.it <strip NOS & PAM to email>
NT, Security, Networking. Chose two of the three. You can't have them all.

 threads assegnando priorita' piu' basse?
Scusa, intendevo pthread_create.
Questo è un pezzo di codice che funziona:
*********************
     pthread_attr_t ac;
     pthread_attr_t a[2];
     struct sched_param pc;
     struct sched_param p[2];
     pc.sched_priority = 50;
     p[0].sched_priority = 38;
     p[1].sched_priority = 40;
     pthread_attr_init( &ac );
     pthread_attr_setschedpolicy( &ac, SCHED_FIFO );
     pthread_attr_setschedparam( &ac, &pc );
     for ( int i = 0; i < 2; ++i )
    {
      pthread_attr_init( &a[i] );
      pthread_attr_setschedpolicy( &a[i], SCHED_FIFO );
      pthread_attr_setschedparam( &a[i], &p[i] );
    }
    pthread_create( &th[0], &a[0], f1, NULL );
    pthread_create( &th[1], &a[1], f2, NULL );
    pthread_create( &thc, &ac, command, NULL );