Guia de rastreamento dinâmico Solaris

Capítulo 22 Provedor sdt

O provedor Statically Defined Tracing (SDT) cria testes nos locais que um programador de software designou formalmente. O mecanismo do SDT permite aos programadores escolher conscientemente os locais de interesse para usuários do DTrace e transmitir algum conhecimento semântico sobre cada local através do nome do teste. O kernel do Solaris definiu uma série de testes SDT, e provavelmente adicionará outros mais ao longo do tempo. O DTrace também fornece um mecanismo para desenvolvedores de aplicativos do usuário definirem testes estáticos, descrito no Capítulo 34Rastreio definido estaticamente em aplicativos do usuário.

Testes

Os testes do SDT definidos pelo kernel do Solaris estão listados na Tabela 22–1. A estabilidade do nome e a estabilidade dos dados destes testes são ambas Privadas, pois sua descrição aqui reflete a implementação do kernel e não deve ser considerada como um comprometimento de interface. Para obter mais informações sobre o mecanismo de estabilidade do DTrace, consulte Estabilidade.

Tabela 22–1 Testes SDT

Nome do teste 

Descrição 

arg0

callout-start

Teste que é acionado imediatamente antes da execução de um callout (consulte <sys/callo.h>). Os callouts são executados pelo relógio periódico do sistema e representam a implementação de timeout(9F).

O ponteiro para callout_t (consulte <sys/callo.h>) correspondente ao callout a ser executado.

callout-end

Teste que é acionado imediatamente depois da execução de um callout (consulte <sys/callo.h>).

O ponteiro para callout_t (consulte <sys/callo.h>) correspondente ao callout que acabou de ser executado.

interrupt-start

Teste que é acionado imediatamente antes da chamada do manipulador de interrupção do dispositivo. 

O ponteiro para a estrutura dev_info (consulte <sys/ddi_impldefs.h> ) correspondente ao dispositivo de interrupção.

interrupt-complete

Teste que é acionado imediatamente depois do retorno do manipulador de interrupção de um dispositivo. 

O ponteiro para a estrutura dev_info (consulte <sys/ddi_impldefs.h> ) correspondente ao dispositivo de interrupção.

Exemplos

O exemplo seguinte é um script para observar o comportamento do callout por segundo:

#pragma D option quiet

sdt:::callout-start
{
	@callouts[((callout_t *)arg0)->c_func] = count();
}

tick-1sec
{
	printa("%40a %10@d\n", @callouts);
	clear(@callouts);
}

Executar este exemplo revela os usuários freqüentes do timeout(9F) no sistema, conforme mostrado na saída seguinte:


# dtrace -s ./callout.d
                                    FUNC      COUNT
                            TS`ts_update          1
              uhci`uhci_cmd_timeout_hdlr          3
                          genunix`setrun          5
                     genunix`schedpaging          5
                         ata`ghd_timeout         10
 uhci`uhci_handle_root_hub_status_change        309

                                    FUNC      COUNT
              ip`tcp_time_wait_collector          1
                            TS`ts_update          1
              uhci`uhci_cmd_timeout_hdlr          3
                     genunix`schedpaging          4
                          genunix`setrun          8
                         ata`ghd_timeout         10
 uhci`uhci_handle_root_hub_status_change        300

                                    FUNC      COUNT
              ip`tcp_time_wait_collector          0
                        iprb`mii_portmon          1
                            TS`ts_update          1
              uhci`uhci_cmd_timeout_hdlr          3
                     genunix`schedpaging          4
                          genunix`setrun          7
                         ata`ghd_timeout         10
 uhci`uhci_handle_root_hub_status_change        300

A interface de timeout(9F) somente produz uma única expiração de temporizador. Os consumidores de timeout() que requerem a funcionalidade de temporizador de intervalo geralmente reinstalam seu timeout a partir do manipulador timeout(). O exemplo seguinte mostra este comportamento:

#pragma D option quiet

sdt:::callout-start
{
	self->callout = ((callout_t *)arg0)->c_func;
}

fbt::timeout:entry
/self->callout && arg2 <= 100/
{
	/*
	 * In this case, we are most interested in interval timeout(9F)s that
	 * are short.  We therefore do a linear quantization from 0 ticks to
	 * 100 ticks.  The system clock's frequency — set by the variable
	 * "hz" — defaults to 100, so 100 system clock ticks is one second. 
	 */
	@callout[self->callout] = lquantize(arg2, 0, 100);
}

sdt:::callout-end
{
	self->callout = NULL;
}

END
{
	printa("%a\n%@d\n\n", @callout);
}

Executar este script e esperar alguns segundos antes de digitar Control-C resulta em uma saída semelhante ao exemplo seguinte:


# dtrace -s ./interval.d
^C
genunix`schedpaging

           value  ------------- Distribution ------------- count    
              24 |                                         0        
              25 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 20       
              26 |                                         0        


ata`ghd_timeout

           value  ------------- Distribution ------------- count    
               9 |                                         0        
              10 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 51       
              11 |                                         0        


uhci`uhci_handle_root_hub_status_change

           value  ------------- Distribution ------------- count    
               0 |                                         0        
               1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1515     
               2 |                                         0

A saída mostra que a uhci_handle_root_hub_status_change() no driver uhci(7D) representa o temporizador de intervalo mais curto no sistema: ele é chamado a cada tique-taque do relógio do sistema.

