Jump to content

Recommended Posts

Posted

Olá pessoal,

Hoje tive um teste de uma cadeira chamada Sistemas Operativos que basicamente abrange, nesta altura, multithreading/sincronização/race conditions/etc...

A meio do teste, numa alínea, passei cerca de uma hora a tentar resolver o exercício de uma maneira (a maneira que supostamente está correcta), mas sem sucesso. A minha questão é:

Tenho uma thread a correr, que modifica um vector (defini o vector como variável local, não sei se tería de ser feito de outra maneira) como um histograma. A ideia é a thread no final retornar o vector à main thread através de pthread_exit(&val) para o pthread_join respectivo. Como é que eu leio/imprimo os valores do array na main thread? Tentei todo o tipo de cast do valor actualizado do join mas sem sucesso.

Já agora, qual é a melhor maneira de resolver este problema usando sempre um retorno de pthread_exit para pthread_join?

Abraço

Posted

Um amostra do código ajudava a analisar mas uma coisa que não podes fazer é passar ponteiros para variáveis locais para fora da função. No mínimo terias de usar uma estrutura global às duas threads. Uma hipótese seria de alocares memória para o vector dentro da thread que o manipula e passar o ponteiro para esse vector através do pthread_exit. Na thread principal farias o que tivesses a fazer e libertarias a memória. Tipo:

/* Estrutura para passar vector */
struct vector
{
  int tamanho;
  char elementos[1];
}

/* Thread 1 */

void * thread1(void * arg)
{
  pthread_t t2;
  struct vector * tres;

  pthread_create(&t2,NULL,thread2,NULL);
  ...
  pthread_join(t2,&tres);
  ...
  free(tres,sizeof(vector) + (tres->tamanho - 1) * sizeof(char));
}

/* Thread 2 */

void * thread2(void * arg)
{
  struct vector * vec;

  vec = malloc(sizeof(vector) + (10 - 1) * sizeof(char));

  vec->tamanho = 10;
  vec->elementos[0] = 'A';
  vec->elementos[1] = 'K';
  ...
  pthread_exit(vec);
}

Atenção que se houvesse mais pares de threads a correr em 'simultâneo' seria preciso garantir que as funções 'malloc' e 'free' seriam reentrantes, ou então controlar o acesso a elas com um objecto de sincronização.

Se soubesses o tamanho do vector ao iniciar a execução da segunda thread poderias alocá-lo na primeira thread, passar o ponteiro através do último parâmetro do pthread_create e recebê-lo na segunda thread através do parâmetro da função. Para este efeito poderias usar uma variável local à thread 1.

Posted

Neste caso eu sabia qual seria o tamanho de vector, no entanto já passava para a thread uma estrutura como argumento. Tería de adicionar um vector à estrutura que passo à thread? Não percebi bem essa última solução que propuseste...

Já agora, o apontador recebido na função join não é do tipo void? Se enviasse o endereço de um vector, como é que o poderia tratar como um vector no thread principal?

Posted

a mim parece que pretendias mais isto :

struct {
  int size;
  int * array;
} Vector;

void * thread_proc(void * arg) {
  Vector * vector = arg;
  ... // fazer o que se tem que fazer no vector
  return vector;
}

int main() { // thread principal
  Vector * vector;
  pthread_t thread;
  ... // maloc's e afins para o vector
  pthread_create(&t, NULL, thread_proc, vector);
  pthread_join(&vector);
  ... // imprimir os valores do vector
  return 0;
}  
IRC : sim, é algo que ainda existe >> #p@p
Posted

Neste caso eu sabia qual seria o tamanho de vector, no entanto já passava para a thread uma estrutura como argumento. Tería de adicionar um vector à estrutura que passo à thread? Não percebi bem essa última solução que propuseste...

Poderias fazer assim :

struct estrutura
{
  int campo1;  /* Inicio dos campos da tua estrutura */
  int campo2;
  int campo3; /* Fim dos campos da tua estrutura */
  char vector[100];      /* Vector de tamanho imutável */
  /* ... ou ... */
  int tamanho;
  char * vector;  /* Vector de tamanho variável */
}
...
struct estrutura est;
pthread_t t2;
...
pthread_create(&t2,NULL,thread2,&est);

E na segunda thread :

void * thread2(void * arg)
{
  (struct estrutura *)arg->vector[0] = 'A';
  (struct estrutura *)arg->vector[1] = 'K';
  ...
}

Já agora, o apontador recebido na função join não é do tipo void? Se enviasse o endereço de um vector, como é que o poderia tratar como um vector no thread principal?

Um ponteiro de tipo void é compatível com qualquer outro; basta fazer o typecasting para o tipo apropriado.

Posted

No teste era pedido explicitamente para ser obtido o vector de cada uma das threads criadas para a thread main através do join, e era essa minha duvida. Alteração de variável global contava apenas metade...

Posted

No teste era pedido explicitamente para ser obtido o vector de cada uma das threads criadas para a thread main através do join, e era essa minha duvida. Alteração de variável global contava apenas metade...

Se 'vector de cada uma das threads' significa 'vector criado em cada uma das threads'  então terias de fazer como indiquei no primeiro post.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.