Mandalika's scratchpad [ Work blog @Oracle | Stock Market Notes | My Music Compositions ]

Old Posts: 09.04  10.04  11.04  12.04  01.05  02.05  03.05  04.05  05.05  06.05  07.05  08.05  09.05  10.05  11.05  12.05  01.06  02.06  03.06  04.06  05.06  06.06  07.06  08.06  09.06  10.06  11.06  12.06  01.07  02.07  03.07  04.07  05.07  06.07  08.07  09.07  10.07  11.07  12.07  01.08  02.08  03.08  04.08  05.08  06.08  07.08  08.08  09.08  10.08  11.08  12.08  01.09  02.09  03.09  04.09  05.09  06.09  07.09  08.09  09.09  10.09  11.09  12.09  01.10  02.10  03.10  04.10  05.10  06.10  07.10  08.10  09.10  10.10  11.10  12.10  01.11  02.11  03.11  04.11  05.11  07.11  08.11  09.11  10.11  11.11  12.11  01.12  02.12  03.12  04.12  05.12  06.12  07.12  08.12  09.12  10.12  11.12  12.12  01.13  02.13  03.13  04.13  05.13  06.13  07.13  08.13  09.13  10.13  11.13  12.13  01.14  02.14  03.14  04.14  05.14  06.14  07.14  09.14  10.14  11.14  12.14  01.15  02.15  03.15  04.15  06.15  09.15  12.15  01.16  03.16  04.16  05.16  06.16 


Saturday, June 11, 2016
 
Solaris API for Locality Group Observability

[ Related: 1st part @ Locality Group Observability on Solaris ]

As of this writing, Solaris has limited support for lgroup observability using programmatic interfaces. Applications can use the lgroup API to traverse the locality group hierarchy, discover the contents of each locality group and even affect thread and memory placement on desired lgroups.

The man page for liblgrp(3LIB) lists out the currently supported public interfaces, and a brief description for most of those interfaces can be obtained by running man -k lgroup in a shell. In order to use this API, applications must link with locality group library, liblgrp(3LIB).

The following sample code demonstrates lgroup API usage by making several lgrp_*() calls including lgrp_device_lgrps() to find the locality groups that are closest to the specified I/O device.

# cat -n iodevlgrp.c

     1  #include <stdio.h>
     2  #include <stdlib.h>
     3  #include <assert.h>
     4  #include <sys/lgrp_user.h>
     5  #include <sys/types.h>
     6
     7  int main(int argc, char **argv) {
     8
     9          if (argc != 2) {
    10                  fprintf(stderr, "Usage: %s \n", argv[0]);
    11                  exit(1);
    12          }
    13
    14          /*  lgroup interface version check */
    15          if (lgrp_version(LGRP_VER_CURRENT) != LGRP_VER_CURRENT) {
    16              fprintf(stderr, "\nBuilt with unsupported lgroup interface %d",
    17                  LGRP_VER_CURRENT);
    18              exit(1);
    19          }
    20
    21          lgrp_cookie_t cookie =lgrp_init(LGRP_VIEW_OS);
    22          lgrp_id_t node = lgrp_root(cookie);
    23
    24          /* refresh the cookie if stale */
    25          if ( lgrp_cookie_stale(cookie) ) {
    26                  lgrp_fini(cookie);
    27                  cookie =lgrp_init(LGRP_VIEW_OS);
    28          }
    29
    30          int nlgrps = lgrp_nlgrps(cookie);
    31          if ( nlgrps == -1 ) {
    32                  perror("\n lgrp_nlgrps");
    33                  lgrp_fini(cookie);
    34                  exit(1);
    35          }
    36          printf("Number of locality groups on the system: %d\n", (nlgrps-1));
    37
    38          /* lgroups closest to the target device */
    39          int numlgrps = lgrp_device_lgrps(argv[1], NULL, 0);
    40          if (numlgrps == -1 ){
    41                  fprintf(stderr, "I/O device: %s. ", argv[1]);
    42                  perror("lgrp_device_lgrps");
    43          } else {
    44                  printf("lgroups closest to the I/O device %s: ", argv[1]);
    45                  lgrp_id_t *lgrpids = (lgrp_id_t *)calloc(numlgrps, sizeof(lgrp_id_t));
    46                  assert(lgrpids != NULL);
    47                  lgrp_device_lgrps(argv[1], lgrpids, numlgrps);
    48                  for (int i = 0; i < numlgrps; ++i) {
    49                          printf(" %d ", lgrpids[i]);
    50                  }
    51                  free(lgrpids);
    52          }
    53          lgrp_fini(cookie);
    54          printf("\n");
    55          return 0;
    56
    57  }