O teste interrupt-start pode ser usado para entender a atividade de interrupção. O exemplo seguinte mostra como quantizar o tempo gasto ao executar um manipulador de interrupção pelo nome do driver:

interrupt-start
{
	self->ts = vtimestamp;
}

interrupt-complete
/self->ts/
{
	this->devi = (struct dev_info *)arg0;
	@[stringof(`devnamesp[this->devi->devi_major].dn_name),
	    this->devi->devi_instance] = quantize(vtimestamp - self->ts);
}

Executar este script acima resultará numa saída semelhante ao exemplo seguinte:


# dtrace -s ./intr.d
dtrace: script './intr.d' matched 2 probes
^C
 isp                                                       0
           value  ------------- Distribution ------------- count    
            8192 |                                         0        
           16384 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1        
           32768 |                                         0        

  pcf8584                                                   0
           value  ------------- Distribution ------------- count    
              64 |                                         0        
             128 |                                         2        
             256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         157      
             512 |@@@@@@                                   31       
            1024 |                                         3        
            2048 |                                         0        

  pcf8584                                                   1
           value  ------------- Distribution ------------- count    
            2048 |                                         0        
            4096 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          154      
            8192 |@@@@@@@                                  37       
           16384 |                                         2        
           32768 |                                         0        

  qlc                                                       0
           value  ------------- Distribution ------------- count    
           16384 |                                         0        
           32768 |@@                                       9        
           65536 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      126      
          131072 |@                                        5        
          262144 |                                         2        
          524288 |                                         0        

  hme                                                       0
           value  ------------- Distribution ------------- count    
            1024 |                                         0        
            2048 |                                         6        
            4096 |                                         2        
            8192 |@@@@                                     89       
           16384 |@@@@@@@@@@@@@                            262      
           32768 |@                                        37       
           65536 |@@@@@@@                                  139      
          131072 |@@@@@@@@                                 161      
          262144 |@@@                                      73       
          524288 |                                         4        
         1048576 |                                         0        
         2097152 |                                         1        
         4194304 |                                         0        

  ohci                                                      0
           value  ------------- Distribution ------------- count    
            8192 |                                         0        
           16384 |                                         3        
           32768 |                                         1        
           65536 |@@@                                      143      
          131072 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@     1368     
          262144 |                                         0 

Criando testes do SDT

Se você for um desenvolvedor de driver de dispositivo, talvez esteja interessado em criar seus próprios testes do SDT em seu driver do Solaris. O efeito de teste desativado do SDT é essencialmente o custo de várias instruções de máquina não operacionais. Portanto, você é encorajado a adicionar testes do SDT aos seus drivers de dispositivo, se necessário. A menos que estes testes afetem negativamente o desempenho, você pode deixá-los em seu código de envio.

Declarando testes

Os testes do SDT são declarados através das macros DTRACE_PROBE , DTRACE_PROBE1, DTRACE_PROBE2, DTRACE_PROBE3 e DTRACE_PROBE4 do <sys/sdt.h>. O nome do módulo e o nome da função de um teste baseado em um SDT correspondem ao módulo do kernel e à função do teste. O nome do teste depende do nome fornecido na macro DTRACE_PROBEn. Se o nome não contiver duas barras inferiores consecutivas (__), o nome do teste será conforme escrito na macro. Se o nome contiver quaisquer duas barras inferiores consecutivas, o nome do teste converterá as barras inferiores consecutivas em um único traço (-). Por exemplo, se uma macro DTRACE_PROBE especificar transaction__start, o teste do SDT será chamado de transaction-start. Esta substituição permite que o código de C forneça nomes de macro que não são identificadores válidos de C sem especificar uma seqüência.

O DTrace inclui o nome do módulo do kernel e o nome da função como parte da tupla que identifica o teste, sendo assim, você não precisa incluir esta informação no nome do teste para evitar colisões de espaço de nome. Você pode usar o comando dtrace -l -P sdt -m módulo em seu módulo do driver para listar os testes que instalou e os nomes completos que serão vistos pelos usuários do DTrace.

Argumentos de teste

Os argumentos de cada teste do SDT são os argumentos especificados na referência de macro DTRACE_PROBEn correspondente. O número de argumentos depende de qual macro foi usada para criar o teste: DTRACE_PROBE1 especifica um argumento, DTRACE_PROBE2 especifica dois argumentos, e assim por diante. Ao declarar seus testes do SDT, você pode minimizar seu efeito de teste desativado, não referenciando os ponteiros e não carregando a partir de variáveis globais nos argumentos do teste. O cancelamento de referência de ponteiro e o carregamento de variável global podem ser feitos com segurança em ações de D que ativam testes, sendo assim, os usuários do DTrace podem solicitar estas ações somente quando necessárias.

Estabilidade

O provedor SDT usa o mecanismo de estabilidade do DTrace para descrever suas estabilidades, conforme mostrado na tabela seguinte. Para obter mais informações sobre o mecanismo de estabilidade, consulte o Capítulo 39Estabilidade.

Elemento 

Estabilidade de nome 

Estabilidade de dados 

Classe de dependência 

Provedor 

Desenvolvendo 

Desenvolvendo 

ISA

Módulo 

Privada 

Privada 

Desconhecida 

Função 

Privada 

Privada 

Desconhecida 

Nome 

Privada 

Privada 

ISA

Argumentos 

Privada 

Privada 

ISA