src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c
changeset 53379 e47074d2d8cc
parent 53004 b9d34a97a4be
equal deleted inserted replaced
53378:52abdb8a48b2 53379:e47074d2d8cc
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    24 #include <stdarg.h>
    24 #include <stdarg.h>
    25 #include <stdio.h>
    25 #include <stdio.h>
    26 #include <stdlib.h>
    26 #include <stdlib.h>
    27 #include <string.h>
    27 #include <string.h>
    28 #include <fcntl.h>
    28 #include <fcntl.h>
    29 #include <thread_db.h>
    29 #include <sys/procfs.h>
    30 #include "libproc_impl.h"
    30 #include "libproc_impl.h"
       
    31 #include "proc_service.h"
    31 
    32 
    32 #define SA_ALTROOT "SA_ALTROOT"
    33 #define SA_ALTROOT "SA_ALTROOT"
    33 
    34 
    34 int pathmap_open(const char* name) {
    35 int pathmap_open(const char* name) {
    35   static const char *alt_root = NULL;
    36   static const char *alt_root = NULL;
   114 // initialize libproc
   115 // initialize libproc
   115 JNIEXPORT bool JNICALL
   116 JNIEXPORT bool JNICALL
   116 init_libproc(bool debug) {
   117 init_libproc(bool debug) {
   117    // init debug mode
   118    // init debug mode
   118    _libsaproc_debug = debug;
   119    _libsaproc_debug = debug;
   119 
       
   120    // initialize the thread_db library
       
   121    if (td_init() != TD_OK) {
       
   122      print_debug("libthread_db's td_init failed\n");
       
   123      return false;
       
   124    }
       
   125 
       
   126    return true;
   120    return true;
   127 }
   121 }
   128 
   122 
   129 static void destroy_lib_info(struct ps_prochandle* ph) {
   123 static void destroy_lib_info(struct ps_prochandle* ph) {
   130    lib_info* lib = ph->libs;
   124    lib_info* lib = ph->libs;
   254    }
   248    }
   255    return NULL;
   249    return NULL;
   256 }
   250 }
   257 
   251 
   258 // add a thread to ps_prochandle
   252 // add a thread to ps_prochandle
   259 thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
   253 thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) {
   260    thread_info* newthr;
   254    thread_info* newthr;
   261    if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
   255    if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
   262       print_debug("can't allocate memory for thread_info\n");
   256       print_debug("can't allocate memory for thread_info\n");
   263       return NULL;
   257       return NULL;
   264    }
   258    }
   265 
   259 
   266    // initialize thread info
   260    // initialize thread info
   267    newthr->pthread_id = pthread_id;
       
   268    newthr->lwp_id = lwp_id;
   261    newthr->lwp_id = lwp_id;
   269 
   262 
   270    // add new thread to the list
   263    // add new thread to the list
   271    newthr->next = ph->threads;
   264    newthr->next = ph->threads;
   272    ph->threads = newthr;
   265    ph->threads = newthr;
   292       previous_thr->next = current_thr->next;
   285       previous_thr->next = current_thr->next;
   293     }
   286     }
   294     ph->num_threads--;
   287     ph->num_threads--;
   295     free(current_thr);
   288     free(current_thr);
   296 }
   289 }
   297 
       
   298 // struct used for client data from thread_db callback
       
   299 struct thread_db_client_data {
       
   300    struct ps_prochandle* ph;
       
   301    thread_info_callback callback;
       
   302 };
       
   303 
       
   304 // callback function for libthread_db
       
   305 static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
       
   306   struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
       
   307   td_thrinfo_t ti;
       
   308   td_err_e err;
       
   309 
       
   310   memset(&ti, 0, sizeof(ti));
       
   311   err = td_thr_get_info(th_p, &ti);
       
   312   if (err != TD_OK) {
       
   313     print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
       
   314     return err;
       
   315   }
       
   316 
       
   317   print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
       
   318 
       
   319   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) {
       
   320     print_debug("Skipping pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
       
   321     return TD_OK;
       
   322   }
       
   323 
       
   324   if (ptr->callback(ptr->ph, ti.ti_tid, ti.ti_lid) != true)
       
   325     return TD_ERR;
       
   326 
       
   327   return TD_OK;
       
   328 }
       
   329 
       
   330 // read thread_info using libthread_db
       
   331 bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
       
   332   struct thread_db_client_data mydata;
       
   333   td_thragent_t* thread_agent = NULL;
       
   334   if (td_ta_new(ph, &thread_agent) != TD_OK) {
       
   335      print_debug("can't create libthread_db agent\n");
       
   336      return false;
       
   337   }
       
   338 
       
   339   mydata.ph = ph;
       
   340   mydata.callback = cb;
       
   341 
       
   342   // we use libthread_db iterator to iterate thru list of threads.
       
   343   if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
       
   344                  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
       
   345                  TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
       
   346      td_ta_delete(thread_agent);
       
   347      return false;
       
   348   }
       
   349 
       
   350   // delete thread agent
       
   351   td_ta_delete(thread_agent);
       
   352   return true;
       
   353 }
       
   354 
       
   355 
   290 
   356 // get number of threads
   291 // get number of threads
   357 int get_num_threads(struct ps_prochandle* ph) {
   292 int get_num_threads(struct ps_prochandle* ph) {
   358    return ph->num_threads;
   293    return ph->num_threads;
   359 }
   294 }
   482 ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
   417 ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
   483   print_debug("ps_lgetfpregs not implemented\n");
   418   print_debug("ps_lgetfpregs not implemented\n");
   484   return PS_OK;
   419   return PS_OK;
   485 }
   420 }
   486 
   421 
   487 // new libthread_db of NPTL seem to require this symbol
       
   488 JNIEXPORT ps_err_e JNICALL
       
   489 ps_get_thread_area() {
       
   490   print_debug("ps_get_thread_area not implemented\n");
       
   491   return PS_OK;
       
   492 }