% cc -o iodevlgrp -llgrp iodevlgrp.c

% ./iodevlgrp /dev/ixgbe0
Number of locality groups on the system: 2
lgroups closest to the I/O device /dev/ixgbe0:  1

% lgrpinfo -d /dev/ixgbe0
lgroup ID : 1

% ./iodevlgrp /dev/ixgbe1
Number of locality groups on the system: 2
lgroups closest to the I/O device /dev/ixgbe1:  2

% lgrpinfo -d /dev/ixgbe1
lgroup ID : 2

Source: Oracle Solaris 11.3 Programming Interfaces Guide

Labels:




Saturday, May 14, 2016
 
Blast from the Past : The Weekend Playlist #9

Previous playlists:

    #1    #8 (50s, 60s and 70s)    |    #2    #3    #4    #5 (80s)    |    #6    #7 (90s)

Another 90s playlist. Audio & Widget courtesy: Spotify

Labels:




Saturday, May 07, 2016
 
Blast from the Past : The Weekend Playlist #8

Previous playlists:

    #1 (50s, 60s and 70s) | #2 (80s) | #3 (80s) | #4 (80s) | #5 (80s) | #6 (90s) | #7 (90s)

Another 50s, 60s & 70s playlist. Audio & Widget courtesy: Spotify

Labels:




Friday, April 22, 2016
 
Solaris 11: Few Random Commands

Logical Domains
Dependencies & Dependents
Network & Power Consumption Stats
HBA Listing

Dependencies

In the following example, dummy domain depends on two domains -- primary domain for virtual disks and virtual network devices, and dom2 for virtual disks and SR-IOV virtual functions (VF).

# ldm list-dependencies dummy
DOMAIN            DEPENDENCY        TYPE
dummy             primary           VDISK,VNET
                  dom2              VDISK,IOV

-l option displays the actual devices.

Dependents

-r option in list-dependencies sub-command shows the dependents for the logical domain(s). -l option displays the actual devices in here too.

eg.,

# ldm list-dependencies -r -l dom2
DOMAIN            DEPENDENT         TYPE           DEVICE
dom2              dummy             VDISK          primary-vds0/vdisk0:vol_dummy_disk0
                                    VDISK          service-vds0/vdisk0:vol_dummy_disk0
                                    IOV            /SYS/IOU1/PCIE14/IOVIB.PF0.VF1
                                    IOV            /SYS/IOU1/EMS4/CARD/NET0/IOVNET.PF0.VF1

Network Statistics

list-netstat sub-command in ldm utility displays the statistics for all the network devices that are configured in the domain(s).

eg.,

# ldm ls-netstat dom2
DOMAIN
dom2

NAME               IPACKETS     RBYTES       OPACKETS     OBYTES
----               --------     ------       --------     ------
net4               444.42M      61.27G       444.42M      7.12G
net1               13.20M       4989.22M     0            0
net0               0            0            0            0
..
ldoms-net0.vf1     37.62M       6.44G        49.15K       3.97M
ldoms-net0.vf0     523.34K      90.15M       62.85K       14.67M
ldoms-net1.vf15    0            0            0            0
..

List HBAs

list-hba sub-command in ldm utility lists out the physical SCSI HBA initiator ports in the target domain. -t option shows SCSI transport medium type such as FC or SAS.

eg.,

# ldm ls-hba -t  primary
NAME                                                 VSAN
----                                                 ----
/SYS/IOU0/EMS1/CARD/SCSI/HBA0/PORT1
        init-port w5080020000016331
        Transport Protocol SAS
/SYS/IOU0/EMS1/CARD/SCSI/HBA0/PORT2
        init-port w5080020000016331
        Transport Protocol SAS
...

Check the latest man page for ldm(1M) for the complete list of options for those sub-commands.

Power Consumption Statistics

ldmpower command shows the breakdown of power consumed by processors and memory in different domains or in a given domain. Note that ldmpower is an independent command, not part of ldm utility.

eg.,

# ldmpower -c processors -c memory -l primary
Processor Power Consumption in Watts
DOMAIN          15_SEC_AVG      30_SEC_AVG      60_SEC_AVG
primary         313             315             317

Memory Power Consumption in Watts
DOMAIN          15_SEC_AVG      30_SEC_AVG      60_SEC_AVG
primary         594             595             595

As usual, check the man page ldmpower(1M) for details.


PCI Devices

