示例#1
0
int init_pipe(struct pipe* p, int n_dst, int q_depth, int buf_sz)
{
	int free_bufs = n_dst * q_depth;
	struct pipe_elem* msg_all = (struct pipe_elem*)malloc(
		free_bufs * (sizeof(msg_all[0]) + buf_sz));
	void* buf_ptr;
	int def_dst_n, i;

	// allocate bufs
	if (!msg_all)
		return -1;
	p->priv = (void*)msg_all;

	// initialize src
	if (init_queue(&p->src, free_bufs))
		goto free_buf;
	
	// initialize dst
	def_dst_n = sizeof(p->_dst) / sizeof(p->_dst[0]);
	p->dst = n_dst < def_dst_n ? &p->_dst[0] :
		(struct queue*)malloc(n_dst * sizeof(p->dst[0]));
	if (!p->dst)
		goto free_src;
	for (i = 0; i < n_dst; i++) {
		if (init_queue(&p->dst[i], q_depth))
			goto free_dst;
	}

	// init spinlock
	if (pthread_spin_init(&p->lock, PTHREAD_PROCESS_PRIVATE)) 
		goto free_dst;

	// push buffers onto src
	buf_ptr = (void*)&msg_all[free_bufs];
	for (i = 0; i < free_bufs; i++) {
		msg_all[i].buf = buf_ptr;
		msg_all[i].seq = 0;
		msg_all[i].ref_cnt = 0;
		buf_ptr += buf_sz;

		assert(!enqueue(&p->src, &msg_all[i]));
	}

	p->n_dst = n_dst;
	return 0;

free_dst : 
	for (i--; i >= 0; i--)
		close_queue(&p->dst[i]);
free_src : 
	close_queue(&p->src);
free_buf : 
	free(msg_all);
destroy_lock : 
	pthread_spin_destroy(&p->lock);
	
	return -1;
}
示例#2
0
void close_pipe(struct pipe* p)
{
	int i;
	
	for (i = 0; i < p->n_dst; i++)
		close_queue(&p->dst[i]);
	if (p->dst != &p->_dst[0])
		free(p->dst);
	close_queue(&p->src);
	free(p->priv);
	pthread_spin_destroy(&p->lock);
	
}
示例#3
0
int open_queue( void )
{
   struct msqid_ds qstat;
   int oldqid = qid;

   qstat.msg_qnum = 0;
   if( qid == -2 )
      keyval = ftok( IPC_KEY_FILE, 'm' );

   if( msgctl( qid, IPC_STAT, &qstat ) != -1 )
   {
      if( qstat.msg_qnum > 50 )
         close_queue(  );
   }

   if( ( qid = msgget( keyval, IPC_CREAT | 0666 ) ) == -1 )
   {
#if defined(__FreeBSD__)
      bug( "Unable to msgget keyval %ld.", keyval );
#else
      bug( "Unable to msgget keyval %d.", keyval );
#endif
      return -1;
   }

   if( oldqid != qid )
      oldqid = qid;

   return 1;
}
示例#4
0
int get_job (job_queue_t *q, job_t *j) {
	int index;
	
#ifdef NO_CACHE_COHERENCE
	__k1_rmb();
#endif

	if(q->begin == q->end && q->status == QUEUE_CLOSED)
		return 0;
	
	COND_VAR_MUTEX_LOCK(q->cond_var);
	while (q->begin == q->end) {
		switch (q->status) {
			case QUEUE_CLOSED:
				COND_VAR_MUTEX_UNLOCK(q->cond_var);
				return 0;
			case QUEUE_WAIT:
				#ifdef NO_CACHE_COHERENCE
				waiting_threads++; //see close_queue()
				COND_VAR_WAIT(q->cond_var);
				waiting_threads--;
				#else
				COND_VAR_WAIT(q->cond_var);
				#endif
				break;
			case QUEUE_OK:
				q->status = QUEUE_WAIT;
				reset_queue(q);
				COND_VAR_MUTEX_UNLOCK(q->cond_var);
				int jobs_added = q->repopulate_queue(q->repopulate_queue_par);
				COND_VAR_MUTEX_LOCK(q->cond_var);
				if (jobs_added)
					q->status = QUEUE_OK;
				else
					close_queue(q);
		}
	}

	index = q->begin++;
	COND_VAR_MUTEX_UNLOCK(q->cond_var);
	memcpy(j, &q->buffer[index].tsp_job, sizeof(job_t));
	return 1;
} 
示例#5
0
int main(int argc, char *argv[])
{
  pid_t pid;
  int i;

  int users_number;
  int service_probability;
  int text_message_probability;

  int status;
  int deadproc = 0; /* A counter of the already terminated user processes */
  int qid;
  int sw; /* Qid of the switch */
  int dest; /* Destination of the message */
  int olddest; /* Destination of the previous message */

  int queues[MAXCHILDS + 1]; /* Queue identifiers - 0 is the qid of the switch */

  int msg_sender;
  int msg_recipient;
  char msg_text[160];
  int msg_service;
  int msg_service_data;

  int t;
  int timing[MAXCHILDS + 1][2];

  int unreachable_destinations[MAXCHILDS + 1];

  char *padding = "                                                                      ";
  char text[160];

  messagebuf_t msg, in;

  /* Command line argument parsing */
  if(argc != 4){
    usage(argv);
    exit(0);
  }

  users_number = strtol(argv[1], NULL, 10);  
  service_probability = strtol(argv[2], NULL, 10);
  text_message_probability = strtol(argv[3], NULL, 10);
  

  if((users_number < MINCHILDS) || (users_number > MAXCHILDS)){
    usage(argv);
    exit(1);
  }

  if((service_probability < 0) || (service_probability > 100)){
    usage(argv);
    exit(0);
  }

  if((text_message_probability < 0) || (text_message_probability > 100)){
    usage(argv);
    exit(0);
  }

  printf("Number of users: %d\n", users_number);
  printf("Probability of a service request: %d%%\n", service_probability);
  printf("Probability of a text message: %d%%\n", text_message_probability);
  printf("\n");

  /* Initialize the random number generator */
  srandom(time(NULL));

  /* Switch queue initialization */
  sw = init_queue(255);
  
  /* Read the last messages we have in the queue */
  while(receive_message(sw, TYPE_TEXT, &in)){
    printf("%d -- S -- Receiving old text messages\n", (int) time(NULL), i);
  }

  /* Read the last messages we have in the queue */
  while(receive_message(sw, TYPE_SERVICE, &in)){
    printf("%d -- S -- Receiving old service messge\n", (int) time(NULL), i);
  }

  /* All queues are "uninitialized" (set equal to switch queue) */
  for(i = 0; i <= users_number; i++){
    queues[i] = sw;
    unreachable_destinations[i] = 0;
  }

  /* Create users */
  for(i = 1; i <= users_number; i++){
    pid = fork();

    if (pid == 0){
      srandom(time(NULL) + 1000*i);

      /* Initialize queue  */
      qid = init_queue(i);
      
      /* Read the last messages we have in the queue */
      while(receive_message(qid, TYPE_TEXT, &in)){
	printf("%s%d -- U %02d -- Receiving old text messages\n", padding, (int) time(NULL), i);
      }

      /* Read the last messages we have in the queue */
      while(receive_message(qid, TYPE_SERVICE, &in)){
	printf("%s%d -- U %02d -- Receiving old service messge\n", padding, (int) time(NULL), i);
      }

      /* Let the switch know we are alive */
      user_send_connect(i, sw);
      
      /* Let the switch know how to reach us */
      user_send_qid(i, qid, sw);
      
      /* Enter the main loop */
      while(1){
	sleep(rand()%MAX_SLEEP);

    	/* Check if the switch requested a service */
    	if(receive_message(qid, TYPE_SERVICE, &in)){
    	  msg_service = get_service(&in);

    	  switch(msg_service){

    	  case SERVICE_TERMINATE:
    	    /* Send an acknowledgement to the switch */
    	    user_send_disconnect(i, getpid(), sw);
	    
    	    /* Read the last messages we have in the queue */
    	    while(receive_message(qid, TYPE_TEXT, &in)){
    	      msg_sender = get_sender(&in);
    	      get_text(&in, msg_text);
    	      printf("%s%d -- U %02d -- Message received\n", padding, (int) time(NULL), i);
	      printf("%s                      Sender: %d\n", padding, msg_sender);
	      printf("%s                      Text: %s\n", padding, msg_text);
    	    }
	    
    	    /* Remove the queue */
    	    close_queue(qid);
    	    printf("%s%d -- U %02d -- Termination\n", padding, (int) time(NULL), i);
    	    exit(0);
    	    break;

    	  case SERVICE_TIME:
    	    user_send_time(i, sw);
    	    printf("%s%d -- U %02d -- Timing\n", padding, (int) time(NULL), i);
    	    break;

	  }
    	}

    	/* Send a message */
    	if(random_number(100) < text_message_probability){
    	  dest = random_number(users_number + 1);

    	  /* Do not send a message to the switch, to yourself and to the previous recipient */
    	  while((dest == 0) || (dest == i) || (dest == olddest)){
    	    dest = random_number(users_number + 1);
    	  }
    	  olddest = dest;

    	  printf("%s%d -- U %02d -- Message to user %d\n", padding, (int) time(NULL), i, dest);
	  sprintf(text, "A message from me (%d) to you (%d)", i, dest);
    	  user_send_text_message(i, dest, text, sw);
    	}
	
    	/* Check the incoming box for simple messages */
    	if(receive_message(qid, TYPE_TEXT, &in)){
    	  msg_sender = get_sender(&in);
    	  get_text(&in, msg_text);
	  printf("%s%d -- U %02d -- Message received\n", padding, (int) time(NULL), i);
	  printf("%s                      Sender: %d\n", padding, msg_sender);
	  printf("%s                      Text: %s\n", padding, msg_text);
    	}
      }
    }
  }
  
  /* Switch (parent process) */ 
  while(1){
    /* Check if some user is answering to service messages */
    if(receive_message(sw, TYPE_SERVICE, &in)){
      msg_service = get_service(&in);
      msg_sender = get_sender(&in);

      switch(msg_service){
      case SERVICE_CONNECT:
	/* A new user has connected */
	printf("%d -- S -- Service: connection\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);
	break;

      case SERVICE_DISCONNECT:
	/* The user is terminating */
	printf("%d -- S -- Service: disconnection\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);

	deadproc++;
	break;

      case SERVICE_QID:
	/* The user is sending us its queue id */
	msg_service_data = get_service_data(&in);
	printf("%d -- S -- Service: queue\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);
	printf("                   Qid: %d\n", msg_service_data);
	queues[msg_sender] = msg_service_data;
	break;

      case SERVICE_TIME:
	msg_service_data = get_service_data(&in);

	/* Timing informations */
	timing[msg_sender][1] = msg_service_data - timing[msg_sender][1];

	printf("%d -- S -- Service: timing\n", (int) time(NULL));
	printf("                   User: %d\n", msg_sender);
	printf("                   Timing: %d\n", timing[msg_sender][1]);

	/* The user is no more blocked by a timing operation */
	timing[msg_sender][0] = 0;
	break;
      }
    }

    /* Check if some user has connected */
    if(receive_message(sw, TYPE_TEXT, &in)){

      msg_recipient = get_recipient(&in);
      msg_sender = get_sender(&in);
      get_text(&in, msg_text);
      
      /* If the destination is connected */
      if(queues[msg_recipient] != sw){
	/* Send the message (forward it) */
	switch_send_text_message(msg_sender, msg_text, queues[msg_recipient]);
	
	printf("%d -- S -- Routing message\n", (int) time(NULL));
	printf("                   Sender: %d -- Destination: %d\n", msg_sender, msg_recipient);
	printf("                   Text: %s\n", msg_text);
      }
      else{
	unreachable_destinations[msg_sender] += 1;

	if (unreachable_destinations[msg_sender] > MAXFAILS) {
	  continue;
	}

	printf("%d -- S -- Unreachable destination\n", (int) time(NULL));
	printf("                   Sender: %d -- Destination: %d\n", msg_sender, msg_recipient);
	printf("                   Text: %s\n", msg_text);
	printf("                   Threshold: %d/%d\n", unreachable_destinations[msg_sender], MAXFAILS);

	if (unreachable_destinations[msg_sender] == MAXFAILS) {
	  printf("%d -- S -- User %d reached max unreachable destinations\n", (int) time(NULL), msg_sender);

	  switch_send_terminate(queues[msg_sender]);
	  
	  /* Remove its queue from the list */
	  queues[msg_sender] = sw;
	}
      }
      
      /* Randomly request a service to the sender of the last message */
      if((random_number(100)  < service_probability) && (queues[msg_sender] != sw)){
	if (random_number(100) < 40){
	  /* The user must terminate */
	  printf("%d -- S -- User %d chosen for termination\n", (int) time(NULL), msg_sender);

	  switch_send_terminate(queues[msg_sender]);

	  /* Remove its queue from the list */
	  queues[msg_sender] = sw;
	}
	else {
	  /* Check if we are already timing that user */
	  if(!timing[msg_sender][0]){
	    timing[msg_sender][0] = 1;
	    timing[msg_sender][1] = (int) time(NULL);
	    printf("%d -- S -- User %d chosen for timing...\n", timing[msg_sender][1], msg_sender);
	    switch_send_time(queues[msg_sender]);
	  }
	}
      }
    }
    else{
      if(deadproc == users_number){
	/* All childs have been terminated, just wait for the last to complete its jobs */
	waitpid(pid, &status, 0);

	/* Remove the switch queue */
	remove_queue(sw);

	printf("\n");
	printf("No more active users. Switch turns off.\n");
	
	/* Terminate the program */
	exit(0);
      }
    }
  }
}