summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2007-10-10 13:58:43 -0400
committerFrank Ch. Eigler <fche@elastic.org>2007-10-10 13:58:43 -0400
commit36c24cdba10c3d20638c78b52cc8e327a3a0b82d (patch)
tree24cbeb006365fdaa21dbf9cf3b44eae055684123
parent38d7fc30b108ec4a9e74ddb33d945cce1bd5c4c6 (diff)
parentd319669c3f77a3e451f1cad845471433e6d0dbfa (diff)
downloadsystemtap-steved-36c24cdba10c3d20638c78b52cc8e327a3a0b82d.tar.gz
systemtap-steved-36c24cdba10c3d20638c78b52cc8e327a3a0b82d.tar.xz
systemtap-steved-36c24cdba10c3d20638c78b52cc8e327a3a0b82d.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
-rw-r--r--ChangeLog8
-rw-r--r--runtime/ChangeLog4
-rw-r--r--runtime/staprun/ChangeLog7
-rw-r--r--runtime/staprun/common.c19
-rw-r--r--runtime/staprun/ctl.c3
-rw-r--r--runtime/staprun/relay.c6
-rw-r--r--runtime/staprun/relay_old.c12
-rw-r--r--runtime/staprun/staprun.h1
-rw-r--r--runtime/uprobes/uprobes.c51
-rw-r--r--runtime/user/ChangeLog62
-rw-r--r--runtime/user/README3
-rw-r--r--runtime/user/alloc.c52
-rw-r--r--runtime/user/copy.c7
-rw-r--r--runtime/user/emul.h121
-rw-r--r--runtime/user/io.c80
-rw-r--r--runtime/user/print.c96
-rwxr-xr-xruntime/user/recreate_links15
-rw-r--r--runtime/user/runtime.h56
-rw-r--r--runtime/user/test.h247
-rw-r--r--tapset/ChangeLog33
-rw-r--r--tapset/aux_syscalls.stp28
-rw-r--r--tapset/queue_stats.stp1
-rw-r--r--tapset/rpc.stp4
-rw-r--r--tapset/syscalls2.stp2
-rw-r--r--testsuite/systemtap.syscall/ChangeLog11
-rw-r--r--testsuite/systemtap.syscall/rt_signal.c17
-rw-r--r--testsuite/systemtap.syscall/signal.c46
27 files changed, 202 insertions, 790 deletions
diff --git a/ChangeLog b/ChangeLog
index 9c176ae7..4c1801d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-10-09 Jim Keniston <jkenisto@us.ibm.com>
+
+ PR 5083
+ * runtime/uprobes/uprobes.c: Adjust module ref-count
+ when creating or removing uprobe_process, so "rmmod
+ --wait uprobes" waits as needed until uretprobed
+ functions return.
+
2007-10-08 Jim Keniston <jkenisto@us.ibm.com>
PR 5079
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index a442eb18..65702a00 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,7 @@
+2007-10-09 Martin Hunt <hunt@redhat.com>
+
+ * user/*: Removed obsolete userspace test files.
+
2007-10-02 Frank Ch. Eigler <fche@elastic.org>
PR 5041
diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog
index cebaeb2c..4e23c424 100644
--- a/runtime/staprun/ChangeLog
+++ b/runtime/staprun/ChangeLog
@@ -1,3 +1,10 @@
+2007-10-09 Martin Hunt <hunt@redhat.com>
+
+ * common.c (set_clexec): New.
+ * staprun.h: Add prototype for set_clexec.
+ * relay*.c, ctl.c: Call set_clexec after
+ file opens.
+
2007-09-14 Martin Hunt <hunt@redhat.com>
* ctl.c (init_ctl_channel): Return 1 if the ctl file opened
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index d3f8835a..47778efd 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -315,3 +315,22 @@ int send_request(int type, void *data, int len)
memcpy(&buf[4], data, len);
return write(control_channel, buf, len+4);
}
+
+/*
+ * set FD_CLOEXEC for any file descriptor
+ */
+int set_clexec(int fd)
+{
+ int val;
+ if ((val = fcntl(fd, F_GETFD, 0)) < 0)
+ goto err;
+
+ if ((val = fcntl(fd, F_SETFD, val | FD_CLOEXEC)) < 0)
+ goto err;
+
+ return 0;
+err:
+ perr("fcntl failed");
+ close(fd);
+ return -1;
+}
diff --git a/runtime/staprun/ctl.c b/runtime/staprun/ctl.c
index d0b07260..7fe57206 100644
--- a/runtime/staprun/ctl.c
+++ b/runtime/staprun/ctl.c
@@ -36,6 +36,9 @@ int init_ctl_channel(void)
perr("Couldn't open control channel '%s'", buf);
return -1;
}
+ if (set_clexec(control_channel) < 0)
+ return -1;
+
return old_transport;
}
diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c
index 30c4ce1e..538d027c 100644
--- a/runtime/staprun/relay.c
+++ b/runtime/staprun/relay.c
@@ -148,7 +148,7 @@ int init_relayfs(void)
return -1;
dbug(2, "attempting to open %s\n", buf);
relay_fd[i] = open(buf, O_RDONLY | O_NONBLOCK);
- if (relay_fd[i] < 0)
+ if (relay_fd[i] < 0 || set_clexec(relay_fd[i]) < 0)
break;
}
ncpus = i;
@@ -184,6 +184,8 @@ int init_relayfs(void)
perr("Couldn't open output file %s", buf);
return -1;
}
+ if (set_clexec(out_fd[i]) < 0)
+ return -1;
}
} else {
/* stream mode */
@@ -193,6 +195,8 @@ int init_relayfs(void)
perr("Couldn't open output file %s", outfile_name);
return -1;
}
+ if (set_clexec(out_fd[i]) < 0)
+ return -1;
} else
out_fd[0] = STDOUT_FILENO;
diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c
index 3f65acbb..f138aee5 100644
--- a/runtime/staprun/relay_old.c
+++ b/runtime/staprun/relay_old.c
@@ -86,7 +86,7 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p
return -1;
dbug(2, "Opening %s.\n", tmp);
relay_fd[cpu] = open(tmp, O_RDONLY | O_NONBLOCK);
- if (relay_fd[cpu] < 0) {
+ if (relay_fd[cpu] < 0 || set_clexec(relay_fd[cpu]) < 0) {
relay_fd[cpu] = 0;
return 0;
}
@@ -99,6 +99,10 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p
perr("Couldn't open proc file %s", tmp);
goto err1;
}
+ if (set_clexec(relay_fd[cpu]) < 0) {
+ relay_fd[cpu] = 0;
+ return -1;
+ }
if (outfile_name) {
/* special case: for testing we sometimes want to
@@ -118,6 +122,10 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p
perr("Couldn't open output file %s", tmp);
goto err2;
}
+ if (set_clexec(fileno(percpu_tmpfile[cpu])) < 0) {
+ perr("Couldn't open output file %s", tmp);
+ goto err2;
+ }
total_bufsize = subbuf_size * n_subbufs;
relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ,
@@ -243,7 +251,7 @@ int init_oldrelayfs(void)
if (!bulkmode) {
if (outfile_name) {
out_fd[0] = open (outfile_name, O_CREAT|O_TRUNC|O_WRONLY, 0666);
- if (out_fd[0] < 0) {
+ if (out_fd[0] < 0 || set_clexec(out_fd[0]) < 0) {
perr("Couldn't open output file '%s'", outfile_name);
return -1;
}
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index 1b0f3221..685de294 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -152,6 +152,7 @@ void parse_args(int argc, char **argv);
void usage(char *prog);
void parse_modpath(const char *);
void setup_signals(void);
+int set_clexec(int fd);
/*
* variables
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c
index 16c5e046..01b40670 100644
--- a/runtime/uprobes/uprobes.c
+++ b/runtime/uprobes/uprobes.c
@@ -475,10 +475,16 @@ static void uprobe_free_process(struct uprobe_process *uproc)
* Decrement uproc's ref count. If it's zero, free uproc and return 1.
* Else return 0. If uproc is locked, don't call this; use
* uprobe_decref_process().
+ *
+ * If we free uproc, we also decrement the ref-count on the uprobes
+ * module, if any. If somebody is doing "rmmod --wait uprobes", this
+ * function could schedule removal of the module. Therefore, don't call
+ * this function and then sleep in uprobes code, unless you know you'll
+ * return with the module ref-count > 0.
*/
static int uprobe_put_process(struct uprobe_process *uproc)
{
- int ret = 0;
+ int freed = 0;
if (atomic_dec_and_test(&uproc->refcount)) {
lock_uproc_table();
down_write(&uproc->rwsem);
@@ -491,11 +497,13 @@ static int uprobe_put_process(struct uprobe_process *uproc)
up_write(&uproc->rwsem);
} else {
uprobe_free_process(uproc);
- ret = 1;
+ freed = 1;
}
unlock_uproc_table();
}
- return ret;
+ if (freed)
+ module_put(THIS_MODULE);
+ return freed;
}
static struct uprobe_kimg *uprobe_mk_kimg(struct uprobe *u)
@@ -842,10 +850,18 @@ int register_uprobe(struct uprobe *u)
if (uproc)
unlock_uproc_table();
else {
+ /* Creating a new uprobe_process. Ref-count the module. */
+ if (!try_module_get(THIS_MODULE)) {
+ /* uprobes.ko is being removed. */
+ ret = -ENOSYS;
+ unlock_uproc_table();
+ goto fail_tsk;
+ }
uproc = uprobe_mk_process(p);
if (IS_ERR(uproc)) {
ret = (int) PTR_ERR(uproc);
unlock_uproc_table();
+ module_put(THIS_MODULE);
goto fail_tsk;
}
/* Hold uproc_mutex until we've added uproc to uproc_table. */
@@ -955,6 +971,7 @@ fail_uproc:
if (uproc_is_new) {
uprobe_free_process(uproc);
unlock_uproc_table();
+ module_put(THIS_MODULE);
} else {
up_write(&uproc->rwsem);
uprobe_put_process(uproc);
@@ -1063,8 +1080,9 @@ static struct task_struct *find_surviving_thread(struct uprobe_process *uproc)
/*
* Run all the deferred_registrations previously queued by the current utask.
- * Runs with no locks or mutexes held. The current utask could disappear
- * as the result of unregister_u*probe() called here.
+ * Runs with no locks or mutexes held. The current utask's uprobe_process
+ * is ref-counted, so they won't disappear as the result of
+ * unregister_u*probe() called here.
*/
static void uprobe_run_def_regs(struct list_head *drlist)
{
@@ -1577,7 +1595,7 @@ static u32 uprobe_report_signal(struct utrace_attached_engine *engine,
u32 ret;
unsigned long probept;
int hit_uretprobe_trampoline = 0;
- LIST_HEAD(def_reg_list);
+ int registrations_deferred = 0;
utask = rcu_dereference((struct uprobe_task *)engine->data);
BUG_ON(!utask);
@@ -1673,12 +1691,16 @@ bkpt_done:
utask->active_probe = NULL;
- /*
- * The deferred_registrations list accumulates in utask,
- * but utask could go away when we uprobe_run_def_regs.
- * So switch the list head to a local variable.
- */
- list_splice_init(&utask->deferred_registrations, &def_reg_list);
+ if (!list_empty(&utask->deferred_registrations)) {
+ /*
+ * Make sure utask doesn't go away before we run
+ * the deferred registrations. This also keeps
+ * the module from getting unloaded before we're
+ * ready.
+ */
+ registrations_deferred = 1;
+ uprobe_get_process(uproc);
+ }
ret = UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN
| UTRACE_ACTION_NEWSTATE;
@@ -1698,7 +1720,10 @@ bkpt_done:
*/
uprobe_put_process(uproc);
- uprobe_run_def_regs(&def_reg_list);
+ if (registrations_deferred) {
+ uprobe_run_def_regs(&utask->deferred_registrations);
+ uprobe_put_process(uproc);
+ }
break;
default:
goto no_interest;
diff --git a/runtime/user/ChangeLog b/runtime/user/ChangeLog
deleted file mode 100644
index 90041891..00000000
--- a/runtime/user/ChangeLog
+++ /dev/null
@@ -1,62 +0,0 @@
-2006-09-26 David Smith <dsmith@redhat.com>
-
- * io.c: Changed 'stpd' references to 'staprun'.
- * print.c: Ditto.
-
-2006-03-30 Martin Hunt <hunt@redhat.com>
-
- * emul.h (kmalloc_node): New.
-
-2006-01-25 Martin Hunt <hunt@redhat.com>
-
- * alloc.c (_stp_alloc_percpu): New function.
- (_stp_free_percpu): New function.
-
-2005-12-14 Martin Hunt <hunt@redhat.com>
-
- * emul.h: Add fake spinlock funcs.
-
-2005-12-07 Martin Hunt <hunt@redhat.com>
-
- * alloc.c: Remove all unused functions.
- * io.c: Add vprintf() prototype.
-
-2005-11-29 Martin Hunt <hunt@redhat.com>
-
- * recreate_links: Remove links to deleted files.
-
-2005-11-08 Martin Hunt <hunt@redhat.com>
-
- * recreate_links: Add link to pmap-gen.c
- * print.c (next_fmt): Remove unneeded dbug().
- * alloc.c: Update to reflect changes to runtime/alloc.c.
-
-2005-10-26 Martin Hunt <hunt@redhat.com>
-
- * recreate_links: Add link to map-gen.c.
-
-2005-09-09 Martin Hunt <hunt@redhat.com>
-
- * runtime.h: Add arith.c
- * recreate_links: Add arith.c
- * emul.h: Define jiffies so arith.c will compile.
-
-2005-08-31 Martin Hunt <hunt@redhat.com>
-
- * emul.h (_stp_kallsyms_lookup): Renamed from kallsyms_lookup.
- * runtime.h: Add prototype for exit();
- * copy.c: New file. Just some empty functions.
-
-2005-08-19 Martin Hunt <hunt@redhat.com>
-
- * runtime.h: Include io.c.
-
-2005-07-14 Frank Ch. Eigler <fche@redhat.com>
-
- * alloc.c (_stp_error): Rename, to avoid name collision with ../io.c.
-
-2005-06-22 Martin Hunt <hunt@redhat.com>
-
- * runtime.h: Include config.h first then redefine CONFIG_SMP
- and NR_CPUS.
-
diff --git a/runtime/user/README b/runtime/user/README
deleted file mode 100644
index b5f8f81a..00000000
--- a/runtime/user/README
+++ /dev/null
@@ -1,3 +0,0 @@
-These files are for user-space testing of SystemTap code.
-
-You need to run ./recreate_links here before running tests.
diff --git a/runtime/user/alloc.c b/runtime/user/alloc.c
deleted file mode 100644
index 361e7d98..00000000
--- a/runtime/user/alloc.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef _ALLOC_C_
-#define _ALLOC_C_
-
-/* emulated memory allocation functions */
-
-void *malloc(size_t size);
-void free(void *ptr);
-
-enum errorcode { ERR_NONE=0, ERR_NO_MEM };
-enum errorcode _stp_errorcode = ERR_NONE;
-
-void *__kmalloc(size_t size, gfp_t flags)
-{
- return malloc(size);
-}
-
-void *_stp_alloc_percpu(size_t size)
-{
- int i;
- struct percpu_data *pdata = malloc(sizeof (*pdata));
- if (!pdata)
- return NULL;
-
- for_each_cpu(i) {
- pdata->ptrs[i] = malloc(size);
- if (!pdata->ptrs[i])
- goto unwind_oom;
- memset(pdata->ptrs[i], 0, size);
- }
-
- /* Catch derefs w/o wrappers */
- return (void *) (~(unsigned long) pdata);
-
-unwind_oom:
- while (--i >= 0) {
- free(pdata->ptrs[i]);
- }
- free(pdata);
- return NULL;
-}
-
-void _stp_free_percpu(const void *objp)
-{
- int i;
- struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
-
- for_each_cpu(i)
- free(p->ptrs[i]);
- free(p);
-}
-
-#endif /* _ALLOC_C_ */
diff --git a/runtime/user/copy.c b/runtime/user/copy.c
deleted file mode 100644
index 2186aa59..00000000
--- a/runtime/user/copy.c
+++ /dev/null
@@ -1,7 +0,0 @@
-long
-_stp_strncpy_from_user(char *dst, const char __user *src, long count)
-{
- return 0;
-}
-
-void __get_user_4(void) {};
diff --git a/runtime/user/emul.h b/runtime/user/emul.h
deleted file mode 100644
index 63938b08..00000000
--- a/runtime/user/emul.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#define kmalloc(size,flags) malloc(size)
-#define kmalloc(size,flags) malloc(size)
-#define kmalloc_node(size,flags,cpu) malloc(size)
-
-#define kfree(ptr) free(ptr)
-
-int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
-{
- int i;
- i=vsnprintf(buf,size,fmt,args);
- return (i >= size) ? (size - 1) : i;
-}
-
-//#define _stp_log printf
-
-/* cpu emulation */
-#undef smp_processor_id
-#undef get_cpu
-#undef put_cpu
-#undef for_each_cpu
-#define for_each_cpu(cpu) \
- for (cpu = 0; cpu < NR_CPUS; cpu++)
-
-int _processor_number = 0;
-#define smp_processor_id() _processor_number
-#define get_cpu() _processor_number
-#define put_cpu() ;
-
-#include "alloc.c"
-void *__alloc_percpu(size_t size, size_t align)
-{
- int i;
- struct percpu_data *pdata = malloc(sizeof (*pdata));
-
- if (!pdata)
- return NULL;
-
- for (i = 0; i < NR_CPUS; i++) {
- pdata->ptrs[i] = malloc(size);
-
- if (!pdata->ptrs[i])
- return NULL;
-
- memset(pdata->ptrs[i], 0, size);
- }
-
- /* Catch derefs w/o wrappers */
- return (void *) (~(unsigned long) pdata);
-}
-
-void
-free_percpu(const void *objp)
-{
- int i;
- struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
-
- for (i = 0; i < NR_CPUS; i++) {
- free(p->ptrs[i]);
- }
- free(p);
-}
-
-#include <stdarg.h>
-unsigned long strtoul(const char *nptr, char **endptr, int base);
-#define simple_strtoul strtoul
-
-const char *_stp_kallsyms_lookup (unsigned long addr,
- unsigned long *symbolsize,
- unsigned long *offset,
- char **modname,
- char *namebuf)
-{
- static char buf[32];
- sprintf (namebuf, "foobar");
- sprintf (buf, "foobar_mod");
- *offset = 1;
- modname = (char **)&buf;
- return namebuf;
-}
-
-int __lockfunc _spin_trylock(spinlock_t *lock)
-{
- return 1;
-}
-
-void __lockfunc _spin_lock(spinlock_t *lock)
-{
-}
-
-void __lockfunc _spin_unlock(spinlock_t *lock)
-{
-}
-
-size_t strlcat(char *dest, const char *src, size_t count)
-{
- size_t dsize = strlen(dest);
- size_t len = strlen(src);
- size_t res = dsize + len;
-
- /* This would be a bug */
- BUG_ON(dsize >= count);
-
- dest += dsize;
- count -= dsize;
- if (len >= count)
- len = count-1;
- memcpy(dest, src, len);
- dest[len] = 0;
- return res;
-}
-size_t strlcpy(char *dest, const char *src, size_t size)
-{
- size_t ret = strlen(src);
-
- if (size) {
- size_t len = (ret >= size) ? size - 1 : ret;
- memcpy(dest, src, len);
- dest[len] = '\0';
- }
- return ret;
-}
diff --git a/runtime/user/io.c b/runtime/user/io.c
deleted file mode 100644
index ecc3d050..00000000
--- a/runtime/user/io.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* I/O for printing warnings, errors and debug messages
- * Copyright (C) 2005 Red Hat Inc.
- *
- * This file is part of systemtap, and is free software. You can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License (GPL); either version 2, or (at your option) any
- * later version.
- */
-
-#ifndef _IO_C_
-#define _IO_C_
-int vprintf(const char *format, va_list ap);
-
-/** Logs Data.
- * This function sends the message immediately to staprun. It
- * will also be sent over the bulk transport (relayfs) if it is
- * being used. If the last character is not a newline, then one
- * is added. This function is not as efficient as _stp_printf()
- * and should only be used for urgent messages. You probably want
- * dbug(), or _stp_warn().
- * @param fmt A variable number of args.
- * @todo Evaluate if this function is necessary.
- */
-void _stp_log (const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vprintf (fmt, args);
- va_end(args);
-}
-
-/** Prints warning.
- * This function sends a warning message immediately to staprun. It
- * will also be sent over the bulk transport (relayfs) if it is
- * being used. If the last character is not a newline, then one
- * is added.
- * @param fmt A variable number of args.
- */
-void _stp_warn (const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vprintf (fmt, args);
- va_end(args);
-}
-
-/** Exits and unloads the module.
- * This function sends a signal to staprun to tell it to
- * unload the module and exit. The module will not be
- * unloaded until after the current probe returns.
- * @note Be careful to not treat this like the Linux exit()
- * call. You should probably call return immediately after
- * calling _stp_exit().
- */
-void _stp_exit (void)
-{
- exit (-1);
-}
-
-/** Prints error message and exits.
- * This function sends an error message immediately to staprun. It
- * will also be sent over the bulk transport (relayfs) if it is
- * being used. If the last character is not a newline, then one
- * is added.
- *
- * After the error message is displayed, the module will be unloaded.
- * @param fmt A variable number of args.
- * @sa _stp_exit().
- */
-void _stp_error (const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vprintf (fmt, args);
- va_end(args);
- _stp_exit();
-}
-
-/** @} */
-#endif /* _IO_C_ */
diff --git a/runtime/user/print.c b/runtime/user/print.c
deleted file mode 100644
index acc938b9..00000000
--- a/runtime/user/print.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifndef _PRINT_C_ /* -*- linux-c -*- */
-#define _PRINT_C_
-
-#include <linux/config.h>
-#include <stdio.h>
-
-/** @file print.c
- * @addtogroup print Print Buffer
- * Print Buffer Functions.
- * The print buffer is for collecting output to send to the user daemon.
- * This is a per-cpu static buffer. The buffer is sent when
- * _stp_print_flush() is called.
- *
- * The reason to do this is to allow multiple small prints to be combined then
- * timestamped and sent together to staprun. It could flush automatically on newlines,
- * but what about stack traces which span many lines? So try this and see how it works for us.
- * @{
- */
-
-/** Size of buffer, not including terminating NULL */
-#ifndef STP_PRINT_BUF_LEN
-#define STP_PRINT_BUF_LEN 8000
-#endif
-
-#include "string.h"
-#include "io.c"
-
-static int _stp_pbuf_len[NR_CPUS];
-
-#define STP_PRINT_BUF_START 0
-static char _stp_pbuf[NR_CPUS][STP_PRINT_BUF_LEN + 1];
-
-void _stp_print_flush (void)
-{
- int cpu = smp_processor_id();
- char *buf = &_stp_pbuf[cpu][0];
- int len = _stp_pbuf_len[cpu];
-
- if (len == 0)
- return;
-
- fwrite (buf, len, 1, stdout);
- _stp_pbuf_len[cpu] = 0;
-}
-
-#define _stp_printf(args...) _stp_sprintf(_stp_stdout,args)
-#define _stp_vprintf(fmt,args) _stp_vsprintf(_stp_stdout,fmt,args)
-#define _stp_print_cstr(str) _stp_string_cat_cstr(_stp_stdout,str)
-#define _stp_print_string(str) _stp_string_cat_string(_stp_stdout,str)
-/** Write a String or C string into the print buffer.
- * This macro selects the proper function to call.
- * @param str A String or C string (char *)
- * @sa _stp_print_cstr _stp_print_string
- */
-
-
-/* Print stuff until a format specification is found. */
-/* Return pointer to that. */
-static char *next_fmt(char *fmt, int *num)
-{
- char *f = fmt;
- int in_fmt = 0;
- *num = 0;
- while (*f) {
- if (in_fmt) {
- if (*f == '%') {
- _stp_string_cat_char(_stp_stdout,'%');
- in_fmt = 0;
- } else if (*f > '0' && *f <= '9') {
- *num = *f - '0';
- f++;
- return f;
- } else
- return f;
- } else if (*f == '%')
- in_fmt = 1;
- else
- _stp_string_cat_char(_stp_stdout,*f);
- f++;
- }
- return f;
-}
-
-#define _stp_print(str) \
- ({ \
- if (__builtin_types_compatible_p (typeof (str), char[])) { \
- char *x = (char *)str; \
- _stp_string_cat_cstr(_stp_stdout,x); \
- } else { \
- String x = (String)str; \
- _stp_string_cat_string(_stp_stdout,x); \
- } \
- })
-
-/** @} */
-#endif /* _PRINT_C_ */
diff --git a/runtime/user/recreate_links b/runtime/user/recreate_links
deleted file mode 100755
index 5b182480..00000000
--- a/runtime/user/recreate_links
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-ln -s ../map.h .
-ln -s ../map.c .
-ln -s ../map-stat.c .
-ln -s ../string.c .
-ln -s ../string.h .
-ln -s ../sym.c .
-ln -s ../counter.c .
-ln -s ../stat.c .
-ln -s ../stat.h .
-ln -s ../stat-common.c .
-ln -s ../arith.c .
-ln -s ../map-gen.c .
-ln -s ../pmap-gen.c .
diff --git a/runtime/user/runtime.h b/runtime/user/runtime.h
deleted file mode 100644
index 79a9dc22..00000000
--- a/runtime/user/runtime.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _RUNTIME_H_
-#define _RUNTIME_H_
-/** @file runtime.h
- * @brief Main include file for runtime functions.
- */
-
-#define _STP_TEST_ 1
-
-#define __KERNEL__
-#include <linux/config.h>
-#undef CONFIG_NR_CPUS
-#undef CONFIG_SMP
-#define CONFIG_NR_CPUS 8
-#define CONFIG_SMP
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/init.h>
-#include <linux/hash.h>
-#include <linux/kprobes.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/time.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-#include <linux/kallsyms.h>
-#include <linux/percpu.h>
-
-
-#ifdef DEBUG
-#define dbug(args...) \
- { \
- printf("%s:%d: ", __FUNCTION__, __LINE__); \
- printf(args); \
- }
-#else
-#define dbug(args...) ;
-#endif
-
-#include "emul.h"
-
-#undef memcpy
-#define memcpy __builtin_memcpy
-
-void exit(int status);
-
-#define NEED_STAT_LOCKS 0
-#define NEED_COUNTER_LOCKS 0
-
-#include "io.c"
-#include "print.c"
-#include "string.c"
-#include "arith.c"
-#include "alloc.c"
-
-#endif /* _RUNTIME_H_ */
diff --git a/runtime/user/test.h b/runtime/user/test.h
deleted file mode 100644
index 3139cfec..00000000
--- a/runtime/user/test.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/* include file for testing maps without running in the kernel */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-
-static inline unsigned long hash_long(unsigned long val, unsigned int bits)
-{
- unsigned long hash = val;
-
-#if __WORDSIZE == 64
- /* Sigh, gcc can't optimise this alone like it does for 32 bits. */
- unsigned long n = hash;
- n <<= 18;
- hash -= n;
- n <<= 33;
- hash -= n;
- n <<= 3;
- hash += n;
- n <<= 3;
- hash -= n;
- n <<= 4;
- hash += n;
- n <<= 2;
- hash += n;
-#else
- /* On some cpus multiply is faster, on others gcc will do shifts */
- hash *= 0x9e370001UL;
-#endif
-
- /* High bits are more random, so use them. */
- return hash >> (8*sizeof(long) - bits);
-}
-
-
-#define STRINGLEN 128
-#define HASH_ELEM_NUM 5000
-#define HASH_TABLE_BITS 8
-#define HASH_TABLE_SIZE (1<<HASH_TABLE_BITS)
-#define BUCKETS 16 /* largest histogram width */
-#define PK 0 /* sprinkle debug printk into probe code */
-
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add_tail(list, head);
-}
-
-
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next, **pprev;
-};
-#define HLIST_HEAD_INIT { .first = NULL }
-#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
-#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
-#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
- struct hlist_node *first = h->first;
- n->next = first;
- if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
-}
-
-#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos; pos = pos->next)
-
-#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
-static inline void __hlist_del(struct hlist_node *n)
-{
- struct hlist_node *next = n->next;
- struct hlist_node **pprev = n->pprev;
- *pprev = next;
- if (next)
- next->pprev = pprev;
-}
-
-static inline void hlist_del(struct hlist_node *n)
-{
- __hlist_del(n);
- n->next = LIST_POISON1;
- n->pprev = LIST_POISON2;
-}
-
-static inline void hlist_del_init(struct hlist_node *n)
-{
- if (n->pprev) {
- __hlist_del(n);
- INIT_HLIST_NODE(n);
- }
-}
-
-static inline void hlist_add_before(struct hlist_node *n,
- struct hlist_node *next)
-{
- n->pprev = next->pprev;
- n->next = next;
- next->pprev = &n->next;
- *(n->pprev) = n;
-}
-
-#define GFP_ATOMIC 0
-
-void *kmalloc (size_t len, int flags)
-{
- return malloc (len);
-}
-
-void *vmalloc (size_t len)
-{
- return malloc (len);
-}
-
-#define kfree(x) free(x)
-#define vfree(x) free(x)
-
-/***** END OF KERNEL STUFF ********/
-
-#ifdef DEBUG
-#define dbug(args...) \
- { \
- printf("%s:%d: ", __FUNCTION__, __LINE__); \
- printf(args); \
- }
-#else
-#define dbug(args...) ;
-#endif
-
-#define dlog(args...) printf(args);
-#define _stp_log(args...) printf(args);
-
-#define STP_NUM_STRINGS 5
-#define NR_CPUS 2
-
-int smp_processor_id(void)
-{
- return 0;
-}
-
-#define vscnprintf vsnprintf
-
-#include "../alloc.c"
-#include "../map.h"
-#include "../map.c"
-
-/* handle renamed functions */
-#define map_new _stp_map_new
-#define map_key_del _stp_map_key_del
-#define map_start _stp_map_start
-#define map_iter _stp_map_iter
-#define map_get_str _stp_map_get_str
-#define map_set_int64 _stp_map_set_int64
-#define map_get_int64 _stp_map_get_int64
-#define map_key_str_str _stp_map_key_str_str
-#define map_key_str _stp_map_key_str
-#define map_key_long _stp_map_key_long
-#define map_key_long_long _stp_map_key_long_long
-#define map_set_stat _stp_map_set_stat
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index b325a627..287b0823 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,36 @@
+2007-10-10 Martin Hunt <hunt@redhat.com>
+
+ * aux_syscalls.stp (_stp_lookup_str): When defaulting
+ to a numeric value, append, don't overwrite.
+
+2007-10-10 Zhaolei <zhaolei@cn.fujitsu.com>
+
+ From Lai Jiangshan <laijs@cn.fujitsu.com>
+ * aux_syscalls.stp (_stp_lookup_or_str) redirect to _stp_lookup_str
+ if val is 0.
+
+2007-10-09 Mike Mason <mmlnx@us.ibm.com>
+
+ * rpc.stp: Replaced atomic_read()'s with kread()'s
+
+2007-10-09 Martin Hunt <hunt@redhat.com>
+ PR5153
+ * aux_syscalls.stp (_sighandler_str): No
+ sa_restorer field for IA64.
+
+2007-10-09 Martin Hunt <hunt@redhat.com>
+
+ * syscalls2.stp (sys_signal): Call
+ _sighandler_str().
+
+ * aux_syscalls.stp (_stp_sigset_str): Don't
+ include SIG_0.
+ (_sighandler_str): New.
+
+2007-10-09 Zhaolei <zhaolei@cn.fujitsu.com>
+
+ * queue_stats.stp (qsq_start): Add destruction for qs_utime.
+
2007-10-09 Zhaolei <zhaolei@cn.fujitsu.com>
From Cai Fei <caifei@cn.fujitsu.com>
diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp
index 3818ae75..05c7dc98 100644
--- a/tapset/aux_syscalls.stp
+++ b/tapset/aux_syscalls.stp
@@ -1520,7 +1520,7 @@ typedef struct {
void _stp_lookup_str(const _stp_val_array * const array, long val, char *ptr, int len)
{
- int i = 0;
+ int i = 0, slen;
while (array[i].name) {
if (array[i].val == val) {
strlcat (ptr, array[i].name, len);
@@ -1528,11 +1528,18 @@ void _stp_lookup_str(const _stp_val_array * const array, long val, char *ptr, in
}
i++;
}
- snprintf(ptr, len, "0x%lx", val);
+ slen = strlen(ptr);
+ _stp_snprintf(ptr + slen, len - slen, "0x%lx", val);
}
void _stp_lookup_or_str(const _stp_val_array * const array, long val, char *ptr, int len)
{
int i = 0, flag = 0;
+
+ if (val == 0) {
+ _stp_lookup_str(array, val, ptr, len);
+ return;
+ }
+
while (array[i].name) {
if (array[i].val & val) {
if (flag)
@@ -1587,7 +1594,7 @@ void _stp_sigset_str(sigset_t *mask, char *ptr, int len)
const _stp_val_array * const array = _stp_signal_list;
int i = 0, flag = 0;
while (array[i].name) {
- if (sigismember(mask, array[i].val)) {
+ if (array[i].val && sigismember(mask, array[i].val)) {
if (flag)
strlcat(ptr, "|", len);
strlcat(ptr, array[i].name, len);
@@ -1785,6 +1792,17 @@ function get_mmap_args:string (args:long)
strlcpy (THIS->__retvalue, "UNKNOWN", MAXSTRINGLEN);
%}
+
+function _sighandler_str:string(uaddr:long)
+%{ /* pure */
+ static const _stp_val_array const _stp_sa_handler_list[] = {
+ {0, "SIG_DFL"},
+ {1, "SIG_IGN"},
+ {0, NULL}
+ };
+ _stp_lookup_str(_stp_sa_handler_list, (long)THIS->uaddr, THIS->__retvalue, MAXSTRINGLEN);
+%}
+
function _struct_sigaction_u:string(uaddr:long)
%{ /* pure */
static const _stp_val_array const _stp_sa_handler_list[] = {
@@ -1818,8 +1836,12 @@ function _struct_sigaction_u:string(uaddr:long)
strlcat (THIS->__retvalue, ", ", MAXSTRINGLEN);
_stp_lookup_or_str(_stp_sa_flags_list, act.sa_flags, THIS->__retvalue, MAXSTRINGLEN);
strlcat (THIS->__retvalue, ", ", MAXSTRINGLEN);
+#if !defined (__ia64__)
len = strlen(THIS->__retvalue);
_stp_snprintf(THIS->__retvalue + len, MAXSTRINGLEN - len, "0x%lx, [", (long)act.sa_restorer);
+#else
+ strlcat (THIS->__retvalue, "[", MAXSTRINGLEN);
+#endif
_stp_sigset_str(&act.sa_mask, THIS->__retvalue, MAXSTRINGLEN);
strlcat (THIS->__retvalue, "]", MAXSTRINGLEN);
}
diff --git a/tapset/queue_stats.stp b/tapset/queue_stats.stp
index 75407fee..9d89903c 100644
--- a/tapset/queue_stats.stp
+++ b/tapset/queue_stats.stp
@@ -59,6 +59,7 @@ function qsq_start (qname) { # reset statistics for new baseline
delete qs_wtime[qname]
delete qs_wlentime[qname]
delete qs_dcount[qname]
+ delete qs_utime[qname]
qs_stime[qname] = qs_time ()
}
diff --git a/tapset/rpc.stp b/tapset/rpc.stp
index 3d17d221..eecdb796 100644
--- a/tapset/rpc.stp
+++ b/tapset/rpc.stp
@@ -948,7 +948,7 @@ function clones_from_clnt:long(clnt:long)
%{ /* pure */
struct rpc_clnt *clnt = (struct rpc_clnt *)(long)THIS->clnt;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
- THIS->__retvalue = atomic_read(&clnt->cl_count); /* FIXME: deref hazard! */
+ THIS->__retvalue = kread(&(clnt->cl_count));
#else
THIS->__retvalue = -1;
#endif
@@ -958,7 +958,7 @@ function tasks_from_clnt:long(clnt:long)
%{ /* pure */
struct rpc_clnt *clnt = (struct rpc_clnt *)(long)THIS->clnt;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
- THIS->__retvalue = atomic_read(&clnt->cl_users); /* FIXME: deref hazard! */
+ THIS->__retvalue = kread(&(clnt->cl_users));
#else
THIS->__retvalue = -1;
#endif
diff --git a/tapset/syscalls2.stp b/tapset/syscalls2.stp
index acb2c137..e702bbcd 100644
--- a/tapset/syscalls2.stp
+++ b/tapset/syscalls2.stp
@@ -2122,7 +2122,7 @@ probe syscall.signal = kernel.function("sys_signal") ? {
name = "signal"
sig = $sig
handler = $handler
- argstr = sprintf("%s, %p", _signal_name($sig), $handler)
+ argstr = sprintf("%s, %s", _signal_name($sig), _sighandler_str($handler))
}
probe syscall.signal.return = kernel.function("sys_signal").return ? {
name = "signal"
diff --git a/testsuite/systemtap.syscall/ChangeLog b/testsuite/systemtap.syscall/ChangeLog
index 9811a707..61c72bc2 100644
--- a/testsuite/systemtap.syscall/ChangeLog
+++ b/testsuite/systemtap.syscall/ChangeLog
@@ -1,3 +1,14 @@
+2007-10-09 Martin Hunt <hunt@redhat.com>
+
+ * rt_signal.c: Fix expected results for IA64.
+
+2007-10-09 Martin Hunt <hunt@redhat.com>
+
+ * rt_signal.c: Fix expected patterns to match
+ recent changes in tapsets.
+
+ * signal.c: Use syscall(). Fix expected patterns.
+
2007-10-01 Martin Hunt <hunt@redhat.com>
* test.tcl (run_one_test): Append newlines when
diff --git a/testsuite/systemtap.syscall/rt_signal.c b/testsuite/systemtap.syscall/rt_signal.c
index 32eb9a92..f25633b7 100644
--- a/testsuite/systemtap.syscall/rt_signal.c
+++ b/testsuite/systemtap.syscall/rt_signal.c
@@ -18,26 +18,33 @@ int main()
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_BLOCK, &mask, NULL);
- // rt_sigprocmask (SIG_BLOCK, XXXX, 0x[0]+, 8) = 0
+ // rt_sigprocmask (SIG_BLOCK, \[SIGUSR1|SIGUSR2\], 0x[0]+, 8) = 0
+ sigdelset(&mask, SIGUSR2);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
- // rt_sigprocmask (SIG_UNBLOCK, XXXX, 0x[0]+, 8) = 0
+ // rt_sigprocmask (SIG_UNBLOCK, \[SIGUSR1\], 0x[0]+, 8) = 0
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGALRM);
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
- // rt_sigaction (SIGUSR1, XXXX, 0x[0]+, 8) = 0
+ // rt_sigaction (SIGUSR1, {SIG_IGN}, 0x[0]+, 8) = 0
sa.sa_handler = SIG_DFL;
sigaction(SIGUSR1, &sa, NULL);
- // rt_sigaction (SIGUSR1, XXXX, 0x[0]+, 8) = 0
+ // rt_sigaction (SIGUSR1, {SIG_DFL}, 0x[0]+, 8) = 0
sa.sa_handler = sig_act_handler;
sigaction(SIGUSR1, &sa, NULL);
- // rt_sigaction (SIGUSR1, XXXX, 0x[0]+, 8) = 0
+
+#ifdef __ia64__
+ // rt_sigaction (SIGUSR1, {XXXX, [^,]+, \[SIGALRM\]}, 0x[0]+, 8) = 0
+#else
+ // rt_sigaction (SIGUSR1, {XXXX, [^,]+, XXXX, \[SIGALRM\]}, 0x[0]+, 8) = 0
+#endif
return 0;
}
diff --git a/testsuite/systemtap.syscall/signal.c b/testsuite/systemtap.syscall/signal.c
index e125e4a1..2c0abe38 100644
--- a/testsuite/systemtap.syscall/signal.c
+++ b/testsuite/systemtap.syscall/signal.c
@@ -2,56 +2,54 @@
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
+#include <string.h>
#include <sys/syscall.h>
-#ifdef SYS_signal
static void
sig_act_handler(int signo)
{
}
-#endif
int main()
{
-#ifdef SYS_signal
sigset_t mask;
struct sigaction sa;
pid_t pid;
+#ifdef SYS_signal
syscall(SYS_signal, SIGUSR1, SIG_IGN);
- // signal (SIGUSR1, 0x0+1) = 0
+ // signal (SIGUSR1, SIG_IGN)
- syscall(SYS_signal, SIGUSR1, SIG_DFL);
- // signal (SIGUSR1, 0x0+) = 1
+ syscall (SYS_signal, SIGUSR1, SIG_DFL);
+ // signal (SIGUSR1, SIG_DFL) = 1
- syscall(SYS_signal, SIGUSR1, sig_act_handler);
+ syscall (SYS_signal, SIGUSR1, sig_act_handler);
// signal (SIGUSR1, XXXX) = 0
+#endif
sigemptyset(&mask);
- sigaddset(&mask, SIGUSR1);
- syscall(SYS_sigprocmask,SIG_BLOCK, &mask, NULL);
+ sigaddset(&mask, SIGUSR2);
+
+#ifdef SYS_sigprocmask
+ syscall (SYS_sigprocmask, SIG_BLOCK, &mask, NULL);
// sigprocmask (SIG_BLOCK, XXXX, 0x0+) = 0
- syscall(SYS_sigprocmask,SIG_UNBLOCK, &mask, NULL);
+ syscall (SYS_sigprocmask, SIG_UNBLOCK, &mask, NULL);
// sigprocmask (SIG_UNBLOCK, XXXX, 0x0+) = 0
+#endif
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGALRM);
- sa.sa_flags = 0;
- syscall(SYS_sigaction,SIGUSR1, &sa, NULL);
- // sigaction (SIGUSR1, XXXX, 0x0+) = 0
-
- /* syscall(SYS_kill,0,SIGUSR1);
- kill (0, SIGUSR1) = 0
-
- pid = getpid();
- getpid () = NNNN
+#ifdef SYS_sigaction
+ syscall (SYS_sigaction, SIGUSR1, &sa, NULL);
+ // sigaction (SIGUSR1, {SIG_IGN}, 0x0+) = 0
+ #endif
- syscall(SYS_tgkill,pid,pid,SIGUSR1);
- tgkill (NNNN, NNNN, SIGUSR1) = 0
- */
+#ifdef SYS_tgkill
+ syscall(SYS_tgkill, 1234, 5678, 0);
+ // tgkill (1234, 5678, SIG_0)
#endif
return 0;