Scan & List

scanpci utility scans PCI buses and reports configuration settings for each PCI device that it finds.

eg.,

# scanpci -v

pci bus 0x0002 cardnum 0x06 function 0x00: vendor 0x111d device 0x80ba
 Integrated Device Technology, Inc. [IDT] Device unknown
 CardVendor 0x0000 card 0x0000 (Card unknown)
  STATUS    0x0010  COMMAND 0x0147
  CLASS     0x06 0x04 0x00  REVISION 0x03
  BIST      0x00  HEADER 0x01  LATENCY 0x00  CACHE 0x10
  MAX_LAT   0x00  MIN_GNT 0x03  INT_PIN 0x00  INT_LINE 0x00
  Bus: primary=02, secondary=03, subordinate=72, sec-latency=0
  I/O behind bridge: 00000000-03ffffff
  Memory behind bridge: 00100000-2000ffff
  Prefetchable memory behind bridge: 100000000-777f0ffff

pci bus 0x0003 cardnum 0x00 function 0x00: vendor 0x8086 device 0x1521
 Intel Corporation I350 Gigabit Network Connection
 CardVendor 0x108e card 0x7b18 (Oracle/SUN, Quad Port GbE PCIe 2.0 Low Profile Adapter, UTP)
  STATUS    0x0010  COMMAND 0x0146
  CLASS     0x02 0x00 0x00  REVISION 0x01
  BIST      0x00  HEADER 0x80  LATENCY 0x00  CACHE 0x10
  BASE0     0x00100000 SIZE 1048576  MEM
  BASE3     0x00200000 SIZE 16384  MEM
  BASEROM   0x00280000 SIZE 524288
  MAX_LAT   0x00  MIN_GNT 0x00  INT_PIN 0x01  INT_LINE 0x00

...

SRU
IDRs

Detect & Show Installed

Identifying Solaris 11 SRU level is one of the popular topics and it was covered in Solaris 11 documentation, My Oracle Support (MOS) and elsewhere by numerous bloggers. After all this, we still have to wonder why there isn't a conscious effort by the development team that owns pkg utility to make this a bit easier for normal human beings. In any case, pkg list entire or pkg info entire commands show a cryptic version string with a bunch of information encoded including the SRU level.

The second numeral in "branch" version represents the Solaris update whereas the third numeral is the SRU.

eg.,

In the following example, Solaris update is 3 (running Solaris 11 - hence it is a Solaris 11.3 system) and current SRU is 5. (I underlined every alternate field)

# pkg info entire | grep -i branch
        Branch: 0.175.3.5.0.6.0

IDRs

IDRs (Interim Diagnostic Reliefs) are in reality package updates whose names usually start with "idr" - therefore, just checking for the string "idr" in the list of installed packages on the system is sufficient to list out what IDRs were installed on the target system.

# pkg list idr*
pkg list: No packages matching 'idr*' installed <-- no IDRs installed

(Ticket Stub CSS Theme Credit: Kia Skretteberg)

Labels:




Saturday, March 26, 2016
 
Programming in C: Few Tidbits #6

[1] Case-insensitive String Comparison

strcasecmp() is the case-insensitive version of strcmp(). When building, make sure to include strings.h (note the plural form).

strncasecmp() is the counterpart to strncmp().

eg.,
..
#include <string.h>
void main(int argc, char** argv)
 ..
        printf("\n\"%s\" and \"%s\" are ", argv[1], argv[2]);
        strcasecmp(argv[1], argv[2]) ? printf(" .. not identical") : printf(" .. identical");
        ..

% ./strcompare next NeXT
"next" and "NeXT" are  .. identical

[2] Initializing a Variable Length Array

As of the length of the variable length array is not known to the compiler at compile time, initializing a variable length automatic array with some default value usually results in a compilation error.

eg.,
% cat -n varlen.c
     1  #include <stdlib.h>
     2
     3  void main(int argc, char** argv) {
     4          int size=atoi(argv[1]);
     5          int array[size] = { 0 };
     6  }
/home/gmandali/C % cc -o varlen varlen.c
"varlen.c", line 5: variable length array can not be initialized: array
cc: acomp failed for varlen.c

One option is to explicitly initialize each element in the array to the desired default value.

eg.,
% cat -n varlen.c
     1  #include <stdlib.h>
     2
     3  void main(int argc, char** argv) {
     4          int size=atoi(argv[1]);
     5          int array[size];
     6          for (int i = 0; i < size; ++i)
     7                  array[i] = 0;
     8  }

% cc -o varlen varlen.c
%

