#define pthdb_tid_t tid_t
#endif
-/* Return whether to treat PID as a debuggable thread id. */
-
-#define PD_TID(ptid) (pd_active && ptid.tid () != 0)
-
/* Success and failure values returned by pthdb callbacks. */
#define PDC_SUCCESS PTHDB_SUCCESS
static aix_thread_target aix_thread_ops;
-/* Address of the function that libpthread will call when libpthdebug
- is ready to be initialized. */
-
-static CORE_ADDR pd_brk_addr;
-
-/* Whether the current application is debuggable by pthdb. */
-
-static int pd_able = 0;
-
-/* Whether a threaded application is being debugged. */
-
-static int pd_active = 0;
-
-/* Whether the current architecture is 64-bit.
- Only valid when pd_able is true. */
-
-static int arch64;
-
/* Forward declarations for pthdb callbacks. */
static int pdc_symbol_addrs (pthdb_user_t, pthdb_symbol_t *, int);
NULL
};
-/* Current pthdb session. */
+/* Aix variable structure. */
+struct aix_thread_variables
+{
+ /* Whether the current application is debuggable by pthdb. */
+ int pd_able;
+
+ /* Whether a threaded application is being debugged. */
+ int pd_active;
+
+ /* Current pthdb session. */
+ pthdb_session_t pd_session;
+
+ /* Address of the function that libpthread will call when libpthdebug
+ is ready to be initialized. */
+ CORE_ADDR pd_brk_addr;
+
+ /* Whether the current architecture is 64-bit.
+ Only valid when pd_able is true. */
+ int arch64;
+};
+
+/* Key to our per-inferior data. */
+static const registry<inferior>::key<aix_thread_variables>
+ aix_thread_variables_handle;
+
+/* Function to Get aix_thread_variables data. */
+static struct aix_thread_variables*
+get_aix_thread_variables_data (struct inferior *inf)
+{
+ if (inf == NULL)
+ return NULL;
+
+ struct aix_thread_variables* data;
+
+ data = aix_thread_variables_handle.get (inf);
+ if (data == NULL)
+ data = aix_thread_variables_handle.emplace (inf);
+
+ return data;
+}
+
+/* Helper to get data for ptid in a function. */
-static pthdb_session_t pd_session;
+static struct aix_thread_variables*
+get_thread_data_helper_for_ptid (ptid_t ptid)
+{
+ inferior *inf = find_inferior_ptid (current_inferior ()->process_target (),
+ ptid);
+ return get_aix_thread_variables_data (inf);
+}
+
+/* Helper to get data for pid in a function. */
+
+static struct aix_thread_variables*
+get_thread_data_helper_for_pid (pid_t pid)
+{
+ inferior *inf = find_inferior_pid (current_inferior ()->process_target (),
+ pid);
+ return get_aix_thread_variables_data (inf);
+}
/* Return a printable representation of pthdebug function return
STATUS. */
ptid_t ptid;
ptid = *ptidp;
- if (PD_TID (ptid))
+ if (ptid.tid () != 0)
*ptidp = ptid_t (ptid.pid ());
}
double fprs[ppc_num_fprs];
struct ptxsprs sprs64;
struct ptsprs sprs32;
-
+ struct aix_thread_variables *data;
+
+ data = get_thread_data_helper_for_pid (user_current_pid);
+
if (debug_aix_thread)
gdb_printf (gdb_stdlog, "pdc_read_regs tid=%d flags=%s\n",
(int) tid, hex_string (flags));
/* General-purpose registers. */
if (flags & PTHDB_FLAG_GPRS)
{
- if (arch64)
+ if (data->arch64)
{
if (!ptrace64aix (PTT_READ_GPRS, tid,
(unsigned long) gprs64, 0, NULL))
/* Special-purpose registers. */
if (flags & PTHDB_FLAG_SPRS)
{
- if (arch64)
+ if (data->arch64)
{
if (!ptrace64aix (PTT_READ_SPRS, tid,
(unsigned long) &sprs64, 0, NULL))
this is needed, I have implemented what I think it should do,
however this code is untested. */
+ struct aix_thread_variables *data;
+
+ data = get_thread_data_helper_for_pid (user_current_pid);
+
if (debug_aix_thread)
gdb_printf (gdb_stdlog, "pdc_write_regs tid=%d flags=%s\n",
(int) tid, hex_string (flags));
/* General-purpose registers. */
if (flags & PTHDB_FLAG_GPRS)
{
- if (arch64)
+ if (data->arch64)
ptrace64aix (PTT_WRITE_GPRS, tid,
(unsigned long) context->gpr, 0, NULL);
else
/* Special-purpose registers. */
if (flags & PTHDB_FLAG_SPRS)
{
- if (arch64)
+ if (data->arch64)
{
ptrace64aix (PTT_WRITE_SPRS, tid,
(unsigned long) &context->msr, 0, NULL);
pthdb_addr_t addr, size_t len)
{
int status, ret;
+ inferior *inf = find_inferior_pid (current_inferior ()->process_target (),
+ user_current_pid);
if (debug_aix_thread)
gdb_printf (gdb_stdlog,
/* This is needed to eliminate the dependency of current thread
which is null so that thread reads the correct target memory. */
{
- scoped_restore_current_thread restore_current_thread;
- /* Before the first inferior is added, we pass inferior_ptid.pid ()
- from pd_enable () which is 0. There is no need to switch threads
- during first initialisation. In the rest of the callbacks the
- current thread needs to be correct. */
- if (user_current_pid != 0)
- switch_to_thread (current_inferior ()->process_target (),
- ptid_t (user_current_pid));
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
+ inferior_ptid = ptid_t (user_current_pid);
+ scoped_restore_current_inferior restore_inferior;
+ set_current_inferior (inf);
+
+ scoped_restore_current_program_space restore_current_progspace;
+ set_current_program_space (inf->pspace);
status = target_read_memory (addr, (gdb_byte *) buf, len);
}
ret = status == 0 ? PDC_SUCCESS : PDC_FAILURE;
pthdb_addr_t addr, size_t len)
{
int status, ret;
+ inferior *inf = find_inferior_pid (current_inferior ()->process_target (),
+ user_current_pid);
if (debug_aix_thread)
gdb_printf (gdb_stdlog,
"pdc_write_data (user_current_pid = %ld, buf = 0x%lx, addr = %s, len = %ld)\n",
user_current_pid, (long) buf, hex_string (addr), len);
- status = target_write_memory (addr, (gdb_byte *) buf, len);
+ {
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
+ inferior_ptid = ptid_t (user_current_pid);
+ scoped_restore_current_inferior restore_inferior;
+ set_current_inferior (inf);
+
+ scoped_restore_current_program_space restore_current_progspace;
+ set_current_program_space (inf->pspace);
+ status = target_write_memory (addr, (gdb_byte *) buf, len);
+ }
+
ret = status == 0 ? PDC_SUCCESS : PDC_FAILURE;
if (debug_aix_thread)
return p1->pthid < p2->pthid ? -1 : p1->pthid > p2->pthid;
}
-/* iterate_over_threads() callback for counting GDB threads.
-
- Do not count the main thread (whose tid is zero). This matches
- the list of threads provided by the pthreaddebug library, which
- does not include that main thread either, and thus allows us
- to compare the two lists. */
-
-static int
-giter_count (struct thread_info *thread, void *countp)
-{
- if (PD_TID (thread->ptid))
- (*(int *) countp)++;
- return 0;
-}
-
-/* iterate_over_threads() callback for accumulating GDB thread pids.
-
- Do not include the main thread (whose tid is zero). This matches
- the list of threads provided by the pthreaddebug library, which
- does not include that main thread either, and thus allows us
- to compare the two lists. */
-
-static int
-giter_accum (struct thread_info *thread, void *bufp)
-{
- if (PD_TID (thread->ptid))
- {
- **(struct thread_info ***) bufp = thread;
- (*(struct thread_info ***) bufp)++;
- }
- return 0;
-}
-
/* ptid comparison function */
static int
sizeof (thrinf), &ktid, 1) != 1)
break;
- if (thrinf.ti_cursig == SIGTRAP)
+ /* We also need to keep in mind Trap and interrupt or any
+ signal that needs to be handled in pd_update (). */
+
+ if (thrinf.ti_cursig)
return thrinf.ti_tid;
}
have difficulty with certain call patterns */
static void
-sync_threadlists (int pid)
+sync_threadlists (pid_t pid)
{
int cmd, status;
int pcount, psize, pi, gcount, gi;
pthdb_pthread_t pdtid;
pthread_t pthid;
pthdb_tid_t tid;
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
+ thread_info *tp;
+ struct aix_thread_variables *data;
+ data = get_thread_data_helper_for_pid (pid);
/* Accumulate an array of libpthdebug threads sorted by pthread id. */
for (cmd = PTHDB_LIST_FIRST;; cmd = PTHDB_LIST_NEXT)
{
- status = pthdb_pthread (pd_session, &pdtid, cmd);
+ status = pthdb_pthread (data->pd_session, &pdtid, cmd);
if (status != PTHDB_SUCCESS || pdtid == PTHDB_INVALID_PTHREAD)
break;
- status = pthdb_pthread_ptid (pd_session, pdtid, &pthid);
+ status = pthdb_pthread_ptid (data->pd_session, pdtid, &pthid);
if (status != PTHDB_SUCCESS || pthid == PTHDB_INVALID_PTID)
continue;
for (pi = 0; pi < pcount; pi++)
{
- status = pthdb_pthread_tid (pd_session, pbuf[pi].pdtid, &tid);
+ status = pthdb_pthread_tid (data->pd_session, pbuf[pi].pdtid, &tid);
if (status != PTHDB_SUCCESS)
tid = PTHDB_INVALID_TID;
pbuf[pi].tid = tid;
/* Accumulate an array of GDB threads sorted by pid. */
+ /* gcount is GDB thread count and pcount is pthreadlib thread count. */
+
gcount = 0;
- iterate_over_threads (giter_count, &gcount);
+ for (thread_info *tp : all_threads (proc_target, ptid_t (pid)))
+ gcount++;
g = gbuf = XNEWVEC (struct thread_info *, gcount);
- iterate_over_threads (giter_accum, &g);
+ for (thread_info *tp : all_threads (proc_target, ptid_t (pid)))
+ *g++ = tp;
qsort (gbuf, gcount, sizeof *gbuf, gcmp);
/* Apply differences between the two arrays to GDB's thread list. */
+
for (pi = gi = 0; pi < pcount || gi < gcount;)
{
if (pi == pcount)
priv->pdtid = pbuf[pi].pdtid;
priv->tid = pbuf[pi].tid;
- process_stratum_target *proc_target
- = current_inferior ()->process_target ();
thread = add_thread_with_info (proc_target,
ptid_t (pid, 0, pbuf[pi].pthid),
priv);
}
else if (cmp_result > 0)
{
- delete_thread (gbuf[gi]);
- gi++;
+ /* This is to make the main process thread now look
+ like a thread. */
+
+ if (gptid.is_pid ())
+ {
+ tp = find_thread_ptid (proc_target, gptid);
+ thread_change_ptid (proc_target, gptid, pptid);
+ aix_thread_info *priv = new aix_thread_info;
+ priv->pdtid = pbuf[pi].pdtid;
+ priv->tid = pbuf[pi].tid;
+ tp->priv.reset (priv);
+ gi++;
+ pi++;
+ }
+ else
+ {
+ delete_thread (gbuf[gi]);
+ gi++;
+ }
}
else
{
- process_stratum_target *proc_target
- = current_inferior ()->process_target ();
thread = add_thread (proc_target, pptid);
aix_thread_info *priv = new aix_thread_info;
return a pid-only ptid with PID. */
static ptid_t
-pd_update (int pid)
+pd_update (pid_t pid)
{
int status;
ptid_t ptid;
pthdb_tid_t tid;
struct thread_info *thread = NULL;
+ struct aix_thread_variables *data;
+
+ data = get_thread_data_helper_for_pid (pid);
- if (!pd_active)
+ if (!data->pd_active)
return ptid_t (pid);
- status = pthdb_session_update (pd_session);
+ status = pthdb_session_update (data->pd_session);
if (status != PTHDB_SUCCESS)
return ptid_t (pid);
for that thread. Otherwise, return a ptid-only ptid using PID. */
static ptid_t
-pd_activate (int pid)
+pd_activate (pid_t pid)
{
int status;
-
- status = pthdb_session_init (pid, arch64 ? PEM_64BIT : PEM_32BIT,
- PTHDB_FLAG_REGS, &pd_callbacks,
- &pd_session);
+ struct aix_thread_variables *data;
+ data = get_thread_data_helper_for_pid (pid);
+
+ status = pthdb_session_init (pid, data->arch64 ? PEM_64BIT : PEM_32BIT,
+ PTHDB_FLAG_REGS, &pd_callbacks,
+ &data->pd_session);
if (status != PTHDB_SUCCESS)
{
return ptid_t (pid);
}
- pd_active = 1;
+ data->pd_active = 1;
return pd_update (pid);
}
-/* Undo the effects of pd_activate(). */
-
-static void
-pd_deactivate (void)
-{
- if (!pd_active)
- return;
- pthdb_session_destroy (pd_session);
-
- pid_to_prc (&inferior_ptid);
- pd_active = 0;
-}
-
/* An object file has just been loaded. Check whether the current
application is pthreaded, and if so, prepare for thread debugging. */
int status;
char *stub_name;
struct bound_minimal_symbol ms;
+ struct aix_thread_variables *data;
+
+ if (!inferior_ptid.pid ())
+ return;
+
+ data = get_thread_data_helper_for_ptid (inferior_ptid);
/* Don't initialize twice. */
- if (pd_able)
+ if (data->pd_able)
return;
/* Check application word size. */
- arch64 = register_size (target_gdbarch (), 0) == 8;
+ data->arch64 = register_size (target_gdbarch (), 0) == 8;
/* Check whether the application is pthreaded. */
stub_name = NULL;
ms = lookup_minimal_symbol (stub_name, NULL, NULL);
if (ms.minsym == NULL)
return;
- pd_brk_addr = ms.value_address ();
- if (!create_thread_event_breakpoint (target_gdbarch (), pd_brk_addr))
+ data->pd_brk_addr = ms.value_address ();
+ if (!create_thread_event_breakpoint (target_gdbarch (), data->pd_brk_addr))
return;
/* Prepare for thread debugging. */
current_inferior ()->push_target (&aix_thread_ops);
- pd_able = 1;
+ data->pd_able = 1;
+
+ inferior *inf = current_inferior ();
+ /* When attaching / handling fork child, don't try activating
+ thread debugging until we know about all shared libraries. */
+ if (inf->in_initial_library_scan)
+ return;
/* If we're debugging a core file or an attached inferior, the
pthread library may already have been initialized, so try to
static void
pd_disable (void)
{
- if (!pd_able)
+ struct aix_thread_variables *data;
+ data = get_thread_data_helper_for_ptid (inferior_ptid);
+
+ if (!data->pd_able)
return;
- if (pd_active)
- pd_deactivate ();
- pd_able = 0;
+ if (!data->pd_active)
+ return;
+ pthdb_session_destroy (data->pd_session);
+
+ pid_to_prc (&inferior_ptid);
+ data->pd_active = 0;
+ data->pd_able = 0;
current_inferior ()->unpush_target (&aix_thread_ops);
}
/* new_objfile observer callback.
If OBJFILE is non-null, check whether a threaded application is
- being debugged, and if so, prepare for thread debugging.
-
- If OBJFILE is null, stop debugging threads. */
+ being debugged, and if so, prepare for thread debugging. */
static void
new_objfile (struct objfile *objfile)
{
if (objfile)
pd_enable ();
- else
- pd_disable ();
}
/* Attach to process specified by ARGS. */
{
struct thread_info *thread;
pthdb_tid_t tid[2];
+ struct aix_thread_variables *data;
- if (!PD_TID (ptid))
+ data = get_thread_data_helper_for_ptid (ptid);
+
+ if (ptid.tid () == 0)
{
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
-
+
inferior_ptid = ptid_t (inferior_ptid.pid ());
beneath ()->resume (ptid, step, sig);
}
ptid.lwp ());
tid[1] = 0;
- if (arch64)
+ if (data->arch64)
ptrace64aix (PTT_CONTINUE, tid[0], (long long) 1,
gdb_signal_to_host (sig), (PTRACE_TYPE_ARG5) tid);
else
aix_thread_target::wait (ptid_t ptid, struct target_waitstatus *status,
target_wait_flags options)
{
+ struct aix_thread_variables *data;
{
pid_to_prc (&ptid);
pid-only ptids. */
gdb_assert (ptid.is_pid ());
+ data = get_thread_data_helper_for_ptid (ptid);
+
/* Check whether libpthdebug might be ready to be initialized. */
- if (!pd_active && status->kind () == TARGET_WAITKIND_STOPPED
+ if (!data->pd_active && status->kind () == TARGET_WAITKIND_STOPPED
&& status->sig () == GDB_SIGNAL_TRAP)
{
process_stratum_target *proc_target
struct gdbarch *gdbarch = regcache->arch ();
if (regcache_read_pc (regcache)
- - gdbarch_decr_pc_after_break (gdbarch) == pd_brk_addr)
+ - gdbarch_decr_pc_after_break (gdbarch) == data->pd_brk_addr)
return pd_activate (ptid.pid ());
}
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int status, i;
pthdb_context_t ctx;
+ struct aix_thread_variables *data;
+ data = get_thread_data_helper_for_ptid (inferior_ptid);
if (debug_aix_thread)
gdb_printf (gdb_stdlog,
"fetch_regs_user_thread %lx\n", (long) pdtid);
- status = pthdb_pthread_context (pd_session, pdtid, &ctx);
+ status = pthdb_pthread_context (data->pd_session, pdtid, &ctx);
if (status != PTHDB_SUCCESS)
error (_("aix-thread: fetch_registers: pthdb_pthread_context returned %s"),
pd_status2str (status));
/* General-purpose registers. */
- if (arch64)
+ if (data->arch64)
supply_gprs64 (regcache, ctx.gpr);
else
for (i = 0; i < ppc_num_gprs; i++)
/* Special registers. */
- if (arch64)
+ if (data->arch64)
supply_sprs64 (regcache, ctx.iar, ctx.msr, ctx.cr, ctx.lr, ctx.ctr,
ctx.xer, ctx.fpscr);
else
struct ptxsprs sprs64;
struct ptsprs sprs32;
int i;
+ struct aix_thread_variables *data;
+
+ data = get_thread_data_helper_for_ptid (regcache->ptid ());
if (debug_aix_thread)
gdb_printf (gdb_stdlog,
"fetch_regs_kernel_thread tid=%lx regno=%d arch64=%d\n",
- (long) tid, regno, arch64);
+ (long) tid, regno, data->arch64);
/* General-purpose registers. */
if (regno == -1
|| (tdep->ppc_gp0_regnum <= regno
&& regno < tdep->ppc_gp0_regnum + ppc_num_gprs))
{
- if (arch64)
+ if (data->arch64)
{
if (!ptrace64aix (PTT_READ_GPRS, tid,
(unsigned long) gprs64, 0, NULL))
if (regno == -1 || special_register_p (gdbarch, regno))
{
- if (arch64)
+ if (data->arch64)
{
if (!ptrace64aix (PTT_READ_SPRS, tid,
(unsigned long) &sprs64, 0, NULL))
struct thread_info *thread;
pthdb_tid_t tid;
- if (!PD_TID (regcache->ptid ()))
+ /* If a new inferior is born, then its pthread debug library is yet to
+ initialised and hence has no private data. So the below if condition
+ exists. */
+
+ if (regcache->ptid ().tid () == 0)
beneath ()->fetch_registers (regcache, regno);
else
{
pthdb_context_t ctx;
uint32_t int32;
uint64_t int64;
+ struct aix_thread_variables *data;
+ data = get_thread_data_helper_for_ptid (inferior_ptid);
if (debug_aix_thread)
gdb_printf (gdb_stdlog,
/* Retrieve the thread's current context for its non-register
values. */
- status = pthdb_pthread_context (pd_session, pdtid, &ctx);
+ status = pthdb_pthread_context (data->pd_session, pdtid, &ctx);
if (status != PTHDB_SUCCESS)
error (_("aix-thread: store_registers: pthdb_pthread_context returned %s"),
pd_status2str (status));
for (i = 0; i < ppc_num_gprs; i++)
if (REG_VALID == regcache->get_register_status (tdep->ppc_gp0_regnum + i))
{
- if (arch64)
+ if (data->arch64)
{
regcache->raw_collect (tdep->ppc_gp0_regnum + i, (void *) &int64);
ctx.gpr[i] = int64;
fill_fprs (regcache, ctx.fpr);
/* Special registers (always kept in ctx as 64 bits). */
- if (arch64)
+ if (data->arch64)
{
fill_sprs64 (regcache, &ctx.iar, &ctx.msr, &ctx.cr, &ctx.lr, &ctx.ctr,
&ctx.xer, &ctx.fpscr);
ctx.fpscr = tmp_fpscr;
}
- status = pthdb_pthread_setcontext (pd_session, pdtid, &ctx);
+ status = pthdb_pthread_setcontext (data->pd_session, pdtid, &ctx);
if (status != PTHDB_SUCCESS)
error (_("aix-thread: store_registers: "
"pthdb_pthread_setcontext returned %s"),
double fprs[ppc_num_fprs];
struct ptxsprs sprs64;
struct ptsprs sprs32;
+ struct aix_thread_variables *data;
+
+ data = get_thread_data_helper_for_ptid (regcache->ptid ());
if (debug_aix_thread)
gdb_printf (gdb_stdlog,
|| (tdep->ppc_gp0_regnum <= regno
&& regno < tdep->ppc_gp0_regnum + ppc_num_fprs))
{
- if (arch64)
+ if (data->arch64)
{
/* Pre-fetch: some regs may not be in the cache. */
ptrace64aix (PTT_READ_GPRS, tid, (unsigned long) gprs64, 0, NULL);
if (regno == -1 || special_register_p (gdbarch, regno))
{
- if (arch64)
+ if (data->arch64)
{
/* Pre-fetch: some registers won't be in the cache. */
ptrace64aix (PTT_READ_SPRS, tid,
struct thread_info *thread;
pthdb_tid_t tid;
- if (!PD_TID (regcache->ptid ()))
+ if (regcache->ptid ().tid () == 0)
beneath ()->store_registers (regcache, regno);
else
{
{
target_ops *beneath = this->beneath ();
- pd_deactivate ();
+ pd_disable ();
beneath->mourn_inferior ();
}
bool
aix_thread_target::thread_alive (ptid_t ptid)
{
- if (!PD_TID (ptid))
+ if (ptid.tid () == 0)
return beneath ()->thread_alive (ptid);
/* We update the thread list every time the child stops, so all
std::string
aix_thread_target::pid_to_str (ptid_t ptid)
{
- if (!PD_TID (ptid))
+ if (ptid.tid () == 0)
return beneath ()->pid_to_str (ptid);
return string_printf (_("Thread %s"), pulongest (ptid.tid ()));
pthdb_detachstate_t detachstate;
int cancelpend;
static char *ret = NULL;
+ struct aix_thread_variables *data;
+
+ data = get_thread_data_helper_for_ptid (thread->ptid);
- if (!PD_TID (thread->ptid))
+ if (thread->ptid.tid () == 0)
return NULL;
string_file buf;
/* i18n: Like "thread-identifier %d, [state] running, suspended" */
buf.printf (_("tid %d"), (int)tid);
- status = pthdb_pthread_state (pd_session, pdtid, &state);
+ status = pthdb_pthread_state (data->pd_session, pdtid, &state);
if (status != PTHDB_SUCCESS)
state = PST_NOTSUP;
buf.printf (", %s", state2str (state));
- status = pthdb_pthread_suspendstate (pd_session, pdtid,
+ status = pthdb_pthread_suspendstate (data->pd_session, pdtid,
&suspendstate);
if (status == PTHDB_SUCCESS && suspendstate == PSS_SUSPENDED)
/* i18n: Like "Thread-Id %d, [state] running, suspended" */
buf.printf (_(", suspended"));
- status = pthdb_pthread_detachstate (pd_session, pdtid,
+ status = pthdb_pthread_detachstate (data->pd_session, pdtid,
&detachstate);
if (status == PTHDB_SUCCESS && detachstate == PDS_DETACHED)
/* i18n: Like "Thread-Id %d, [state] running, detached" */
buf.printf (_(", detached"));
- pthdb_pthread_cancelpend (pd_session, pdtid, &cancelpend);
+ pthdb_pthread_cancelpend (data->pd_session, pdtid, &cancelpend);
if (status == PTHDB_SUCCESS && cancelpend)
/* i18n: Like "Thread-Id %d, [state] running, cancel pending" */
buf.printf (_(", cancel pending"));