UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Observer dtrask
Observer
9,992 Views
Registered: ‎01-08-2014

petalinux pthread_create does not create new thread?

Jump to solution

The attached test program creates two detached threads. When I run the app and look at the processes in top, I cannot find individual entries for each thread. I tried typing H with top running, but this did not show me any additional information.

 

Does this mean that my pthreads are not being created as separate threads somehow?

 

A side effect of this is that if the ioctl call made by each thread is blocking, the entier process blocks until the ioctl returns, not just the thread that made the call. In the example below, I have worked around this by making the ioctl non-blocking, but now the process consumes the CPU, which is, of course, undesirable.

 

Thanks, in advance, for your help.

 

....

 

Well, for some reason, the system won't let me attach my source file, so here it is...

 

/*
 * Placeholder PetaLinux user application.
 *
 * Replace this with your application code
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <net/if.h>

#include <pthread.h>

#define FP_IOCTL_CMD  SIOCDEVPRIVATE + 14
#define PPS_IOCTL_CMD SIOCDEVPRIVATE + 1

void* wait_for_frame_pulse(void* arg) {

  int sd;

  int ioctl_result = 0;

  unsigned short fod = 0;

  int flags;

  // setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, "ad160", 5);
 
  struct ifreq ifr;

  memset(&ifr, 0, sizeof(struct ifreq));

  if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    
    printf("Socket error!\n");

    pthread_exit(NULL);
  }

  flags = fcntl(sd, F_GETFL, 0);

  /* if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) { */

  /*   printf("fcntl error! %s\n", strerror(errno)); */

  /*   pthread_exit(NULL); */
  /* } */


  strcpy(ifr.ifr_name, "ad160");

  printf("About to start frame pulse waiting cycle.\n");

  while (1) {

    /* printf("Waiting for frame pulse: %d\n", fod%200); */

    while (ioctl(sd, FP_IOCTL_CMD, &ifr) == -1) {

      if (errno != EWOULDBLOCK) {
    printf("AD16NET FP IOCTL failed: %s\n", strerror(errno));

    pthread_exit (NULL);
      }
    }

    /* printf("%d: GOT A FRAME PULSE!\n", fod%200); */

    ++fod;
  }

  pthread_exit(NULL);
}

void* wait_for_pulse_per_second(void* arg) {

  int sd;

  unsigned short sod = 0;

  int flags;

  // setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, "ad160", 5);
 
  struct ifreq ifr;

  memset(&ifr, 0, sizeof(struct ifreq));

  if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    
    printf("Socket error!\n");

    pthread_exit(NULL);
  }

  flags = fcntl(sd, F_GETFL, 0);

  /* if (fcntl(sd, F_SETFL, flags | O_NONBLOCK) < 0) { */

  /*   printf("fcntl error! %s\n", strerror(errno)); */

  /*   pthread_exit(NULL); */
  /* } */

  strcpy(ifr.ifr_name, "ad160");

  printf("About to start pulse per second waiting cycle.\n");

  while (1) {

    /* printf("Waiting for pulse per second: %d\n", sod); */

    while (ioctl(sd, PPS_IOCTL_CMD, &ifr) == -1) {

      if (errno != EWOULDBLOCK) {
    printf("AD16NET PPS IOCTL failed: %s\n", strerror(errno));

    pthread_exit (NULL);
      }
    }

    /* printf("%d: GOT A PPS!\n", sod); */

    ++sod;
  }

  pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
  int s, thread_id_pps, thread_id_fp;
  pthread_attr_t attr;

  struct timespec sleep_time;

  sleep_time.tv_sec = 1;
  sleep_time.tv_nsec = 0;


    printf("Hello, PetaLinux World!\n");
    printf("cmdline args:\n");
    while(argc--)
        printf("%s\n",*argv++);

    s = pthread_attr_init(&attr);

    if (s != 0) {
      perror("pthread_attr_init");
      exit(-1);
    }

    s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    if (s != 0) {
      perror("pthread_attr_setdetachstate");
      exit(-1);
    }

    s = pthread_create(&thread_id_fp,
               &attr,
               &wait_for_frame_pulse,
               NULL);

    if (s) {
      
      perror("pthread_create 1");
      exit (-1);
    }

    s = pthread_create(&thread_id_pps,
               &attr,
               &wait_for_pulse_per_second,
               NULL);

    if (s) {
      
      perror("pthread_create 2");
      exit (-1);
    }

    pthread_attr_destroy(&attr);

    /* wait_for_pulse_per_second(); */

    /* if (pthread_detach(thread_id_fp)) { */

    /*   perror("pthread_detach 1"); */
    /*   exit (-1); */
    /* } */

    /* if (pthread_detach(thread_id_pps)) { */

    /*   perror("pthread_detach 2"); */
    /*   exit (-1); */
    /* } */