Another option is to rely on memset().

eg.,
% cat -n varlen.c
     1  #include <stdlib.h>
     2  #include <string.h>
     3
     4  void main(int argc, char** argv) {
     5          int size=atoi(argv[1]);
     6          int array[size];
     7          memset(array, 0, sizeof(array));
     8  }

% cc -o varlen varlen.c
%

In this case, sizeof operator evaluates the operand (variable length array).


[3] Check if a Process is Alive

kill() function can be used to send a null signal (signal 0) to check the validity of a process.

eg.,
% cat -n chkproc.c
     1  #include <sys/types.h>
     2  #include <signal.h>
     3  #include <stdlib.h>
     4  #include <stdio.h>
     5
     6  void main(int argc, char **argv) {
     7          pid_t pid = atoi( argv[1] );
     8          int rc = kill( pid, 0 );
     9          if ( !rc ) {
    10                  printf("process with pid ( %d ) is alive", pid);
    11          } else {
    12                  printf("process with pid ( %d ) is not found", pid);
    13          }
    14  }

% cc -o chkproc chkproc.c

% ps
  PID TTY         TIME CMD
19846 pts/25      0:00 ps
28978 pts/25      0:00 bash

% ./chkproc 28978
process with pid ( 28978 ) is alive

% ./chkproc 28979
process with pid ( 28979 ) is not found

pid_t is actually int data type.


[4] Evaluating "( integer )" Expression

This is a simple one but probably an important one to remember. When dealing with an expression that yields an integer or when testing an integer, only a value of zero evaluates to false. Everything else including negative numbers, floating point numbers, characters, strings, .. are evaluated to true. In other words, anything non-zero is true.

eg.,
% cat -n ifexpr.c
     1  #include <stdio.h>
     2  #include <stdlib.h>
     3  #include <ctype.h>
     4
     5  void main(int argc, char **argv) {
     6          printf("\n[ %10d ] : %s",  0, (0) ? "true" : "false" );
     7          printf("\n[ %10d ] : %s",  1, (1) ? "true" : "false" );
     8          printf("\n[ %10d ] : %s",  -2, (-2) ? "true" : "false" );
     9          printf("\n[ %10s ] : %s",  "dummy", ("dummy") ? "true" : "false" );
    10          printf("\n[ %10c ] : %s",  'C', ('C') ? "true" : "false" );
    11          printf("\n[ %10f ] : %s",  2.34, (2.34) ? "true" : "false" );
    12          printf("\n[ %10f ] : %s\n",  0.0000, (0.0000) ? "true" : "false" );
    13  }

% cc -o ifexpr ifexpr.c
% ./ifexpr

[          0 ] : false
[          1 ] : true
[         -2 ] : true
[      dummy ] : true
[          C ] : true
[   2.340000 ] : true
[   0.000000 ] : false

[5] Variable Declaration in a switch { case: } Statement

Let's start with an example that shows compilation failure.

% cat -n varincase.c
     1  #include 
     2
     3  void main() {
     4          switch ( 1 ) {
     5                  case 2:
     6                          int i = 15;
     7                          break;
     8                  default:
     9                          printf("default\n");
    10          }
    11  }

% cc -o varincase varincase.c
"varincase.c", line 6: syntax error before or at: int
"varincase.c", line 7: undefined symbol: i
cc: acomp failed for varincase.c

In this example, identifier i is being declared and initialized in the case label of switch statement. Since no linkage or no static scope was specified, identifier i will have automatic storage duration that is local to the block containing the invocation (switch() { .. }, that is).

However the problem with this code is that case <expression> and default are labels and the controlling expression in switch statement causes the control to jump to appropriate label. In the example, when the control is transferred to default label, it enters the scope of identifier i without initializing it [as it bypasses the case where the identifier is being declared and initialized], which is not permitted. Therefore the fix is to declare the identifier (if at all needed) in its own compound statement so the scope is limited to that compound statement. (A compond statement is a block of code.)

Adding curly braces around case 2: statements will make the code compile and run as shown below.

% cat -n varincase.c
     1  #include <stdio.h>
     2
     3  void main() {
     4          switch ( 1 ) {
     5                  case 2:
     6                  {
     7                          int i = 15;
     8                          break;
     9                  }
    10                  default:
    11                          printf("default\n");
    12          }
    13  }

% cc -o varincase varincase.c

% ./varincase
default


(Stacked Paper CSS Theme Credit: Chris McLeod)

Labels:





2004-2016 

This page is powered by Blogger. Isn't yours?