Code example – creating any number of threads

So, let's put it to the test: we will write a simple extension of our previous program, this time allowing the user to specify the number of threads to attempt to create within the process as the parameter (ch14/cr8_so_many_threads.c). The main function is as follows:

int main(int argc, char **argv)
{
long i;
int ret;
pthread_t tid;
long numthrds=0;

if (argc != 2) {
fprintf(stderr, "Usage: %s number-of-threads-to-create ", argv[0]);
exit(EXIT_FAILURE);
}
numthrds = atol(argv[1]);
if (numthrds <= 0) {
fprintf(stderr, "Usage: %s number-of-threads-to-create ", argv[0]);
exit(EXIT_FAILURE);
}

for (i = 0; i < numthrds; i++) {
ret = pthread_create(&tid, NULL, worker, (void *)i);
if (ret)
FATAL("pthread_create() failed! [%d] ", ret);
}
pthread_exit(NULL);
}

It's quite simple: we convert the string value the user passed as the first parameter to a numeric one with numthrds; we then have main loop numthrds times, invoking pthread_create(3) and thus creating a brand new thread upon each loop iteration! Once created, what do the new threads do? It's clear – they execute the code of the worker function. Let's take a look:

void * worker(void *data)
{
long datum = (long)data;
printf("Worker thread #%5ld: pausing now... ", datum);
(void)pause();


printf(" #%5ld: work done, exiting now ", datum);
pthread_exit(NULL);
}

Again, this is very simple: the worker threads just emit a printf(3)—which is useful because they print out their thread number—it's just the loop index of course. Then, they go to sleep via the pause(2) system call. (This system call is useful: it's a perfect blocking call; it puts the calling thread to sleep until a signal arrives.)

All right, let's try it out:

$ ./cr8_so_many_threads 
Usage: ./cr8_so_many_threads number-of-threads-to-create
$ ./cr8_so_many_threads 300
Worker thread # 0: pausing now...
Worker thread # 1: pausing now...
Worker thread # 2: pausing now...
Worker thread # 3: pausing now...
Worker thread # 5: pausing now...
Worker thread # 6: pausing now...
Worker thread # 4: pausing now...
Worker thread # 7: pausing now...
Worker thread # 10: pausing now...
Worker thread # 11: pausing now...
Worker thread # 9: pausing now...
Worker thread # 8: pausing now...

[...]

Worker thread # 271: pausing now...
Worker thread # 299: pausing now...
Worker thread # 285: pausing now...
Worker thread # 284: pausing now...
Worker thread # 273: pausing now...
Worker thread # 287: pausing now...
[...]
^C
$

It works (notice that we've truncated the output as there would be far too much to show in this book). Notice how the order in which the threads come alive and execute (emitting their printf) is random. We can see that the last thread we created is the one highlighted in bold—thread # 299 (0 to 299 is 300 threads).

Now, let's run it again, but this time ask it to create an impossibly large number of threads (we are currently trying this out on a guest VM with 1 GB of RAM):

$ prlimit --nproc ; ulimit -u
RESOURCE DESCRIPTION SOFT HARD UNITS
NPROC max number of processes 3710 3710 processes
3710
$ ./cr8_so_many_threads 40000

Worker thread # 0: pausing now...
Worker thread # 1: pausing now...
Worker thread # 2: pausing now...
Worker thread # 4: pausing now...

[...]

Worker thread # 2139: pausing now...
Worker thread # 2113: pausing now...
Worker thread # 2112: pausing now...
FATAL:cr8_so_many_threads.c:main:52: pthread_create() #2204 failed ! [11]
kernel says: Resource temporarily unavailable
$
Obviously, again, the results that you will see will depend on your system; we encourage the reader to try it out on different systems. Also, it's possible that the actual failure message may have appeared somewhere higher up in your Terminal window; scroll up to find it!
The name of the thread, as shown by ps(1), and so on, can be set via the pthread_setname_np(3) API; note that the np suffix implies that the API is non-portable (Linux-only).
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset