Find the answer to your Linux question:
Results 1 to 4 of 4
Hi all; I have a program called "Device Manager" to manange usb tokens for sending and recieving multiple data to/from them using shared memory method. Here is a piece of ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Sep 2009
    Posts
    28

    Problem with a MultiThreaded program in C++?


    Hi all;

    I have a program called "Device Manager" to manange usb tokens for sending and recieving
    multiple data to/from them using shared memory method.

    Here is a piece of "Device Manager" code:
    Code:
    int main()
    {
      pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    
      MY_ReqHandler *reqHandler = new MY_ReqHandler(&lock);
    
      MY_SharedMemory shMem;
    
      if(shMem.init())
          retlog((char*)"main", 1, 1);
    
      printf("sharedMem inited\n");
    
      int ret = shMem.create();
      printf("sharedMem create retVal %d\n", ret);
    
      ...
    }
    The type "MY_ReqHandler" is a C++ class that it's constructor initializes a token connected to the system as below:
    Code:
    MY_ReqHandler::MY_ReqHandler (pthread_mutex_t* trdlock)
    {
        enterLogger ((char*)"MY_ReqHandler::MY_ReqHandler");
     
        this->lock = trdlock;
    
        int ret = pthread_create(&hThread, NULL, run, (void*) this);
        if (ret)
          perror("pthread_create failed.");
    
        returnLogger((char*)"MY_ReqHandler::MY_ReqHandler", 0, 0);
        return;
    }
    And the Thread function as below:
    Code:
    void* run (void* obj)
    {
       enterLogger ((char*)"run (MY_ReqHandler)");
    
       pthread_mutex_lock(((MY_ReqHandler*)obj)->lock);
    
       ((MY_USBWrapper*)obj)->InitToken(1, VENDORID, PRODUCTID);
    
       pthread_mutex_unlock(((MY_ReqHandler*)obj)->lock);
    
       retlog((char*)"run (MY_ReqHandler)", 0, 0);
    }
    Here, "MY_USBWrapper" type is another class that one of it's member functions called "InitToken" initializes the token (including find and get a handle to it using "libusb" library inside a function with name "rawhid_open").

    The function "rawhid_open" that is called in "InitToken" is as below (It uses "libusb" library functions):
    Code:
    int rawhid_open(int max, int vid, int pid)
    {
       struct usb_bus *bus;
       struct usb_device *dev;
       struct usb_interface *iface;
       struct usb_interface_descriptor *desc;
       struct usb_endpoint_descriptor *ep;
       usb_dev_handle *u;
       uint8_t buf[1024];
       int i, n, ep_in, ep_out, count=0, claimed;
       hid_t *hid;
    
       if(first_hid)
          free_all_hid();
    
       printf("rawhid_open, max=%d\n", max);
    
       if(max < 1)
          return 0;
    
       usb_init();
    
       usb_find_busses();
         printf("usb_find_busses is called\n");
    
       usb_find_devices();
         printf("usb_find_devices is called\n");
    
       for (bus = usb_get_busses(); bus; bus = bus->next)
       {
            for (dev = bus->devices; dev; dev = dev->next)
            {
              if (vid > 0 && dev->descriptor.idVendor != vid)
                 continue;
    
              if (pid > 0 && dev->descriptor.idProduct != pid)
                 continue;
    
              if (!dev->config)
                 continue;
    
              if (dev->config->bNumInterfaces < 1)
                 continue;
    
              printf("device: vid=%04X, pid=%04X, with %d iface\n",
                 dev->descriptor.idVendor,
                 dev->descriptor.idProduct,
                 dev->config->bNumInterfaces);
    
              iface = dev->config->interface;
    
              u = NULL;
              claimed = 0;
              for(i=0; i<dev->config->bNumInterfaces && iface; i++, iface++)
              {
                 desc = iface->altsetting;
                 if (!desc)
                    continue;
    
                 printf("  type %d, %d, %d\n", desc->bInterfaceClass,
                    desc->bInterfaceSubClass, desc->bInterfaceProtocol);
    
                 if (desc->bInterfaceClass != 3)
                    continue;
                 if (desc->bInterfaceSubClass != 0)
                    continue;
    
                 if (desc->bInterfaceProtocol != 0)
                    continue;
    
                 ep = desc->endpoint;
                 ep_in = ep_out = 0;
                 for (n = 0; n < desc->bNumEndpoints; n++, ep++)
                 {
                    if (ep->bEndpointAddress & 0x80)
                    {
                       if (!ep_in)
                          ep_in = ep->bEndpointAddress & 0x7F;
    
                       printf("    IN endpoint %d\n", ep_in);
    
                    }
                    else
                    {
                       if (!ep_out)
                          ep_out = ep->bEndpointAddress;
    
                       printf("    OUT endpoint %d\n", ep_out);
                    }
                 }
    
                 if (!ep_in)
                    continue;
    
                 if (!u)
                 {
                    u = usb_open(dev);
    
                    if (!u)
                    {
                       printf("  unable to open device\n");
                       break;
                    }
                 }
    
                 printf("  hid interface (generic)\n");
    
                 if (usb_get_driver_np(u, i, (char *)buf, sizeof(buf)) >= 0)
                 {
                    printf("  in use by driver \"%s\"\n", buf);
    
                    if (usb_detach_kernel_driver_np(u, i) < 0)
                    {
                       printf("  unable to detach from kernel\n");
                       continue;
                    }
                 }
    
                 if (usb_claim_interface(u, i) < 0)
                 {
                    printf("  unable claim interface %d\n", i);
                    continue;
                 }
                 hid = (struct hid_struct *)malloc(sizeof(struct hid_struct));
                 if (!hid)
                 {
                    usb_release_interface(u, i);
                    continue;
                 }
    
                 hid->usb = u;
                 hid->ep_in = ep_in;
                 hid->ep_out = ep_out;
                 hid->open = 1;
                 add_hid(hid);
                 claimed++;
                 count++;
                 if (count >= max) return count;
              }
    
              if (u && !claimed) usb_close(u);
           }
        }
    
        return count;
    }
    Also, "MY_SharedMemory" class is intended for shared memory (IPC) operations and the member function "init" is as following:
    Code:
    MY_SharedMemory::init ()
    {
         fprintf(stderr, "All numeric input is expected to follow C conventions:\n");
         fprintf(stderr, "\t0x... is interpreted as hexadecimal,\n");
         fprintf(stderr, "\t0... is interpreted as octal,\n");
         fprintf(stderr, "\totherwise, decimal.\n");
    
        /* Get the key. */
         fprintf(stderr, "Enter key: ");
         scanf("%li", (long int*) &key);
    
        /* Get the size of the segment. */
         fprintf(stderr, "Enter size: ");
         scanf("%i", &size);
    
        /* Get the shmflg value. */
         fprintf(stderr, "Expected flags for the shmflg argument are:\n");
         fprintf(stderr, "\tIPC_CREAT = \t%#8.8o\n", IPC_CREAT);
         fprintf(stderr, "\tIPC_EXCL = \t%#8.8o\n", IPC_EXCL);
         fprintf(stderr, "\towner read =\t%#8.8o\n", 0400);
         fprintf(stderr, "\towner write =\t%#8.8o\n", 0200);
         fprintf(stderr, "\tgroup read =\t%#8.8o\n", 040);
         fprintf(stderr, "\tgroup write =\t%#8.8o\n", 020);
         fprintf(stderr, "\tother read =\t%#8.8o\n", 04);
         fprintf(stderr, "\tother write =\t%#8.8o\n", 02);
         fprintf(stderr, "Enter shmflg: ");
         scanf("%i", &shmflg);
         turn = 2;
    
        return 0;
    }
    But when I run the "Device Manager" executable file, I see the following result:
    Code:
    rawhid_open, max=1
    
    usb_find_busses is called
    
    
    All numeric input is expected to follow C conventions:
            0x... is interpreted as hexadecimal,
            0... is interpreted as octal,
            otherwise, decimal.
    
    Enter key: usb_find_devices is called
    
    device: vid=E854, pid=1230, with 1 iface
      type 3, 0, 0
        IN endpoint 1
        OUT endpoint 2
      hid interface (generic)
      in use by driver "usbfs"
    
    found rawhid device
    10
    Enter size: 10
    Expected flags for the shmflg argument are:
            IPC_CREAT =     00001000
            IPC_EXCL =      00002000
            owner read =    00000400
            owner write =   00000200
            group read =    00000040
            group write =   00000020
            other read =    00000004
            other write =   00000002
    Enter shmflg: 00001000
    sharedMem inited
    sharedMem create retVal 0
    sharedMem created
    As you see, in the middle of "rawhid_open" function (that is, after "usb_find_busses is called" message), the program switches to "Sharememory::init" function. I mean, the control of program
    exits from "rawhid_open" function or thread function of "MY_ReqHandler" constructor and the constructor returns.

    So that, the control goes to the rest of "Device manager" code at "shMem.init" part in:
    Code:
    All numeric input is expected to follow C conventions:
    ...
    And again, in the "Enter key:" part, switches to the rest of "MY_ReqHandler" constructor or
    "rawhid_open" function at "usb_find_devices is called" and ...

    My question is that why do I face this result?!

    I expect that at first, the "MY_ReqHandler" constructor or thread function runs completely (token to be initialized)and then "shMem.init" to be run!

    But I see the mentioned result!!

    Could you help me what the problem is?

    Unfortunately, I couldn't find the solution. help me please...

    TIA.

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,664
    Be patient. It will take awhile for me (or other folks) to find the time to analyze your code.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    Sep 2009
    Posts
    28
    Quote Originally Posted by Rubberman View Post
    Be patient. It will take awhile for me (or other folks) to find the time to analyze your code.
    Thanks a lot for your favor!

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,664
    Flush the output before you execute the scanf() functions. IE, fflush(stdout) to be sure that what you are seeing is what is really happening. Also, please provide the class definitions (headers) for MY_SharedMemory and MY_ReqHandler along with the code for their constructors.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •