Operating System - Linux
1751907 Members
5191 Online
108783 Solutions
New Discussion юеВ

C-programming - or how to display the number of threads per process

 
SOLVED
Go to solution
john korterman
Honored Contributor

C-programming - or how to display the number of threads per process

Hello C-programming experts and others!


dmesg on hpux 11.23 running SAP has produced this message a couple of times:
kernel table kthread is full

which I interpret as the system having run out of space for allocating threads.

As I thought it would be helpful to know the number of threads per process, I started searching for a tool for displaying this. A Google search soon found this c-code:


#include "sys/param.h"
#include "sys/pstat.h"
int main ( void )
{
struct pst_status * psa = NULL;
struct pst_status * prc = NULL;
struct pst_dynamic psd;
long nproc = 0;
long thsum = 0;
long i;
if ( pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1 )
(void)perror("pstat_getdynamic failed");
// Get the number of active processes from pst_dynamic
nproc = psd.psd_activeprocs;
psa = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));
// Read the info about the active processes into the array 'psa'
if ( pstat_getproc(psa, sizeof(struct pst_status), nproc, 0) == -1 )
(void)perror("pstat_getproc failed");
(void)printf("\n\n------------------------------------------------------------------------------");
(void)printf("\n %5s | %5s |%7s| %5s | %s", "PID", "UID", "Threads", "RSS", "Command");
(void)printf("\n------------------------------------------------------------------------------");

// Report the process info as required
prc = (struct pst_status *)psa;
for (i=0; i < nproc; i++)
{
(void)printf("\n %5ld | ", prc->pst_pid);
(void)printf("%5ld | ", prc->pst_uid);
(void)printf("%5ld | ", prc->pst_nlwps);
(void)printf("%5ld | ", prc->pst_rssize);
(void)printf("%s ", prc->pst_cmd);
thsum += prc->pst_nlwps;
++prc;
}

(void)printf("\n\n*** %ld processes, %ld threads running\n\n", nproc, thsum);
(void)free(psa);
(void)exit(0);
}



in a number of places, also on an HP site:
http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801/?ciid=060818f70fe0211018f70fe02110275d6e10RCRD



Knowing nothing about C-programming, I just tried inserting the above code in a file named

johnth.c on an ancient K360 running hpux 11.0 and performed

$ make ./johnth
make johnth
cc -O johnth.c -o johnth
/usr/ccs/bin/ld: (Warning) At least one PA 2.0 object file (johnth.o) was detected. The linked output may not run on a PA 1.x system.

and running the executable on the same machine produced some very convincingly looking output!



... then tried the same code on itanium 11.23:

$ make ./johnth
cc -O ./johnth.c -o ./johnth
(Bundled) cc: warning 922: "-O" is unsupported in the bundled compiler, ignored.


But consecutive execution of johnth produced this message:
pstat_getproc failed: Value too large to be stored in data type

followed by some not quite convincingly looking output; only swap shows a thread.

Can someone tell me how to adapt the C-code to itanium 11.23, or suggest other ways (Perl?) to achieve the same result, i.e. show the number of threads per process?


Regards,
John K.

it would be nice if you always got a second chance
12 REPLIES 12
Don Morris_1
Honored Contributor

Re: C-programming - or how to display the number of threads per process

Add:

#include

remove the cast of the return value of malloc() on the assignment to psa.

Because you didn't include the prototype for malloc(), the compiler has to assume it returns an int [32-bit integer] instead of a void * [pointer suitable for any pointer type]. They aren't the same, and what's likely happened is your memory address was truncated. As such, when you went to use it in the call to pstat_getproc(), the memory pointer you passed is garbage and the kernel knows that isn't writable. Hence it refuses to try and you get the error.

Also, I don't think this is your problem -- but in general on 11.22 and later, using -D_PSTAT64 when compiling 32-bit programs is a good idea. There are many pstat interfaces that use the 64-bit structures only, using it will have a little structure sizing cost but save you debugging time.
john korterman
Honored Contributor

Re: C-programming - or how to display the number of threads per process

Hello Don,

and thank you for your answer. I am not quite sure how to
"remove the cast of the return value of malloc() on the assignment to psa."

Can you tell a litte more about how to do this?

regards,
John K.
it would be nice if you always got a second chance
Don Morris_1
Honored Contributor
Solution

Re: C-programming - or how to display the number of threads per process

Sure.

I'm referring to the following line in your source:

psa = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));

Here you're taking the value returned from malloc() [which if you've included stdlib is now of type void *] and telling the compiler to instead treat it as a (struct pst_status *) [pointer to a pst_status structure]. This is referred to as an explicit cast of the return value.

Since void * is by definition a pointer representation suitable to be used for any other pointer type, psa [which is a (struct pst_status *)] can get an assignment from a void * without a cast.

So the line should just be:
psa = malloc(nproc * sizeof(struct pst_status));

