Back to index

libdrm  2.4.37
drmstat.c
Go to the documentation of this file.
00001 /* drmstat.c -- DRM device status and testing program
00002  * Created: Tue Jan  5 08:19:24 1999 by faith@precisioninsight.com
00003  *
00004  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
00005  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
00006  * All Rights Reserved.
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a
00009  * copy of this software and associated documentation files (the "Software"),
00010  * to deal in the Software without restriction, including without limitation
00011  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00012  * and/or sell copies of the Software, and to permit persons to whom the
00013  * Software is furnished to do so, subject to the following conditions:
00014  * 
00015  * The above copyright notice and this permission notice (including the next
00016  * paragraph) shall be included in all copies or substantial portions of the
00017  * Software.
00018  * 
00019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00022  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00023  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00024  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00025  * DEALINGS IN THE SOFTWARE.
00026  * 
00027  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
00028  * 
00029  */
00030 
00031 #include "config.h"
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <unistd.h>
00036 #include <sys/types.h>
00037 #include <sys/time.h>
00038 #include <sys/mman.h>
00039 #include <getopt.h>
00040 #include <strings.h>
00041 #include <errno.h>
00042 #include <signal.h>
00043 #include <fcntl.h>
00044 #ifdef HAVE_ALLOCA_H
00045 # include <alloca.h>
00046 #endif
00047 #include "xf86drm.h"
00048 
00049 /* Support gcc's __FUNCTION__ for people using other compilers */
00050 #if !defined(__GNUC__) && !defined(__FUNCTION__)
00051 # define __FUNCTION__ __func__ /* C99 */
00052 #endif
00053 
00054 int sigio_fd;
00055 
00056 static double usec(struct timeval *end, struct timeval *start)
00057 {
00058     double e = end->tv_sec   * 1000000 + end->tv_usec;
00059     double s = start->tv_sec * 1000000 + start->tv_usec;
00060 
00061     return e - s;
00062 }
00063 
00064 static void getversion(int fd)
00065 {
00066     drmVersionPtr version;
00067     
00068     version = drmGetVersion(fd);
00069     if (version) {
00070        printf( "Name: %s\n", version->name ? version->name : "?" );
00071        printf( "    Version: %d.%d.%d\n",
00072               version->version_major,
00073               version->version_minor,
00074               version->version_patchlevel );
00075        printf( "    Date: %s\n", version->date ? version->date : "?" );
00076        printf( "    Desc: %s\n", version->desc ? version->desc : "?" );
00077        drmFreeVersion(version);
00078     } else {
00079        printf( "No driver available\n" );
00080     }
00081 }
00082        
00083 void handler(int fd, void *oldctx, void *newctx)
00084 {
00085     printf("Got fd %d\n", fd);
00086 }
00087 
00088 void process_sigio(char *device)
00089 {
00090     int              fd;
00091 
00092     if ((fd = open(device, 0)) < 0) {
00093        drmError(-errno, __FUNCTION__);
00094        exit(1);
00095     }
00096 
00097     sigio_fd = fd;
00098     /*  drmInstallSIGIOHandler(fd, handler); */
00099     for (;;) sleep(60);
00100 }
00101 
00102 int main(int argc, char **argv)
00103 {
00104     int            c;
00105     int            r  = 0;
00106     int            fd = -1;
00107     drm_handle_t      handle;
00108     void           *address;
00109     char           *pt;
00110     unsigned long  count;
00111     unsigned long  offset;
00112     unsigned long  size;
00113     drm_context_t  context;
00114     int            loops;
00115     char           buf[1024];
00116     int            i;
00117     drmBufInfoPtr  info;
00118     drmBufMapPtr   bufs;
00119     drmLockPtr     lock;
00120     int            secs;
00121 
00122     while ((c = getopt(argc, argv,
00123                      "lc:vo:O:f:s:w:W:b:r:R:P:L:C:XS:B:F:")) != EOF)
00124        switch (c) {
00125        case 'F':
00126            count  = strtoul(optarg, NULL, 0);
00127            if (!fork()) {
00128               dup(fd);
00129               sleep(count);
00130            }
00131            close(fd);
00132            break;
00133        case 'v': getversion(fd);                                        break;
00134        case 'X':
00135            if ((r = drmCreateContext(fd, &context))) {
00136               drmError(r, argv[0]);
00137               return 1;
00138            }
00139            printf( "Got %d\n", context);
00140            break;
00141        case 'S':
00142            process_sigio(optarg);
00143            break;
00144        case 'C':
00145            if ((r = drmSwitchToContext(fd, strtoul(optarg, NULL, 0)))) {
00146               drmError(r, argv[0]);
00147               return 1;
00148            }
00149            break;
00150        case 'c':
00151            if ((r = drmSetBusid(fd,optarg))) {
00152               drmError(r, argv[0]);
00153               return 1;
00154            }
00155            break;
00156        case 'o':
00157            if ((fd = drmOpen(optarg, NULL)) < 0) {
00158               drmError(fd, argv[0]);
00159               return 1;
00160            }
00161            break;
00162        case 'O':
00163            if ((fd = drmOpen(NULL, optarg)) < 0) {
00164               drmError(fd, argv[0]);
00165               return 1;
00166            }
00167            break;
00168        case 'B':            /* Test buffer allocation */
00169            count  = strtoul(optarg, &pt, 0);
00170            size   = strtoul(pt+1, &pt, 0);
00171            secs   = strtoul(pt+1, NULL, 0);
00172            {
00173               drmDMAReq      dma;
00174               int            *indices, *sizes;
00175 
00176               indices = alloca(sizeof(*indices) * count);
00177               sizes   = alloca(sizeof(*sizes)   * count);
00178               dma.context         = context;
00179               dma.send_count      = 0;
00180               dma.request_count   = count;
00181               dma.request_size    = size;
00182               dma.request_list    = indices;
00183               dma.request_sizes   = sizes;
00184               dma.flags           = DRM_DMA_WAIT;
00185               if ((r = drmDMA(fd, &dma))) {
00186                   drmError(r, argv[0]);
00187                   return 1;
00188               }
00189               for (i = 0; i < dma.granted_count; i++) {
00190                   printf("%5d: index = %d, size = %d\n",
00191                         i, dma.request_list[i], dma.request_sizes[i]);
00192               }
00193               sleep(secs);
00194               drmFreeBufs(fd, dma.granted_count, indices);
00195            }
00196            break;
00197        case 'b':
00198            count   = strtoul(optarg, &pt, 0);
00199            size    = strtoul(pt+1, NULL, 0);
00200            if ((r = drmAddBufs(fd, count, size, 0, 65536)) < 0) {
00201               drmError(r, argv[0]);
00202               return 1;
00203            }
00204            if (!(info = drmGetBufInfo(fd))) {
00205               drmError(0, argv[0]);
00206               return 1;
00207            }
00208            for (i = 0; i < info->count; i++) {
00209               printf("%5d buffers of size %6d (low = %d, high = %d)\n",
00210                      info->list[i].count,
00211                      info->list[i].size,
00212                      info->list[i].low_mark,
00213                      info->list[i].high_mark);
00214            }
00215            if ((r = drmMarkBufs(fd, 0.50, 0.80))) {
00216               drmError(r, argv[0]);
00217               return 1;
00218            }
00219            if (!(info = drmGetBufInfo(fd))) {
00220               drmError(0, argv[0]);
00221               return 1;
00222            }
00223            for (i = 0; i < info->count; i++) {
00224               printf("%5d buffers of size %6d (low = %d, high = %d)\n",
00225                      info->list[i].count,
00226                      info->list[i].size,
00227                      info->list[i].low_mark,
00228                      info->list[i].high_mark);
00229            }
00230            printf("===== /proc/dri/0/mem =====\n");
00231            sprintf(buf, "cat /proc/dri/0/mem");
00232            system(buf);
00233 #if 1
00234            if (!(bufs = drmMapBufs(fd))) {
00235               drmError(0, argv[0]);
00236               return 1;
00237            }
00238            printf("===============================\n");
00239            printf( "%d bufs\n", bufs->count);
00240            for (i = 0; i < bufs->count; i++) {
00241               printf( "  %4d: %8d bytes at %p\n",
00242                      i,
00243                      bufs->list[i].total,
00244                      bufs->list[i].address);
00245            }
00246            printf("===== /proc/dri/0/vma =====\n");
00247            sprintf(buf, "cat /proc/dri/0/vma");
00248            system(buf);
00249 #endif
00250            break;
00251        case 'f':
00252            offset  = strtoul(optarg, &pt, 0);
00253            size    = strtoul(pt+1, NULL, 0);
00254            handle  = 0;
00255            if ((r = drmAddMap(fd, offset, size,
00256                             DRM_FRAME_BUFFER, 0, &handle))) {
00257               drmError(r, argv[0]);
00258               return 1;
00259            }
00260            printf("0x%08lx:0x%04lx added\n", offset, size);
00261            printf("===== /proc/dri/0/mem =====\n");
00262            sprintf(buf, "cat /proc/dri/0/mem");
00263            system(buf);
00264            break;
00265        case 'r':
00266        case 'R':
00267            offset  = strtoul(optarg, &pt, 0);
00268            size    = strtoul(pt+1, NULL, 0);
00269            handle  = 0;
00270            if ((r = drmAddMap(fd, offset, size,
00271                             DRM_REGISTERS,
00272                             c == 'R' ? DRM_READ_ONLY : 0,
00273                             &handle))) {
00274               drmError(r, argv[0]);
00275               return 1;
00276            }
00277            printf("0x%08lx:0x%04lx added\n", offset, size);
00278            printf("===== /proc/dri/0/mem =====\n");
00279            sprintf(buf, "cat /proc/dri/0/mem");
00280            system(buf);
00281            break;
00282        case 's':
00283            size = strtoul(optarg, &pt, 0);
00284            handle = 0;
00285            if ((r = drmAddMap(fd, 0, size,
00286                             DRM_SHM, DRM_CONTAINS_LOCK,
00287                             &handle))) {
00288               drmError(r, argv[0]);
00289               return 1;
00290            }
00291            printf("0x%04lx byte shm added at 0x%08lx\n", size, handle);
00292            sprintf(buf, "cat /proc/dri/0/vm");
00293            system(buf);
00294            break;
00295        case 'P':
00296            offset  = strtoul(optarg, &pt, 0);
00297            size    = strtoul(pt+1, NULL, 0);
00298            address = NULL;
00299            if ((r = drmMap(fd, offset, size, &address))) {
00300               drmError(r, argv[0]);
00301               return 1;
00302            }
00303            printf("0x%08lx:0x%04lx mapped at %p for pid %d\n",
00304                  offset, size, address, getpid());
00305            printf("===== /proc/dri/0/vma =====\n");
00306            sprintf(buf, "cat /proc/dri/0/vma");
00307            system(buf);
00308            mprotect((void *)offset, size, PROT_READ);
00309            printf("===== /proc/dri/0/vma =====\n");
00310            sprintf(buf, "cat /proc/dri/0/vma");
00311            system(buf);
00312            break;
00313        case 'w':
00314        case 'W':
00315            offset  = strtoul(optarg, &pt, 0);
00316            size    = strtoul(pt+1, NULL, 0);
00317            address = NULL;
00318            if ((r = drmMap(fd, offset, size, &address))) {
00319               drmError(r, argv[0]);
00320               return 1;
00321            }
00322            printf("0x%08lx:0x%04lx mapped at %p for pid %d\n",
00323                  offset, size, address, getpid());
00324            printf("===== /proc/%d/maps =====\n", getpid());
00325            sprintf(buf, "cat /proc/%d/maps", getpid());
00326            system(buf);
00327            printf("===== /proc/dri/0/mem =====\n");
00328            sprintf(buf, "cat /proc/dri/0/mem");
00329            system(buf);
00330            printf("===== /proc/dri/0/vma =====\n");
00331            sprintf(buf, "cat /proc/dri/0/vma");
00332            system(buf);
00333            printf("===== READING =====\n");
00334            for (i = 0; i < 0x10; i++)
00335               printf("%02x ", (unsigned int)((unsigned char *)address)[i]);
00336            printf("\n");
00337            if (c == 'w') {
00338               printf("===== WRITING =====\n");
00339               for (i = 0; i < size; i+=2) {
00340                   ((char *)address)[i]   = i & 0xff;
00341                   ((char *)address)[i+1] = i & 0xff;
00342               }
00343            }
00344            printf("===== READING =====\n");
00345            for (i = 0; i < 0x10; i++)
00346               printf("%02x ", (unsigned int)((unsigned char *)address)[i]);
00347            printf("\n");
00348            printf("===== /proc/dri/0/vma =====\n");
00349            sprintf(buf, "cat /proc/dri/0/vma");
00350            system(buf);
00351            break;
00352        case 'L':
00353            context = strtoul(optarg, &pt, 0);
00354            offset  = strtoul(pt+1, &pt, 0);
00355            size    = strtoul(pt+1, &pt, 0);
00356            loops   = strtoul(pt+1, NULL, 0);
00357            address = NULL;
00358            if ((r = drmMap(fd, offset, size, &address))) {
00359               drmError(r, argv[0]);
00360               return 1;
00361            }
00362            lock       = address;
00363 #if 1
00364            {
00365               int            counter = 0;
00366               struct timeval loop_start, loop_end;
00367               struct timeval lock_start, lock_end;
00368               double         wt;
00369 #define HISTOSIZE 9
00370               int            histo[HISTOSIZE];
00371               int            output = 0;
00372               int            fast   = 0;
00373 
00374               if (loops < 0) {
00375                   loops = -loops;
00376                   ++output;
00377               }
00378 
00379               for (i = 0; i < HISTOSIZE; i++) histo[i] = 0;
00380 
00381               gettimeofday(&loop_start, NULL);
00382               for (i = 0; i < loops; i++) {
00383                   gettimeofday(&lock_start, NULL);
00384                   DRM_LIGHT_LOCK_COUNT(fd,lock,context,fast);
00385                   gettimeofday(&lock_end, NULL);
00386                   DRM_UNLOCK(fd,lock,context);
00387                   ++counter;
00388                   wt = usec(&lock_end, &lock_start);
00389                   if      (wt <=      2.5) ++histo[8];
00390                   if      (wt <       5.0) ++histo[0];
00391                   else if (wt <      50.0) ++histo[1];
00392                   else if (wt <     500.0) ++histo[2];
00393                   else if (wt <    5000.0) ++histo[3];
00394                   else if (wt <   50000.0) ++histo[4];
00395                   else if (wt <  500000.0) ++histo[5];
00396                   else if (wt < 5000000.0) ++histo[6];
00397                   else                     ++histo[7];
00398                   if (output) printf( "%.2f uSec, %d fast\n", wt, fast);
00399               }
00400               gettimeofday(&loop_end, NULL);
00401               printf( "Average wait time = %.2f usec, %d fast\n",
00402                      usec(&loop_end, &loop_start) /  counter, fast);
00403               printf( "%9d <=     2.5 uS\n", histo[8]);
00404               printf( "%9d <        5 uS\n", histo[0]);
00405               printf( "%9d <       50 uS\n", histo[1]);
00406               printf( "%9d <      500 uS\n", histo[2]);
00407               printf( "%9d <     5000 uS\n", histo[3]);
00408               printf( "%9d <    50000 uS\n", histo[4]);
00409               printf( "%9d <   500000 uS\n", histo[5]);
00410               printf( "%9d <  5000000 uS\n", histo[6]);
00411               printf( "%9d >= 5000000 uS\n", histo[7]);
00412            }
00413 #else
00414            printf( "before lock: 0x%08x\n", lock->lock);
00415            printf( "lock: 0x%08x\n", lock->lock);
00416            sleep(5);
00417            printf( "unlock: 0x%08x\n", lock->lock);
00418 #endif
00419            break;
00420        default:
00421            fprintf( stderr, "Usage: drmstat [options]\n" );
00422            return 1;
00423        }
00424 
00425     return r; 
00426 }
00427 
00428 void
00429 xf86VDrvMsgVerb(int scrnIndex, int type, int verb, const char *format,
00430                 va_list args)
00431 {
00432        vfprintf(stderr, format, args);
00433 }
00434 
00435 int xf86ConfigDRI[10];