* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/* This file contains the implementation of the UST listener thread, which
+ * receives trace control commands. It also coordinates the initialization of
+ * libust.
+ */
+
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
*/
s64 pidunique = -1LL;
+extern struct chan_info_struct chan_infos[];
+
struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
static struct ustcomm_app ustcomm_app;
return retval;
}
-static unsigned int poweroftwo(unsigned int x)
-{
- unsigned int power2 = 1;
- unsigned int hardcoded = 2147483648u; /* FIX max 2^31 */
-
- if (x < 2)
- return 2;
+/* Return the power of two which is equal or higher to v */
- while (power2 < x && power2 < hardcoded)
- power2 *= 2;
-
- return power2;
+static unsigned int pow2_higher_or_eq(unsigned int v)
+{
+ int hb = fls(v);
+ int hbm1 = hb-1;
+ int retval = 1<<(hb-1);
+
+ if(v-retval == 0)
+ return retval;
+ else
+ return retval<<1;
}
static int do_cmd_set_subbuf_size(const char *recvbuf, struct ustcomm_source *src)
goto end;
}
- power = poweroftwo(size);
+ power = pow2_higher_or_eq(size);
+ power = max_t(unsigned int, 2u, power);
if (power != size)
- WARN("using the next 2^n = %u\n", power);
+ WARN("using the next power of two for buffer size = %u\n", power);
ltt_lock_traces();
trace = _ltt_trace_find_setup(trace_name);
void create_listener(void)
{
int result;
+ sigset_t sig_all_blocked;
+ sigset_t orig_parent_mask;
if(have_listener) {
WARN("not creating listener because we already had one");
return;
}
+ /* A new thread created by pthread_create inherits the signal mask
+ * from the parent. To avoid any signal being received by the
+ * listener thread, we block all signals temporarily in the parent,
+ * while we create the listener thread.
+ */
+
+ sigfillset(&sig_all_blocked);
+
+ result = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_parent_mask);
+ if(result) {
+ PERROR("pthread_sigmask: %s", strerror(result));
+ }
+
result = pthread_create(&listener_thread, NULL, listener_main, NULL);
if(result == -1) {
PERROR("pthread_create");
}
+ /* Restore original signal mask in parent */
+ result = pthread_sigmask(SIG_SETMASK, &orig_parent_mask, NULL);
+ if(result) {
+ PERROR("pthread_sigmask: %s", strerror(result));
+ }
+
have_listener = 1;
}
{
int result;
char* autoprobe_val = NULL;
+ char* subbuffer_size_val = NULL;
+ char* subbuffer_count_val = NULL;
+ unsigned int subbuffer_size;
+ unsigned int subbuffer_count;
+ unsigned int power;
/* Assign the pidunique, to be able to differentiate the processes with same
* pid, (before and after an exec).
}
}
+ subbuffer_size_val = getenv("UST_SUBBUF_SIZE");
+ if(subbuffer_size_val) {
+ sscanf(subbuffer_size_val, "%u", &subbuffer_size);
+ power = pow2_higher_or_eq(subbuffer_size);
+ if(power != subbuffer_size)
+ WARN("using the next power of two for buffer size = %u\n", power);
+ chan_infos[LTT_CHANNEL_UST].def_subbufsize = power;
+ }
+
+ subbuffer_count_val = getenv("UST_SUBBUF_NUM");
+ if(subbuffer_count_val) {
+ sscanf(subbuffer_count_val, "%u", &subbuffer_count);
+ if(subbuffer_count < 2)
+ subbuffer_count = 2;
+ chan_infos[LTT_CHANNEL_UST].def_subbufcount = subbuffer_count;
+ }
+
if(getenv("UST_TRACE")) {
char trace_name[] = "auto";
char trace_type[] = "ustrelay";
inform_consumer_daemon(trace_name);
}
-
return;
/* should decrementally destroy stuff if error */