Queue in two processes

  1. 3 weeks ago

    I am trying to use a queue_bmm in two processes:

    1. Queue server: I create a share memory region where I store the queue state, the elements and the data to share.
    2. Queue client: I want to get the share data using lfds710_queue_bmm_dequeue. But I sometimes get a segmentation fault, others the program doesn't do anything, and also sometimes give me a bad shared data (0, and I should get 5,6,7...).

    My code is the next:

    The code for the "queue server":

    #include <stdio.h>
    #include <string.h>
    #include "liblfds710.h"
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <sys/stat.h>      
    #include <fcntl.h>
    
    
    struct shared_queue
    {
      struct lfds710_queue_bmm_state aqbmms; //address queue state
      struct lfds710_queue_bmm_element qbmme[4];
      int data;
    };
    
    struct shared_queue *squeue;
    
    void share_data_queue(){
    	 int c_fd; //file descriptor
    	
    	if ((c_fd=open("/data/local/tmp/queue",O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH)) == -1) {
    		printf ("error in open\n");
    	}
    	if (ftruncate(c_fd,sizeof(struct shared_queue)) == -1) {
    		 printf ("error in ftruncate\n");
    	}
    	if ((squeue=mmap(0,sizeof(struct shared_queue),PROT_READ|PROT_WRITE,MAP_SHARED,c_fd,0)) == MAP_FAILED) {
    	  printf ("error in mmap\n");
    	}
    }//share_data_queue
    
    
    int main()
    {
    	share_data_queue();
    
    	LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
     	lfds710_queue_bmm_init_valid_on_current_logical_core( &squeue->aqbmms, squeue->qbmme, 4, NULL );	
    
    	int i = 0;
    	//int element;
    	squeue->data=5;
            
    	while (i<4){
      		lfds710_queue_bmm_enqueue( &squeue->aqbmms, NULL,  (void *) squeue->data );
    		//lfds710_queue_bmm_dequeue( &squeue->aqbmms, NULL,  (void *) &element );
    		//printf("Shared value:%d\n", element);
    		i++;
    		squeue->data = squeue->data+1;
    	}
    	sleep(20);
    	lfds710_queue_bmm_cleanup( &squeue->aqbmms, NULL );
    	return 0;
    }

    The code for the "queue client":

    #include <stdio.h>
    #include <string.h>
    #include "liblfds710.h"
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <sys/stat.h>      
    #include <fcntl.h>
    
    
    struct shared_queue
    {
      struct lfds710_queue_bmm_state aqbmms; //address queue state
      struct lfds710_queue_bmm_element qbmme[4];
      int data;
    };
    
    
    struct shared_queue *squeue;
    
    void share_data_queue(){
    	  int c_fd; //file descriptor
    	  //int e_fd;
    
    	//struct lfds710_queue_bmm_state qbmms;
    	if ((c_fd=open("/data/local/tmp/queue",O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH)) == -1) {
    		printf ("error in open\n");
    	}
    	if (ftruncate(c_fd,sizeof(struct shared_queue)) == -1) {
    		 printf ("error in ftruncate\n");
    	}
    	if ((squeue=mmap(0,sizeof(struct shared_queue),PROT_READ|PROT_WRITE,MAP_SHARED,c_fd,0)) == MAP_FAILED) {
    	  printf ("error in mmap\n");
    	}
    }//share_data_queue
    
    
    
    int main()
    {
    	//struct lfds710_queue_bmm_element qbmme[4];	
    	
    	share_data_queue();
    	int i = 0;	
    	int element;
    	printf("before loop\n");
    	while (i<4){
      		lfds710_queue_bmm_dequeue( &squeue->aqbmms, NULL,  (void *) &element );
    		printf("Shared value:%d\n", element); //OJO
    		i++;
    	}
    
    	return 0;
    }// main
  2. admin

    Feb 28 Administrator
    Edited 3 weeks ago by admin

    Hej, aperez.

    I'm just on my way home now, and I'll look at the code and so on properly once I'm here.

    One thing I would say now though, from just having run my eyes over the code, is that the BMM queue is a *relaxed* queue. By this word I mean to say that although once an enqueue call has returned, an element definitely will be enqueued and in the expected order, it does *not* mean that element will yet be seen by *dequeuers in other threads*.

    So - in theory - you could have one thread sitting there enqueuing all day long, and another thread which is dequeuing never returning anything. (This obviously doesn't happen in practise - it's an extreme example - but much shorter term versions of it are happening for every enqueue; it takes a certain time for information to propagate, and there are no guarantees from the hardware about how long this will take.)

    What it means is that you must *always* check the return value from the dequeue() function. This is because no matter how many elements you may have enqueued, they may not yet be visible to the dequeue thread.

  3. admin

    Feb 28 Administrator
    Edited 3 weeks ago by admin

    The virtual memory addresses being used in the various processes have to be identical.

    The data structures are not internally using offsets - they use pointers. I have thought about using offsets, but it's work which has had less importance than other work, in part since mmap() with a specific virtual memory address does work.

    Call mmap() with a first argument which specifies a particular virtual memory addresses.

 

or Sign Up to reply!