The reason it is better not to explicitly cast the return value from malloc() [besides the fact that there's no need to] is that it hides the very compilation warning that would have told you malloc() wasn't properly described to the compiler. If you remove the cast, but don't include stdlib you should see warnings about converting an integer to a pointer implicitly... that is the compiler warning that since there is no definition for malloc() it has to assume it returns an int [this is in the Standard if I recall correctly] and you are assigning an int type to the (struct pst_status *) variable... which is not usually a good idea since the types have no guarantee of compatibility.

Specifically:
# cc -o malloc_trunc malloc_trunc.c
"malloc_trunc.c", line 15: warning #2513-D: a value of type "int" cannot be
assigned to an entity of type "struct pst_status *"
psa = malloc(nproc * sizeof(struct pst_status));
^

Hope that helps and is clear enough.
Dennis Handly
Acclaimed Contributor

Re: C-programming - or how to display the number of threads per process

>Don: remove the cast of the return value of malloc() on the assignment to psa.

Do not remove the cast, it is required by C++. But you do need and .

>Don: Since void* is by definition a pointer representation suitable to be used for any other pointer type, psa can get an assignment from a void* without a cast.

This is not true for C++. A cast is required for type safety. And a prototype is always required.

>warning #2513-D: a value of type "int" cannot be assigned to an entity of type "struct pst_status*"

Using the latest aCC6 compiler with +DD64 will now give a hard error.

>Don: using -D_PSTAT64 when compiling 32-bit programs is a good idea.

Yes, this fixes it.
Sandman!
Honored Contributor

Re: C-programming - or how to display the number of threads per process

The source code should look at the value of the psd_numkthreadsallocd metric obtained through the pstat_getdynamic() API to determine the max # of threads that have been used simultaneously so far. This is according to the nkthread(5) manpage.


#include
#include

main(void)
{
struct pst_dynamic dyn[1], *pdyn = dyn;
if (pstat_getdynamic(dyn, sizeof(struct pst_dynamic), 1, 0))
printf("max threads used concurrently so far %d\n",
pdyn->psd_numkthreadsallocd);
}
Dennis Handly
Acclaimed Contributor

Re: C-programming - or how to display the number of threads per process

Any reason you are using Fortran's prespacing or COBOL's AFTER ADVANCING for your printfs?
This is a no-no for C. (The \n should go at the end so your buffering works correctly for stderr.)

Ah, you forgot to tell google to not find poor coding style code. :-) Oh well, it is from DSPP.

>Sandman: The source code should look at the value of the psd_numkthreadsallocd

If you are going to compile with +DD32 and -D_PSTAT64 the format should be %lld. Similarly for most of John's: pst_pid pst_uid pst_nlwps pst_rssize
john korterman
Honored Contributor

Re: C-programming - or how to display the number of threads per process

Thank you very much for your responses,

but urgent work just arrived; I'll look at them later.

regards, John K.
it would be nice if you always got a second chance
john korterman
Honored Contributor

Re: C-programming - or how to display the number of threads per process

Hello again,

tried this:


a)
included
changed
psa = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));
to
psa = malloc(nproc * sizeof(struct pst_status));
and compiled using -D_PSTAT64
(Don's suggestion)
Result: no errors and shows for each process the number of threads


b)
included and .
and compiled using -D_PSTAT64
(Dennis' suggestion)
Result: no errors and showsfor each process the number of threads



c)
compiled the code supplied by Sandman!
Result: no errors, shows
"max threads used concurrently so far: "


a) and b) agree on the same number of threads (e.g. 432)
c) shows, a few seconds later on the same system, 828.


Thank you very much for your input. Points will be assigned later.

regards,
John K.


it would be nice if you always got a second chance
Sandman!
Honored Contributor

Re: C-programming - or how to display the number of threads per process

>a) and b) agree on the same number of threads (e.g. 432)
>c) shows, a few seconds later on the same system, 828

Output from c) is different as it shows the "high water" mark of the number of threads that have been simultaneously used. It is the allowable limit beyond which "kthread: table is full" messages start popping up in dmesg and syslog. See the URL below for details.

http://docs.hp.com/en/TKP-90202/re59.html

a) and b) show a snapshot of the process attributes like RSS, num of threads currently running etc. on the system while c) shows the total threads running on the system just prior to getting the "table is full" message. Code below shows both the snapshot of process attributes and the high water mark of the threads used so far.
==============================================================

#include
#include
#include

void main(void)
{
struct pst_status pst[1], *prc = pst;
struct pst_dynamic dyn[1], *pdyn = dyn;
int cnt, i=0, pc=0, tc=0;

printf("PID\tRSS\tTHREADS\tCOMMAND\n\n");
while (pstat_getproc(pst, sizeof(struct pst_status), 1, i))
{
printf("%ld\t%ld\t%ld\t%s\n",prc->pst_pid,prc->pst_rssize,prc->pst_nlwps,
prc->pst_cmd);
tc += prc->pst_nlwps;
i = prc->pst_idx + 1;
++pc;
}
printf("\n%d processes and %d threads running currently\n", pc, tc);
if (pstat_getdynamic(dyn, sizeof(struct pst_dynamic), 1, 0))
printf("max threads used concurrently so far %ld\n",
pdyn->psd_numkthreadsallocd);
}