MODIFICAÇÕES AO NÍVEL DO USUÁRIO
Ao nível do usuário, retirei a opção --turbo e adicionei a opção "-t, --threads NUM". Por default, apenas uma thread é disparada. Se o número de threads exceder o --threshold, o T50 chia. Se o número de threads ultrapassar o número de processadores (ou cores), um aviso é dado (mas deixa continuar), exceto se ultrapassar um máximo número de threads que atribuí arbitrariamente em src/include/defines.h. E, é claro, se o número de threads for <= 0, ele chia também.
Então as threads são criadas (com uma pilha de cerca de 16 kB de tamanho cada, para não sobrecarregar o sistema em caso de muitas
threads) e o loop de chamada dos módulos e envio dos pacotes é executado, em cada uma das threads.
MODIFICAÇÔES NO CÓDIGO
Muitas modificações foram feitas: __RND agora é uma função, não mais uma macro, já que random() não pode ser usada em ambientes
multithreaded e random_r() precisa manter o seu "estado" entre threads.
A função main() está mais limpinha, deixando a mágica para a função worker(), código principal das worker threads, em src/worker.c.
Algumas funções tiveram as suas listas de parâmetros reduzidas, recebendo agora apenas um ponteiro para o tipo "worker_data_t" (definido em include/typedefs.h). Isso é útil porque a única maneira de passar parâmetros para a "worker thread" é via um ponteiro "void", na chamada de pthread_create(). E ainda diminui o empilhamento de valores antes de chamadas.
Ao livrar-me do modo "turbo", livrei-me também das compilações condicionais usando __HAVE_TURBO__.
Minha idéia foi sempre isolar ao máximo cada função, pensando num ambiente multithreaded. Já no branch "master" as funções dos "módulos" nada mais fazem do que preencher o buffer que será usado por sendto(), por exemplo.
Neste código experimental, do jeito que está, as chamadas à sendto() são serializadas (ou seja, estão dentro de um mecanismo de sincronia de threads). Pode ser que isso não cause qualquer aumento de performance e, até mesmo, a piore um pouco. Mas, lembrem-se que este é um código experimental. Eis outra idéia de implementação (que tem o potencial de aumentar muito a performance).
A FUTURA IMPLEMENTAÇÂO
Pensei em criar um "cache" de pacotes, preenchidos pelas threads que chamam os "módulos" que enfilierariam os pacotes montados. Essas seriam as "worker threads". Ao mesmo tempo uma thread isolada (uma "dispatcher thread") iria colhendo os pacotes montados no cache e enviado-os, o mais rápido possível. Dessa maneira, sendto() não precisaria ficar cercada por um mecanismo de sincronia de threads. Este seria usado para evitar a exaustão de memória com o preenchimento do cache.
Essa implementação é mais complicada... Por favor me deem idéias! ;)
[]s
Fred