Hace algún tiempo, escribí el post Solaris: Buceando en el Kernel con libkvm sobre cómo podemos utilizar la librería libkvm para crear nuestros propios comandos y que dichos comandos realicen cosas que hasta ahora no podíamos hacer.
No tenemos que perder nunca la perspectiva de que administramos sistemas, no nos dedicamos a crear software, pero creo que un buen administrador de sistemas, debe ser capaz de crear sus propios comandos, Unix tiene miles de comandos y continuamente salen más utilidades que nos ayudan en nuestro día a día, pero hace tiempo ya que he descubierto que siempre se vamos a necesitar algo que no podemos hacer con los comandos convencionales. Este post es meramente educativo, no pretendo que compiléis estos programas y los pongáis en producción, el objetivo es enseñar lo fácil que es, con unos conocimientos mínimos de C y algo del Kernel de Solaris, construir comandos a medida que nos pueden ayudar bastante en nuestro día a día.
Nota :Antes de seguir, sería interesante leer el post Solaris: Buceando en el Kernel con libkvm
Mezclando truss y prstat
Mucha gente utiliza habitualmente las herramientas truss y prstat, ambas son muy potentes si se saben utilizar.
- truss, permite tracear las señales y las llamadas a sistema que ejecuta un proceso.
- prstat, devuelve información estadística sobre los procesos que están corriendo en el sistema.
Por ahora solo hemos hablado de procesos, pero actualmente lo que nos vamos a encontrar en casi todos los sistemas son aplicaciones Java que lanzan varias decenas de threads, por lo que debemos saber no qué están haciendo los procesos sino también qué están haciendo los threads de un proceso. Tanto truss como prstat, nos permiten trabajar a nivel de threads. Por ejemplo, utilizando el parámetro -L en el comando prstat.
# prstat -L -p 10206 PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID 10206 user1 1635M 1499M sleep 11 10 1:39:47 2.1% java/2 10206 user1 1635M 1499M sleep 0 10 0:02:12 1.3% java/88 10206 user1 1635M 1499M sleep 0 10 0:02:08 1.3% java/84 10206 user1 1635M 1499M sleep 0 10 0:02:19 1.3% java/87 10206 user1 1635M 1499M sleep 0 10 0:02:20 1.3% java/81 10206 user1 1635M 1499M sleep 0 10 0:02:08 1.2% java/85 10206 user1 1635M 1499M sleep 10 10 0:02:13 1.2% java/86 10206 user1 1635M 1499M sleep 0 10 0:02:06 1.2% java/82 10206 user1 1635M 1499M sleep 10 10 0:02:25 1.2% java/83 10206 user1 1635M 1499M sleep 10 10 0:01:26 0.5% java/62 10206 user1 1635M 1499M sleep 13 10 0:00:41 0.2% java/59 10206 user1 1635M 1499M sleep 59 10 0:00:40 0.2% java/60 10206 user1 1635M 1499M sleep 27 10 0:01:06 0.2% java/67 10206 user1 1635M 1499M sleep 18 10 0:00:14 0.1% java/23125 10206 user1 1635M 1499M sleep 59 10 0:00:46 0.0% java/9 10206 user1 1635M 1499M sleep 29 10 0:00:00 0.0% java/23440 10206 user1 1635M 1499M sleep 29 10 0:00:27 0.0% java/44 10206 user1 1635M 1499M sleep 18 10 0:00:00 0.0% java/23439 10206 user1 1635M 1499M sleep 29 10 0:00:00 0.0% java/30 10206 user1 1635M 1499M sleep 29 10 0:00:00 0.0% java/29 10206 user1 1635M 1499M sleep 29 10 0:00:00 0.0% java/28 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/27 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/26 10206 user1 1635M 1499M sleep 29 10 0:00:00 0.0% java/25 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/24 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/23 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/22 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/21 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/20 10206 user1 1635M 1499M sleep 0 10 0:00:00 0.0% java/19 Total: 1 processes, 156 lwps, load averages: 3.18, 3.14, 2.92
En el comando truss por defecto nos devuelve el ID del threads en la salida.
# truss -p 10206 /10: poll(0x190FFD58, 0, 50) = 0 /10: poll(0x190FFD58, 0, 50) = 0 /2: lwp_cond_wait(0x00038070, 0x00038058, 0x79E7FD30) Err#62 ETIME /10: poll(0x190FFD58, 0, 50) = 0 /10: poll(0x190FFD58, 0, 50) = 0 /10: poll(0x190FFD58, 0, 50) = 0 /105: poll(0x0DD79CC8, 27, 10000) = 1 /105: lwp_unpark(122, 1) = 0 /122: lwp_park(0x00000000, 0) = 0 /10: poll(0x190FFD58, 0, 50) = 0 /10: poll(0x190FFD58, 0, 50) = 0 /105: poll(0x0DD79CC8, 27, 10000) = 1 ...
Sería bastante interesante disponer de un comando que nos permitiese conocer, por un lado los threads que se están ejecutando y qué están haciendo estos threads, una mezcla de los comandos truss y prstat. Este nuevo comando lo podemos programar nosotros mismos utilizando la librería libkvm, podría ser algo parecido a esto.
# lwpstat -p 10206 Pid: 10206 PPid: 7670 Threads: 155
Args: /bea/jdk142_05/bin/java -server -verbose:gc -ms1280m -mx1280m -Xs
t_tid time t_state wchan/wchan0 sobj_type #w t_ts syscall
----- -------- ------- --------------------------- --------- --- ---------------------------------------------------
10 00:00:00 SLEEP 0x300.../0x0000000 CV 0 0x3002bba81b8 poll(0x190ffd58, 0x0,...)
105 00:00:00 SLEEP 0x317.../0x0000000 CV 0 0x395b38f9670 poll(0xdd79cc8, 0x1b,...)
123 00:00:00 SLEEP 0x302.../0x0000000 CV 0 0x300e5bc2b78 lwp_park(0x0, 0x0,...)
130 00:00:00 SLEEP 0x32b.../0x0000000 CV 0 0x300818c1050 lwp_park(0x0, 0x0,...)
64 00:00:00 SLEEP 0x000.../0x395b391 USER 0 0x3021be28e50 lwp_cond_wait(0x10ba220, 0x10ba208, ...)
115 00:00:00 SLEEP 0x300.../0x0000000 CV 0 0x300418f29d8 lwp_park(0x0, 0x0, ...)
122 00:00:00 SLEEP 0x300.../0x0000000 CV 0 0x3021be28eb8 lwp_park(0x0, 0x0,...)
75 00:00:00 SLEEP 0x000.../0x395b391 USER 0 0x3002b81cc38 lwp_cond_wait(0xfe77e8, 0xfe77d0, ...)
144 00:00:00 SLEEP 0x300.../0x0000000 CV 0 0x3002b820340 read(0x634560,0x634548, ...)
80 00:00:00 SLEEP 0x0000081167c/0x395b391 USER 0 0x495f627a838 lwp_cond_wait(0x811678, 0x811660, ...)
76 00:00:00 SLEEP 0x00000fe60cc/0x395b391 USER 0 0x3003214bc08 lwp_cond_wait(0xfe60c8, 0xfe60b0, ...)
2 00:00:00 SLEEP 0x00000038074/0x395b391 USER 0 0x300013190b0 lwp_cond_wait(0x38070, 0x38058, ...)
79 00:00:00 SLEEP 0x0000080fc0c/0x395b391 USER 0 0x3002b81d2b8 lwp_cond_wait(0x80fc08, 0x80fbf0, ...)
77 00:00:01 SLEEP 0x00001256864/0x395b391 USER 0 0x302156b4888 lwp_cond_wait(0x1256860, 0x1256848, ...)
114 00:00:01 SLEEP 0x32b7824acfe/0x0000000 CV 0 0x3002b81c550 lwp_park(0x0, 0x0, ...)
78 00:00:01 SLEEP 0x00001256974/0x395b391 USER 0 0x3dd07f86070 lwp_cond_wait(0x1256970, 0x1256958, ...)
106 00:00:01 SLEEP 0x300630412de/0x0000000 CV 0 0x3021be29810 lwp_park(0x0, 0xdc7bd00, ...)
131 00:00:01 SLEEP 0x301f83e5b7e/0x0000000 CV 0 0x3002bba88a0 lwp_park(0x0, 0x0, ...)
86 00:00:01 SLEEP 0x00000fe74ac/0x395b391 USER 0 0x3021be29878 lwp_cond_wait(0xfe74a8, 0xfe7490, ...)
171 00:00:02 SLEEP 0x3005f13ea1e/0x0000000 CV 0 0x300818c0de0 poll(0x37ff0, 0x0, ...)
83 00:00:02 SLEEP 0x00000c7cc44/0x395b391 USER 0 0x32bccb88148 lwp_cond_wait(0xc7cc40, 0xc7cc28, ...)
88 00:00:02 SLEEP 0x00000fe5f6c/0x395b391 USER 0 0x30061483468 lwp_cond_wait(0xfe5f68, 0xfe5f50, ...)
40 00:00:02 SLEEP 0x000007d0b34/0x395b391 USER 0 0x3020108f668 lwp_cond_wait(0x7d0b30, 0x7d0b18, ...)
41 00:00:02 SLEEP 0x000007d1724/0x395b391 USER 0 0x300318c1c18 lwp_cond_wait(0x7d1720, 0x7d1708, ...)
42 00:00:02 SLEEP 0x00000b217d4/0x395b391 USER 0 0x3003e9b0c30 lwp_cond_wait(0xb217d0, 0xb217b8, ...)
72 <1m, 15 <5m, 30 <30m, 3 <1h, 1 <5h, 34 >5h
Tendríamos una comando que nos daría una salida parecida a la de prstat, es decir todos los threads que está ejecutando el proceso, con la llamada a sistema que está ejecutando cada thread. Este comando nos permitiría ver con un sencillo pantallazo, qué están haciendo los threads de nuestro proceso.
El comando lwpstat
El código fuente de nuestro nuevo comando lwpstat es un sencillo programa en C (lwpstat.c), que utiliza algunas de las funciones de la librería libkvm para visualizar qué está haciendo cada uno de los threads de nuestros procesos. El algoritmo es extremadamente sencillo:
for(;;)
{
kvm_p=kvm_open()
...
pproc=kvm_getproc(kvm_p,npid)
...
read_thread_info(kvm_p,pproc,nthreads,p_thread_info,nlwp_time)
...
kvm_close(kvm_p);
....
Presentar los datos.
}
Un bucle en el que se abre el fichero que vamos a leer, en nuestro caso es /dev/kmem, la imagen del espacio de direcciones del Kernel, luego se optiene un puntero a la estructura de datos de nuestro proceso. Mediante la función read_thread_info se lee la información del todos los threads del proceso. Una vez que hemos terminado de leer la información, cerramos el acceso al fichero /dev/kmem con la función kvm_close(). Por último, se presenta la información de los threads. La función encargada de leer la información del thread, únicamente extrae la información de una estrutura de datos de tipo kthread_t, podemos ver como está implementada esta estructura de datos en el fichero /usr/include/sys/thread.h, de todos los campos, nos interesa t_sysnum, que contiene el número de la última llamada a sistema que ha ejecutado el thread.
typedef struct _kthread {
...
uint_t t_pctcpu; /* %cpu at last clock_tick(), binary */
/* point at right of high-order bit */
short t_sysnum; /* system call number */
kcondvar_t t_delay_cv;
kmutex_t t_delay_lock;
...
} kthread_t;
Si echáis un ojo al código fuente y al fichero /usr/include/sys/thread.h es sencillo entender qué estamos obteniendo de la estructura kthread_t.
IMPORTANTE: algunos de los datos de la estructura kthread_t están controlados por mutex, en nuestro ejemplo no estamos haciendo uso de dichos mutex, por lo que a veces podemos encontrarnos que no tenemos acceso a dichos datos, la explicación a esta forma de trabajar es sencilla, no queremos que nuestro programa entorpezca la ejecución normal de un proceso, por lo que nos limitamos únicamente a leer la información.
El comando lwpfd
Este es una variante del comando lwpstat, que implementa el acceso a los ficheros. Con lwpfd podemos conocer en cada momento cuales son los ficheros con los que está trabajando un thread en concreto. Todos los threads de un proceso tienen acceso a los descriptores de ficheros del proceso y esto lo podemos conocer utilizando el comando pfiles, lo que no nos ofrece pfiles es el fichero con el que está trabajando cada thread. El algoritmo es exactamente el mismo que el de comando lwpstat.
lwpfd utiliza el campo t_activefd, de la estructura de datos kthread_t. El campo t_activefd es un array con la lista de ficheros activos en el thread.
typedef struct _kthread {
...
struct _afd t_activefd; /* active file descriptor table */
...
} kthread_t;
Este es un ejemplo de la salida del comando lwpfd.
#lwpfd -p 12006 Pid: 12006 PPid: 10628 Threads: 91
Args: /bea/jdk142_05/bin/java -server -verbose:gc -Xloggc:/logs
t_tid time t_state syscall
----- -------- ------- --------------------------------------
20 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 102: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52579 R:192.168.0.1:1521 State:CONNECTED
21 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 30: R[0] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52628 R:192.168.0.1:1521 State:CONNECTED
26 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 92: R[0] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52576 R:192.168.0.1:1521 State:CONNECTED
33 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 58: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:47410 R:192.168.0.1:1521 State:CONNECTED
35 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 45: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:57898 R:192.168.0.1:1521 State:CONNECTED
36 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 67: R[0] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:46341 R:192.168.0.1:1521 State:CONNECTED
39 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 62: R[0] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:44885 R:192.168.0.1:1521 State:CONNECTED
40 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 52: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:53076 R:192.168.0.1:1521 State:CONNECTED
42 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 60: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:48419 R:192.168.0.1:1521 State:CONNECTED
54 00:00:00 SLEEP lwp_mutex_enter(0xee988, 0x1, ...)
55 00:00:00 SLEEP lwp_mutex_enter(0xee988, 0x1, ...)
56 00:00:00 SLEEP poll(0xee988, 0x1, ...)
59 00:00:00 SLEEP lwp_cv_wait(0x10fd748, 0x10fd730, ...)
880 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 65: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52192 R:192.168.0.1:1521 State:CONNECTED
10 00:00:00 SLEEP poll(0x214ffd58, 0x0, ...)
876 00:00:00 SLEEP lwp_cv_wait(0x4e2038, 0x4e2020, ...)
38 00:00:00 SLEEP read(0x37dd8, 0x0, ...)
FD 73: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52190 R:192.168.0.1:1521 State:CONNECTED
27 00:00:00 SLEEP read(0xcd0bb0, 0xcd0b98, ...)
FD 100: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52569 R:192.168.0.1:1521 State:CONNECTED
90 00:00:00 SLEEP accept(0x37dd8, 0x0, ...)
FD 42: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:172.16.85.18:8100 R:0.0.0.0:0 State:LISTEN
32 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 85: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:52339 R:192.168.0.1:1521 State:CONNECTED
37 00:00:00 SLEEP read(0xeecd0, 0x1, ...)
FD 51: R[1] SOCK AF_INET mtime: Type:SOCK_STREAM L:0.0.0.0:50850 R:192.168.0.1:1521 State:CONNECTED
9 00:00:00 SLEEP lwp_cv_wait(0x382f8, 0x382e0, ...)
67 00:00:00 SLEEP lwp_cv_wait(0x9a0f68, 0x9a0f50, ...)
69 00:00:00 SLEEP lwp_cv_wait(0x48d858, 0x48d840, ...)
2 00:00:00 SLEEP lwp_cv_wait(0x37e58, 0x37e40, ...)
3 00:00:00 SLEEP lwp_cv_wait(0xedfc0, 0xedfa8, ...)
4 00:00:00 SLEEP lwp_cv_wait(0xee710, 0xee6f8, ...)
57 <1m, 8 <5m, 26 <30m, 0 <1h, 0 <2h, 0 >5h
IMPORTANTE: algunos de los datos de la estructura kthread_t están controlados por mutex, en nuestro ejemplo no estamos haciendo uso de dichos mutex, por lo que a veces podemos encontrarnos que no tenemos acceso a dichos datos, la explicación a esta forma de trabajar es sencilla, no queremos que nuestro programa entorpezca la ejecución normal de un proceso, por lo que nos limitamos únicamente a leer la información.
Ficheros
Estos son los distintos ficheros con los que puedes compilar los comando lwpstat y lwpfd.
- lwpstat.c, código fuente del comando lwpstat
- lwpfd.c, código fuente del comando lwpfd
- sysc.c, código fuente con la función encargada de leer la lista de llamadas de sistema del fichero /etc/name_to_sysnum
- sysc.h, fichero de cabecera para las funciones de sysc.c
Makefile
KBIT= 64
FLAGS = -m$(KBIT)
LIBS = -lkvm
OPTIONS = $(FLAGS) $(LIBS)
BIN =
CC= gcc
all: compile
compile: lwpstat.o lwpfd.o sysc.h sysc.o
$(CC) -o lwpstat $(OPTIONS) lwpstat.o sysc.o
$(CC) -o lwpfd $(OPTIONS) lwpfd.o sysc.o
sysc.o: sysc.c
$(CC) -c sysc.c $(FLAGS) -o sysc.o
lwpstat.o: lwpstat.c sysc.h
$(CC) -c lwpstat.c $(FLAGS) -o lwpstat.o
lwpfd.o: lwpfd.c sysc.h
$(CC) -c lwpfd.c $(FLAGS) -o lwpfd.o
Conclusión
Este post, solo pretende ser un ejemplo de las posibilidad que tenemos de acceder a información en nuestro sistema si utilizamos herramientas como la librería libkvm. La verdad es que las posibilidades son infinitas y en entornos donde existen procesos que lanzan threads, conocer qué están haciendo cada uno de los threads es un objetivo importante para nosotros como administradores de sistemas. Herramientas como lwpstat y lwpfd, nos permiten de forma rápida conocer qué están haciendo los threads de un proceso.
En el siguiente ejemplo, podemos ver como hay varios threads intentando acceder a un mutex, por lo que podemos tener un problema de bloqueos.
Pid: 12006 PPid: 10628 Threads: 91
Args: /bea/jdk142_05/bin/java -server -verbose:gc -Xloggc:/logs
kvm_read: Error leyendo t_sobj_ops
t_tid time t_state wchan/wchan0 sobj_type #w t_ts syscall
----- -------- ------- --------------------------- --------- --- ------------- --------------------------------------
2 00:00:00 ONPROC 0x00000000000/0x00000000000 USER 0 0x3004e8c2a28 nosys(0x37e58, 0x37e40, ...)
10 00:00:00 SLEEP 0x3003f6755be/0x00000000000 CV 0 0x30071dcddb0 poll(0x214ffd58, 0x0, ...)
52 00:00:04 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3003214a478 lwp_mutex_enter(0x37dd8, 0x4400, ...)
91 00:00:04 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3003214aa90 lwp_mutex_enter(0x37dd8, 0x0, ...)
25 00:00:04 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3003ebe7b40 lwp_mutex_enter(0x37dd8, 0x0, ...)
90 00:00:06 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3194bbceea0 lwp_mutex_enter(0x37dd8, 0x0, ...)
12 00:00:06 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3005f11cbd8 lwp_mutex_enter(0x37dd8, 0x0, ...)
67 00:00:07 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3003214a410 lwp_mutex_enter(0x37dd8, 0x4400, ...)
103 00:00:07 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3021be294d0 lwp_mutex_enter(0x37dd8, 0x0, ...)
54 00:00:07 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3006699db38 lwp_mutex_enter(0x37dd8, 0x0, ...)
13 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3005f11cde0 lwp_mutex_enter(0x380c0, 0x1, ...)
15 00:00:07 SLEEP 0x00000037ddd/0x31955844140 USER 0 0x3020108f120 lwp_mutex_enter(0x37dd8, 0x0, ...)
17 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3003f3a80e0 lwp_mutex_enter(0x380c0, 0x1, ...)
19 00:00:07 SLEEP 0x000000ef285/0x31955844140 USER 0 0x301010a31e0 lwp_mutex_enter(0xef280, 0x1, ...)
20 00:00:07 SLEEP 0x000000ef285/0x31955844140 USER 0 0x3005705d328 lwp_mutex_enter(0xef280, 0x1, ...)
21 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3026cdf8e48 lwp_mutex_enter(0x380c0, 0x1, ...)
23 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3001431f878 lwp_mutex_enter(0x380c0, 0x1, ...)
24 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3002bba8f20 lwp_mutex_enter(0x380c0, 0x1, ...)
26 00:00:07 SLEEP 0x000000ef285/0x31955844140 USER 0 0x3000ad43400 lwp_mutex_enter(0xef280, 0x1, ...)
27 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x319591a04f8 lwp_mutex_enter(0x380c0, 0x1, ...)
29 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x32b7669d318 lwp_mutex_enter(0x380c0, 0x1, ...)
30 00:00:07 SLEEP 0x000000ef285/0x31955844140 USER 0 0x5b8de62b2b0 lwp_mutex_enter(0xef280, 0x1, ...)
31 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3005705dbb0 lwp_mutex_enter(0x380c0, 0x1, ...)
33 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3002b81cb68 lwp_mutex_enter(0x380c0, 0x1, ...)
35 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x30056c1a4e0 lwp_mutex_enter(0x380c0, 0x1, ...)
39 00:00:07 SLEEP 0x000000380c5/0x31955844140 USER 0 0x3026cdf9600 lwp_mutex_enter(0x380c0, 0x1, ...)
42 00:00:07 SLEEP 0x00000037ec4/0x31955844140 USER 0 0x3026cdf9b48 lwp_cv_wait(0x37ec0, 0x37ea8, ...)
Voy a intentar seguir desarrollando estos comandos, por lo que agradecería cualquier, consejo o idea que se te ocurra.
Algunos derechos reservados. Licencia Creative Commons
Comentarios Recientes
Sobre
Esta plantilla a sido creada con la validacion de CSS y XHTML, por N.Design Studio.Los iconos usados son de Web 2 Mini pack.