Si scusate, ho omesso di spiegare che l'ordine in cui i thread scrivono non è importante, ma è fondamentale che ogni thread termini di scrivere i propri dati prima che un altro inizi a scrivere i suoi.
Ho provato a fare un pò di test con flock() e diversi file descriptor ottenuti dai thread (tutti che si riferiscono allo stesso file) e ho visto che tutto sembra funzionare.
Gli stessi test con flockfile() su un FILE * fallivano.
Ogni thread scrive i propri contenuti, e gli altri rimangono in coda; succede che i thread non scrivano necessariamente nell'ordine in cui sono invocati, ma ognuno scrive tutto quanto ha da scrivere prima di lasciare il posto al successivo, che fa la stessa cosa, e questo mi sta bene.
L'unica "difficoltà" sta nel fatto che con una fprintf() potevo fare direttamente output formattato su file; ora invece devo passare prima per una sprintf() per formattare la mia stringa, e poi passarla alla write().
Avevo inizialmente optato per gli stream offerti dalla libreria perchè ho letto che implementano intrinsecamente funzionalità di locking sul singolo stream; il MIO errore è stato quello di non capire subito che nel mio caso ogni thread apre il suo stream che, sebbene punti allo stesso file, è comunque differente dagli altri.
Agendo a basso livello sull'inode, sembra tutto risolto!
Grazie mille!