#if 0
    int pid = fork();

    if (pid == 0) {
      wait_for_frame_pulse();
    }

    else if (pid > 0) {
      wait_for_pulse_per_second();
    }

    else {
      printf("fork() failed!\n");
      return 1;
    }
#endif

    pthread_exit(NULL);
    
    /* while (1) {nanosleep(&sleep_time, NULL);} */
    
    /* return 0; */
}

0 Kudos
1 Solution

Accepted Solutions
Observer dtrask
Observer
18,338 Views
Registered: ‎01-08-2014

Re: petalinux pthread_create does not create new thread?

Jump to solution

The issue of blocking is not because the pthreads are running in the same kernel thread. The issue was that I was trying to implement the ioctl in a network device. When you call ioctl on a socket, it apparently blocks the process until the ioctl completes.

 

I implemented a character device inside my network driver and used this to handle the ioctls instead. Once I did this, I found that only the calling thread blocked on ioctl, not the entire process.

 

0 Kudos
6 Replies
Scholar rfs613
Scholar
9,958 Views
Registered: ‎05-28-2013

Re: petalinux pthread_create does not create new thread?

Jump to solution

Try "top -H" or press "H" within top to show thread details. Unlike the old LinuxThreads model which had 1 process for every thread (plus a manager), under the current NPTL you will no longer see all the threads in the process list.

 

As for the ioctl(), it was mentioned in another thread recently, the kernel locks these against concurrent access by default.  A driver can implement an ioctl_unlocked() method if it doesn't want this.

 

0 Kudos
Observer dtrask
Observer
9,872 Views
Registered: ‎01-08-2014

Re: petalinux pthread_create does not create new thread?

Jump to solution

Actually, that's what I did. I typed "H" while top was running. I just tried it again, and pasted the result, below. Pressing "H" only refreshes the display, nothing else. Also, when I type "top -H" I get the Usage statement, which tells me that the "-H" is not supported.

 

Also, since this is a network device, it doesn't appear that there is an option to do an "ioctl_unlocked". The only ioctl specified in struct net_device_ops is "ndo_do_ioctl."

 

Of course, being a newb, I could be missing something.

 

Mem: 36824K used, 995664K free, 0K shrd, 734928K buff, 734976K cached
CPU: 13.2% usr 83.6% sys  0.0% nic  3.0% idle  0.0% io  0.0% irq  0.0% sirq
Load average: 2.39 0.68 0.23 3/45 882
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
  877   873 root     Z        0  0.0   1 96.6 [AD16NET_test]
  873     1 root     S     2956  0.2   0  0.0 -sh
  882   873 root     R     2956  0.2   0  0.0 top
  817     1 root     S     2852  0.2   0  0.0 /sbin/inetd
  857     1 root     S     2764  0.2   0  0.0 udhcpc -R -b -p /var/run/udhcpc.et
  875     1 root     S     2764  0.2   1  0.0 /sbin/httpd -h /srv/www
    1     0 root     S     1860  0.1   0  0.0 init [5]
  393     2 root     RW       0  0.0   1  0.0 [kworker/1:1]
    6     2 root     SW       0  0.0   0  0.0 [kworker/u4:0]
   17     2 root     SW       0  0.0   0  0.0 [kworker/u4:1]
    7     2 root     SW       0  0.0   1  0.0 [rcu_preempt]
   49     2 root     SW       0  0.0   0  0.0 [kworker/0:1]
    2     0 root     SW       0  0.0   1  0.0 [kthreadd]
    3     2 root     SW       0  0.0   0  0.0 [ksoftirqd/0]
    4     2 root     SW       0  0.0   0  0.0 [kworker/0:0]
    5     2 root     SW<      0  0.0   0  0.0 [kworker/0:0H]
    8     2 root     SW       0  0.0   0  0.0 [rcu_sched]
    9     2 root     SW       0  0.0   0  0.0 [rcu_bh]
   10     2 root     SW       0  0.0   0  0.0 [migration/0]
   11     2 root     SW       0  0.0   1  0.0 [migration/1]

 

 

