2 * Copyright (c) 2011, Joakim Johansson <jocke@tbricks.com>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
38 #include <sys/syscall.h>
45 STRUCTURE OF /proc/pid
46 A given directory /proc/pid contains the following entries.
47 A process can use the invisible alias /proc/self if it
48 wishes to open one of its own /proc files (invisible in the
49 sense that the name ``self'' does not appear in a directory
50 listing of /proc obtained from ls(1), getdents(2), or
54 Contains a prheader structure followed by an array of
55 lwpstatus structures, one for each active lwp in the process
56 (see also /proc/pid/lwp/lwpid/lwpstatus, below). The
57 prheader structure describes the number and size of the
58 array entries that follow.
60 typedef struct prheader {
61 long pr_nent; // number of entries
62 size_t pr_entsize; // size of each entry, in bytes
65 The lwpstatus structure may grow by the addition of elements
66 at the end in future releases of the system. Programs must
67 use pr_entsize in the file header to index through the
68 array. These comments apply to all /proc files that include
69 a prheader structure (lpsinfo and lusage, below).
74 int threads_runnable(unsigned int *threads_running)
76 const char *path = "/proc/self/lstatus";
77 int read_fd, retval = -1, i;
78 unsigned int running_count = 0;
81 lwpstatus_t *lwpstatus;
84 read_fd = open(path, O_RDONLY);
91 if (fcntl(read_fd, F_SETFL, O_NONBLOCK) != 0)
93 dbg_perror("fcntl()");
97 actual_read = read(read_fd, &prheader, sizeof(prheader_t));
99 if (actual_read != sizeof(prheader_t))
101 dbg_printf("read returned wrong number of bytes - %ld instead of %ld", actual_read, sizeof(prheader_t));
105 dbg_printf("read prheader, pr_nent = %ld, pr_entsize = %ld, sizeof(lwpstatus_t) = %ld",prheader.pr_nent, prheader.pr_entsize, sizeof(lwpstatus_t));
107 lwp_buffer = malloc(prheader.pr_nent * prheader.pr_entsize);
111 dbg_perror("malloc(prheader.pr_nent * prheader.pr_entsize)");
115 actual_read = read(read_fd, lwp_buffer, (prheader.pr_nent * prheader.pr_entsize));
117 if (actual_read != (prheader.pr_nent * prheader.pr_entsize))
119 dbg_printf("read returned wrong number of bytes - %ld instead of %ld", actual_read, prheader.pr_nent * prheader.pr_entsize);
124 for (i = 0; i < prheader.pr_nent; i++)
126 lwpstatus = (lwpstatus_t *) (lwp_buffer + (i * prheader.pr_entsize));
127 dbg_printf("lwp %d, syscall = %d", lwpstatus->pr_lwpid, lwpstatus->pr_syscall);
129 if (lwpstatus->pr_flags & PR_ASLEEP)
131 dbg_printf("lwp %d is sleeping",lwpstatus->pr_lwpid);
136 dbg_printf("lwp %d is running",lwpstatus->pr_lwpid);
142 *threads_running = running_count;
145 if (close(read_fd) != 0)
147 dbg_perror("close()");
153 #elif defined(__linux__)
160 This directory refers to the process accessing the /proc filesystem, and is identical to the /proc directory named by the process ID of the same process.
165 Status information about the process. This is used by ps(1). It is defined in /usr/src/linux/fs/proc/array.c.
166 The fields, in order, with their proper scanf(3) format specifiers, are:
172 The filename of the executable, in parentheses. This is visible whether or not the executable is swapped out.
175 One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging.
179 /proc/[number]/task (since kernel 2.6.0-test6)
180 This is a directory that contains one subdirectory for each thread in the process. The name of each subdirectory is the numerical thread ID of the thread (see gettid(2)). Within each of these subdirectories, there is a set of files with the same names and contents as under the /proc/[number] directories. For attributes that are shared by all threads, the contents for each of the files under the task/[thread-ID] subdirectories will be the same as in the corresponding file in the parent /proc/[number] directory (e.g., in a multithreaded process, all of the task/[thread-ID]/cwd files will have the same value as the /proc/[number]/cwd file in the parent directory, since all of the threads in a process share a working directory). For attributes that are distinct for each thread, the corresponding files under task/[thread-ID] may have different values (e.g., various fields in each of the task/[thread-ID]/status files may be different for each thread).
181 In a multithreaded process, the contents of the /proc/[number]/task directory are not available if the main thread has already terminated (typically by calling pthread_exit(3)).
186 read data from /proc/self/task/11019/stat: [11019 (lt-dispatch_sta) D 20832 10978 20832 34819 10978 4202560 251 3489 0 0 0 2 2 5 20 0 37 0 138715543 2538807296 13818 18446744073709551615 4194304 4203988 140736876632592 139770298610200 139771956665732 0 0 0 0 0 0 0 -1 2 0 0 0 0 0
191 #include <sys/types.h>
196 #define MAX_RESULT_SIZE 4096
198 static int _read_file(const char *path, char *result)
200 int read_fd, retval = -1;
203 read_fd = open(path, O_RDONLY);
206 dbg_perror("open()");
210 if (fcntl(read_fd, F_SETFL, O_NONBLOCK) != 0)
212 dbg_perror("fcntl()");
217 actual_read = read(read_fd, result, MAX_RESULT_SIZE);
220 dbg_printf("read %ld from %s", actual_read, path);
222 dbg_printf("read %zd from %s", actual_read, path);
225 if (actual_read == 0)
233 if (close(read_fd) != 0)
235 dbg_perror("close()");
242 int threads_runnable(unsigned int *threads_running)
246 const char *task_path = "/proc/self/task";
247 char thread_path[1024];
248 char thread_data[MAX_RESULT_SIZE+1];
249 char dummy[MAX_RESULT_SIZE+1];
252 unsigned int running_count = 0;
254 dbg_puts("Checking threads_runnable()");
256 if ((dip = opendir(task_path)) == NULL)
258 dbg_perror("opendir");
262 while ((dit = readdir(dip)) != NULL)
264 memset(thread_data, 0, sizeof(thread_data));
266 sprintf(thread_path, "%s/%s/stat",task_path, dit->d_name);
268 if (_read_file(thread_path, thread_data) == 0)
270 if (sscanf(thread_data, "%d %s %c", &pid, dummy, &state) == 3)
272 dbg_printf("The state for thread %s is %c", dit->d_name, state);
284 dbg_printf("Failed to scan state for thread %s (%s)", dit->d_name, thread_data);
289 if (closedir(dip) == -1)
294 dbg_printf("Running count is %d", running_count);
295 *threads_running = running_count;
302 int threads_runnable(unsigned int *threads_running)