2009-02-17 17 views
33

Ho un pthread_t, e mi piacerebbe cambiare l'affinità della CPU. Il problema è che sto usando glibc 2.3.2, che non ha pthread_setaffinity_np(). Va bene, però, perché pthread_setaffinity_np() è esso stesso un wrapper di sched_setaffinity(), che può essere chiamato passando un ID di thread invece di un ID di processo per impostare l'affinità per un thread arbitrario.Come ottengo un ID filo da un pthread_t arbitrario?

MA ... L'id filo che sched_setaffinity può lavorare con è un id filo sistema operativo, il tipo che si può ottenere dalla chiamata di sistema gettid(). Questo è diverso dal tipo opaco pthread_t e gettid() restituirà solo il threadid del thread corrente . Devo essere in grado di impostare l'affinità della CPU di un thread arbitrario.

Sfortunatamente, non riesco ad accedere alle parti private del pthread, il che mi consente di rubare l'id del thread lanciando un pthread_t a struct pthread *. Tanto meglio, immagino, dal momento che fare affidamento su implementazioni private richiede anche problemi in più.

Ho letto anche la funzione pthread_getunique_np, tuttavia questo restituisce un "identificatore integrale univoco" - che non credo sia in alcun modo forma o forma equivalente a un ID del thread del sistema operativo.

Quindi, la domanda: come posso ottenere un ID filo da un pthread_t arbitrario?

risposta

31

Poiché pthread s non devono essere implementati con i thread Linux (o con i thread del kernel), e alcune implementazioni sono interamente a livello utente o miste, l'interfaccia pthread s non fornisce funzioni per accedere a questi dettagli di implementazione, in quanto non sarebbero portabili (anche attraverso le implementazioni di pthread su Linux). Le librerie di thread che usano quelle potrebbero fornire questa estensione, ma sembra che non ce ne siano altre.

Diverso dall'accesso alle strutture di dati interne della libreria di threading (cosa che non è comprensibile, anche se con le ipotesi sull'affinità del processore e gli ID di thread Linux, il tuo codice non sarà comunque portatile), potresti essere in grado di riprodurre un trick al momento della creazione, se controlli il codice che crea i fili:

Give pthread_create() una funzione di voce che chiama gettid() (che tra l'altro si rischia di avere a che fare con il syscall macro direttamente, perché non è sempre esportato per libc), memorizza il risultato da qualche parte, quindi chiama la funzione di inserimento originale. Se si hanno più thread con la stessa funzione di inserimento, è possibile passare un puntatore incrementato a un array nell'argomento arg a pthread_create, che verrà quindi passato alla funzione di immissione creata per memorizzare l'ID del thread. Conservare il valore di ritorno pthread_t di pthread_create nello stesso ordine, e quindi sarete in grado di cercare gli ID di thread Linux di tutti i thread creati in base al loro valore pthread_t.

Se questo trucco è valsa la pena, dipende da quanto sia importante tramontando l'affinità CPU è nel tuo caso, contro non accedono strutture interne della biblioteca thread o seconda di una libreria di thread che fornisce pthread_setaffinity_np.

1

Suggerirei una soluzione semplice con un array int condiviso in cui è possibile scrivere l'id del thread dai thread per accedervi in ​​seguito.

Spero che questo aiuti.

+1

Non c'è bisogno di mmap, i thread condividono comunque la stessa memoria. – raimue

+0

Buon punto :) cavolo che è così ovvio ...;) –

2
pthread_t pthread_self() 

questo ritorno pthread_t corrente, che è filo id, è possibile convertirlo in tipo "unsigned int",

+2

In realtà 'unsigned long int'. – JumpAlways

+0

'pthread_t me();' => riferimento a 'me()'. – Eric

12

realtà pthread_self rendimenti pthread_t e non un filo id intero è possibile lavorare con i seguenti helper la funzione ti porterà in modo portatile attraverso diversi sistemi POSIX.

uint64_t gettid() { 
    pthread_t ptid = pthread_self(); 
    uint64_t threadId = 0; 
    memcpy(&threadId, &ptid, std::min(sizeof(threadId), sizeof(ptid))); 
    return threadId; 
} 
+0

'pthread_t tid = pthread_self();' funziona sul thread principale, ma non su un altro? Ho il mio arresto di exe che lo chiama da '__start_routine' dopo aver chiamato' pthread_create'. – Eric

0

In glibc 2.24 il pthread_t restituito è solo il puntatore a opaca struct pthread. È possibile cercare la definizione in nptl/descr.h.

Problemi correlati