0 Kudos
Scholar rfs613
Scholar
9,866 Views
Registered: ‎05-28-2013

Re: petalinux pthread_create does not create new thread?

Jump to solution

You've probably got the busybox version of "top" in that case. It does not support -H on the command line, but it does support "H" key at runtime:

# top --help
BusyBox v1.21.1 multi-call binary.

Usage: top [-b] [-nCOUNT] [-dSECONDS] [-m]

Provide a view of process activity in real time.
Read the status of all processes from /proc each SECONDS
and display a screenful of them.
Keys:
        N/M/P/T: show CPU usage, sort by pid/mem/cpu/time
        S: show memory
        R: reverse sort
        H: toggle threads, 1: toggle SMP
        Q,^C: exit

Options:
        -b      Batch mode
        -n N    Exit after N iterations
        -d N    Delay between updates
        -m      Same as 's' key

Your top output indicates that your AD16NET_test process is in Zombie state, were you expecting that? I suspect your thread(s) have already exited at this point. (Admittedly I have not read your source code in detail...)

0 Kudos
Observer dtrask
Observer
9,858 Views
Registered: ‎01-08-2014

Re: petalinux pthread_create does not create new thread?

Jump to solution

Ah, yes. I see now that it is the Busybox version of top. 

 

The main thread spawns two detached threads and then exits. Perhaps that's why it is showing as a Zombie, even though it is using nearly all the CPU? At any rate, I have verified that the two spawned threads are, in fact, running and calling the ioctl on the driver.

 

Curious that I can't seem to see anything but the main process in top.

 

0 Kudos
Observer dtrask
Observer
18,339 Views
Registered: ‎01-08-2014

Re: petalinux pthread_create does not create new thread?

Jump to solution

The issue of blocking is not because the pthreads are running in the same kernel thread. The issue was that I was trying to implement the ioctl in a network device. When you call ioctl on a socket, it apparently blocks the process until the ioctl completes.

 

I implemented a character device inside my network driver and used this to handle the ioctls instead. Once I did this, I found that only the calling thread blocked on ioctl, not the entire process.

 

0 Kudos
Explorer
Explorer
2,715 Views
Registered: ‎03-09-2017

Re: petalinux pthread_create does not create new thread?

Jump to solution

Hi , I have my program here that contains pthread and my petalinux is not building this app on the rootfs leaving an error and here is my code for the program involving pthread in it.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>


void *myfunc (void *myvar);



int main(int argc, char *argv[])
{
	pthread_t thread1,thread2;
	char *msg1 = "thread1";
	char *msg2 = "thread2";
	int ret1,ret2;

	ret1 = pthread_create(&thread1, NULL, myfunc, (void *) msg1);//pass address of the 		thread1,secondly NULL which is an attribute to be passed,thirdly the function to be passed 		and fourthly the arguments to be passed as arguments to the above function.
	
	ret2 = pthread_create(&thread2, NULL, myfunc, (void *) msg2);
	

	printf("Main function after pthread_create\n");	

	pthread_join(thread1, NULL);
	pthread_join(thread1, NULL);
	
	printf("first thread ret1 = %d\n", ret1);
	printf("Second thread ret2 = %d\n", ret2);
	return 0;

}


void *myfunc (void *myvar)
{
	//char *msg;
	//msg = (char *) myvar;

	int i;
	for(i = 0;i<10;i++)
	{
		printf("%s %d\n",(char*)myvar,i);
		sleep(1);

	}
	return NULL;

}

If i do the same using ARM cross compilers using the commands on my ubuntu

<path to the file location>$arm-xilinx-linux-gnueabi-gcc cmdthread.c -o cmdthread -pthread

and generate an image and send that image using ssh on to my zedboard bin and it is successfully running over my zedboard. Now i want to generate the boot and copy it to my sd card and want to make my zedboard to store this permanently. But here petalinux tool is not building it before i generate a boot.

 

0 Kudos