예제 #1
0
int
MONITOR_WRAP_NAME(pthread_sigmask)(int how, const sigset_t *set,
				   sigset_t *oldset)
{
    char buf[MONITOR_SIG_BUF_SIZE];
    char *type;
    sigset_t my_set;

    monitor_signal_init();
    monitor_thread_name_init();

    type = (how == SIG_UNBLOCK) ? "unblock" : "block";
    if (monitor_debug) {
	monitor_sigset_string(buf, MONITOR_SIG_BUF_SIZE, set);
	MONITOR_DEBUG("(%s) request:%s\n", type, buf);
    }

    if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) {
	my_set = *set;
	monitor_remove_client_signals(&my_set);
	set = &my_set;
	if (monitor_debug) {
	    monitor_sigset_string(buf, MONITOR_SIG_BUF_SIZE, set);
	    MONITOR_DEBUG("(%s) actual: %s\n", type, buf);
	}
    }

    return (*real_pthread_sigmask)(how, set, oldset);
}
예제 #2
0
/*
 *  Called from real_pthread_create(), it's where the newly-created
 *  thread begins.
 */
static void *
monitor_begin_thread(void *arg)
{
    struct monitor_thread_node *tn = arg;
    void *ret;

    MONITOR_ASM_LABEL(monitor_thread_fence1);
    MONITOR_DEBUG1("\n");

    /*
     * Wait for monitor_init_thread_support() to finish in the main
     * thread before this thread runs.
     *
     * Note: if this thread is created before libc_start_main (OpenMP
     * does this), then this will wait for both init_process and
     * thread_support to finish from libc_start_main.  And that has
     * the potential to deadlock if the application waits for this
     * thread to accomplish something before it finishes its library
     * init.  (An evil thing for it to do, but it's possible.)
     */
    while (! monitor_thread_support_done)
	usleep(MONITOR_POLL_USLEEP_TIME);

    /*
     * Don't create any new threads after someone has called exit().
     */
    tn->tn_self = (*real_pthread_self)();
    tn->tn_stack_bottom = alloca(8);
    strncpy(tn->tn_stack_bottom, "stakbot", 8);
    if ((*real_pthread_setspecific)(monitor_pthread_key, tn) != 0) {
	MONITOR_ERROR1("pthread_setspecific failed\n");
    }
    if (monitor_link_thread_node(tn) != 0) {
	MONITOR_DEBUG1("warning: trying to create new thread during "
		       "exit cleanup: thread not started\n");
	return (NULL);
    }

    PTHREAD_CLEANUP_PUSH(monitor_pthread_cleanup_routine, tn);

    MONITOR_DEBUG("tid = %d, self = %p, start_routine = %p\n",
		  tn->tn_tid, (void *)tn->tn_self, tn->tn_start_routine);
    MONITOR_DEBUG("calling monitor_init_thread(tid = %d, data = %p) ...\n",
		  tn->tn_tid, tn->tn_user_data);
    tn->tn_user_data = monitor_init_thread(tn->tn_tid, tn->tn_user_data);

    tn->tn_appl_started = 1;
    MONITOR_ASM_LABEL(monitor_thread_fence2);
    ret = (tn->tn_start_routine)(tn->tn_arg);
    MONITOR_ASM_LABEL(monitor_thread_fence3);

    PTHREAD_CLEANUP_POP(1);

    MONITOR_ASM_LABEL(monitor_thread_fence4);
    return (ret);
}
예제 #3
0
int
MONITOR_WRAP_NAME(sigwaitinfo)(const sigset_t *set, siginfo_t *info)
{
    char buf[MONITOR_SIG_BUF_SIZE];
    siginfo_t my_info, *info_ptr;
    ucontext_t context;
    int ret, save_errno;

    monitor_thread_name_init();
    if (monitor_debug) {
	monitor_sigset_string(buf, MONITOR_SIG_BUF_SIZE, set);
	MONITOR_DEBUG("waiting on:%s\n", buf);
    }

    getcontext(&context);
    info_ptr = (info != NULL) ? info : &my_info;
    do {
	ret = real_sigwaitinfo(set, info_ptr);
	save_errno = errno;
    }
    while (monitor_sigwait_helper(set, ret, save_errno, info_ptr, &context));

    errno = save_errno;
    return ret;
}
예제 #4
0
/*{{{  MonitorInit*/
struct file_operations* MonitorInit (struct DeviceContext_s* Context)
{
    unsigned int        i;

    MONITOR_DEBUG("\n");

    init_waitqueue_head (&(Context->EventQueue.EventReceived));
    init_waitqueue_head (&(Context->EventQueue.BufferReleased));
    spin_lock_init (&(Context->EventQueue.Lock));

    Context->OpenCount                          = 0;
    Context->Status.status_code                 = MONITOR_STATUS_IDLE;
    Context->Status.subsystem_mask              = MONITOR_SYSTEM_GENERIC;     /* Allow all system wide events */
    Context->EventQueue.Write                   = 0;
    Context->EventQueue.Read                    = 0;
    Context->EventQueue.LostCount               = 0;

    for (i = 0; i <= MAX_MONITOR_EVENT_CODE; i++)
    {
        memset (Context->StoredEventValues[i].Parameters, 0, sizeof(unsigned int)*MONITOR_PARAMETER_COUNT);
        Context->StoredEventValues[i].Count     = 0;
    }

    for (i = 0; i < MONITOR_MAX_MME_DEVICES; i++)
    {
        MonitorMMEInit (Context, &(Context->MMEContext[i]), i+1);
    }

    return &MonitorFops;
}
예제 #5
0
int
MONITOR_WRAP_NAME(sigtimedwait)(const sigset_t *set, siginfo_t *info,
				const struct timespec *timeout)
{
    char buf[MONITOR_SIG_BUF_SIZE];
    siginfo_t my_info, *info_ptr;
    ucontext_t context;
    int ret, save_errno;

    monitor_thread_name_init();
    if (monitor_debug) {
	monitor_sigset_string(buf, MONITOR_SIG_BUF_SIZE, set);
	MONITOR_DEBUG("waiting on:%s\n", buf);
    }

    /*
     * FIXME: if we restart sigtimedwait(), then we should subtract
     * the elapsed time from the timeout.
     */
    getcontext(&context);
    info_ptr = (info != NULL) ? info : &my_info;
    do {
	ret = real_sigtimedwait(set, info_ptr, timeout);
	save_errno = errno;
    }
    while (monitor_sigwait_helper(set, ret, save_errno, info_ptr, &context));

    errno = save_errno;
    return ret;
}
예제 #6
0
static void
monitor_shootdown_handler(int sig)
{
    struct monitor_thread_node *tn;
    int old_state;

    tn = (*real_pthread_getspecific)(monitor_pthread_key);
    if (tn == NULL) {
	MONITOR_WARN1("unable to deliver monitor_fini_thread callback: "
		      "pthread_getspecific() failed\n");
	return;
    }
    if (tn->tn_magic != MONITOR_TN_MAGIC) {
	MONITOR_WARN1("unable to deliver monitor_fini_thread callback: "
		      "bad magic in thread node\n");
	return;
    }
    if (!tn->tn_appl_started || tn->tn_fini_started || tn->tn_block_shootdown) {
	/* fini-thread has already run, or else we don't want it to run. */
	return;
    }
    if (monitor_fini_thread_done) {
	MONITOR_WARN("unable to deliver monitor_fini_thread callback (tid %d): "
		     "monitor_fini_process() has begun\n", tn->tn_tid);
	return;
    }

    (*real_pthread_setcancelstate)(PTHREAD_CANCEL_DISABLE, &old_state);
    tn->tn_fini_started = 1;
    MONITOR_DEBUG("calling monitor_fini_thread(data = %p), tid = %d ...\n",
		  tn->tn_user_data, tn->tn_tid);
    monitor_fini_thread(tn->tn_user_data);
    tn->tn_fini_done = 1;
    (*real_pthread_setcancelstate)(old_state, NULL);
}
예제 #7
0
/*
 *  We get here when the application thread has finished, either by
 *  returning, pthread_exit() or being canceled.
 */
static void
monitor_pthread_cleanup_routine(void *arg)
{
    struct monitor_thread_node *tn = arg;

    if (tn == NULL) {
	MONITOR_WARN1("unable to deliver monitor_fini_thread callback: "
		      "missing cleanup handler argument\n");
	return;
    }
    if (tn->tn_magic != MONITOR_TN_MAGIC) {
	MONITOR_WARN1("unable to deliver monitor_fini_thread callback: "
		      "bad magic in thread node\n");
	return;
    }
    if (!tn->tn_appl_started || tn->tn_fini_started || tn->tn_block_shootdown) {
	/* fini-thread has already run, or else we don't want it to run. */
	return;
    }
    if (monitor_fini_thread_done) {
	MONITOR_WARN("unable to deliver monitor_fini_thread callback (tid %d): "
		     "monitor_fini_process() has begun\n", tn->tn_tid);
	return;
    }

    tn->tn_fini_started = 1;
    MONITOR_DEBUG("calling monitor_fini_thread(data = %p), tid = %d ...\n",
		  tn->tn_user_data, tn->tn_tid);
    monitor_fini_thread(tn->tn_user_data);
    tn->tn_fini_done = 1;

    monitor_unlink_thread_node(tn);
}
예제 #8
0
/*{{{  MonitorOpen*/
static int MonitorOpen         (struct inode*   Inode,
                                struct file*    File)
{
    struct DeviceContext_s*     Context         = container_of(Inode->i_cdev, struct DeviceContext_s, CDev);
    struct ModuleContext_s*     ModuleContext   = Context->ModuleContext;

    MONITOR_DEBUG ("\n");
    File->private_data                          = Context;

    mutex_lock (&(ModuleContext->Lock));
    if (Context->Status.status_code == MONITOR_STATUS_IDLE)
    {
        Context->Status.status_code             = MONITOR_STATUS_RUNNING;
        Context->Status.subsystem_mask          = MONITOR_SYSTEM_GENERIC;     /* Allow all system wide events */
        /*
        Context->EventQueue.Write               = 0;
        Context->EventQueue.Read                = 0;
        Context->EventQueue.LostCount           = 0;
        */
    }
    Context->OpenCount++;
    mutex_unlock (&(ModuleContext->Lock));

    return 0;
}
예제 #9
0
/*{{{  MonitorIoctlRequestEvent*/
static int MonitorIoctlRequestEvent (struct DeviceContext_s* Context, struct monitor_event_request_s* EventRequest)
{
    struct EventValue_s*   StoredEvent;

    MONITOR_DEBUG("\n");

    if (!access_ok (VERIFY_WRITE, EventRequest,  sizeof (struct monitor_event_request_s)))
    {
        MONITOR_ERROR ("Invalid status address = %p\n", EventRequest);
        return -EFAULT;
    }

    if ((EventRequest->event_code & MONITOR_EVENT_INDEX_MASK) > MAX_MONITOR_EVENT_CODE)
    {
        MONITOR_ERROR ("Invalid event requested (%x)\n", EventRequest->event_code);
        return -EINVAL;
    }

    StoredEvent                 = &(Context->StoredEventValues[EventRequest->event_code & MONITOR_EVENT_INDEX_MASK]);

    memcpy (EventRequest->parameters, StoredEvent->Parameters, sizeof(StoredEvent->Parameters));
    EventRequest->count         = StoredEvent->Count;
    if (EventRequest->reset)
        StoredEvent->Count      = 0;

    return 0;
}
예제 #10
0
int
MONITOR_WRAP_NAME(sigwait)(const sigset_t *set, int *sig)
{
    char buf[MONITOR_SIG_BUF_SIZE];
    siginfo_t my_info;
    ucontext_t context;
    int ret, save_errno;

    monitor_thread_name_init();
    if (monitor_debug) {
	monitor_sigset_string(buf, MONITOR_SIG_BUF_SIZE, set);
	MONITOR_DEBUG("waiting on:%s\n", buf);
    }

    getcontext(&context);
    do {
	ret = real_sigwaitinfo(set, &my_info);
	save_errno = errno;
    }
    while (monitor_sigwait_helper(set, ret, save_errno, &my_info, &context));

    if (ret < 0) {
	return save_errno;
    }
    if (sig != NULL) {
	*sig = ret;
    }
    return 0;
}
예제 #11
0
/*
 *  Returns: 1 if we handled the signal (and thus we restart sigwait),
 *  else 0 to pass the signal to the application.
 */
static int
monitor_sigwait_helper(const sigset_t *set, int sig, int sigwait_errno,
		       siginfo_t *info, ucontext_t *context)
{
    struct monitor_thread_node *tn;
    int old_state;

    /*
     * If sigwaitinfo() returned an error, we restart EINTR and pass
     * other errors back to the application.
     */
    if (sig < 0) {
	return (sigwait_errno == EINTR);
    }

    /*
     * End of process shootdown signal.
     */
    tn = monitor_get_tn();
    if (sig == shootdown_signal
	&& monitor_in_exit_cleanup
	&& !monitor_fini_thread_done
	&& tn != NULL
	&& tn->tn_appl_started
	&& !tn->tn_fini_started
	&& !tn->tn_block_shootdown)
    {
	(*real_pthread_setcancelstate)(PTHREAD_CANCEL_DISABLE, &old_state);
	tn->tn_fini_started = 1;
	MONITOR_DEBUG("calling monitor_fini_thread(data = %p), tid = %d ...\n",
		      tn->tn_user_data, tn->tn_tid);
	monitor_fini_thread(tn->tn_user_data);
	tn->tn_fini_done = 1;
	(*real_pthread_setcancelstate)(old_state, NULL);

	return 1;
    }

    /*
     * A signal for which the client has installed a handler via
     * monitor_sigaction().
     */
    if (monitor_sigwait_handler(sig, info, context) == 0) {
	return 1;
    }

    /*
     * A signal not in 'set' is treated as EINTR and restarted.
     */
    if (! sigismember(set, sig)) {
	return 1;
    }

    /*
     * Otherwise, return the signal to the application.
     */
    return 0;
}
예제 #12
0
/*{{{  MonitorIoctlDisable*/
static int MonitorIoctlDisable(struct DeviceContext_s* Context, monitor_subsystem_mask_t SubsystemMask)
{
	MONITOR_DEBUG("\n");
	if ((SubsystemMask & MONITOR_ENABLE_ALL) == 0)
	{
		MONITOR_ERROR("Invalid subsystem mask %08x\n", SubsystemMask);
		return -EINVAL;
	}
	Context->Status.subsystem_mask     &= (~(SubsystemMask & MONITOR_ENABLE_ALL));
	return 0;
}
예제 #13
0
/*{{{ MonitorMMEThread*/
static int MonitorMMEThread(void *Param)
{
	struct MMEContext_s *Context = (struct MMEContext_s *)Param;
	MME_ERROR MMEStatus;
	unsigned long long TimeStamp;
	unsigned int TimeValue;
	daemonize(MONITOR_MME_THREAD_NAME);
	MONITOR_DEBUG("Starting\n");
	while (Context->Monitoring)
	{
		MMEStatus = TransformerGetLogEvent(Context);
		if (MMEStatus != MME_SUCCESS)
			break;
		if (down_interruptible(&(Context->EventReceived)) != 0)
			break;
		TimeValue = *Context->DeviceContext->Timer;
		TimeStamp = ktime_to_us(ktime_get());
		if (Context->MMECommandStatus.TimeCode != 0)
		{
			unsigned long long TimeDiff;
			/* This assumes that the timer is counting down from ClockMaxValue to 0 */
			if (Context->MMECommandStatus.TimeCode > TimeValue)
				TimeDiff = (unsigned long long)(Context->MMECommandStatus.TimeCode - TimeValue);
			else
				TimeDiff = ((unsigned long long)Context->MMECommandStatus.TimeCode + Context->ClockMaxValue + 1) - (unsigned long long)TimeValue;
			TimeStamp -= ((unsigned long long)TimeDiff * 1000000ull) / Context->TicksPerSecond;
		}
		if (Context->Monitoring)
			MonitorRecordEvent(Context->DeviceContext,
							   Context->Id,
							   Context->MMECommandStatus.EventID,
							   TimeStamp,
							   Context->MMECommandStatus.Parameters,
							   Context->MMECommandStatus.Message);
	}
	MONITOR_DEBUG("Terminating\n");
	up(&(Context->ThreadTerminated));
	return 0;
}
예제 #14
0
static int StmMonitorRemove(struct device *dev)
{

    unregister_chrdev_region (FirstDevice, MONITOR_MAX_DEVICES);

    if (ModuleContext != NULL)
        kfree (ModuleContext);

    ModuleContext  = NULL;

    MONITOR_DEBUG("STM monitor device unloaded\n");

    return 0;
}
예제 #15
0
파일: pmpi.c 프로젝트: phisama/libmonitor
/*
 * In C, MPI_Comm is not always void *, but that seems to be
 * compatible with most libraries.
 */
int
MONITOR_WRAP_NAME(PMPI_Comm_rank)(void *comm, int *rank)
{
    int size = -1, ret;

    MONITOR_DEBUG("comm = %p\n", comm);
    MONITOR_GET_REAL_NAME(real_pmpi_comm_size, PMPI_Comm_size);
    MONITOR_GET_REAL_NAME_WRAP(real_pmpi_comm_rank, PMPI_Comm_rank);
    ret = (*real_pmpi_comm_size)(comm, &size);
    ret = (*real_pmpi_comm_rank)(comm, rank);
    monitor_set_mpi_size_rank(size, *rank);

    return (ret);
}
예제 #16
0
/*{{{  MonitorIoctlGetStatus*/
static int MonitorIoctlGetStatus(struct DeviceContext_s* Context, struct monitor_status_s* Status)
{
	struct EventQueue_s*        EventList       = &Context->EventQueue;
	MONITOR_DEBUG("\n");
	if (!access_ok(VERIFY_WRITE, Status,  sizeof(struct monitor_status_s)))
	{
		MONITOR_ERROR("Invalid status address = %p\n", Status);
		return -EFAULT;
	}
	if (EventList->Read >= EventList->Write)
		Context->Status.event_count     = EventList->Read - EventList->Write;
	else
		Context->Status.event_count     = (EventList->Read + MAX_MONITOR_EVENT) - EventList->Write;
	Context->Status.events_lost         = EventList->LostCount;
	memcpy(Status, &Context->Status, sizeof(struct monitor_status_s));
	return 0;
}
예제 #17
0
/*
 *  Allow the client to change the thread stack size, if needed.  This
 *  is useful for profilers, in case the application's stack is too
 *  small.  This would be easier if we could copy the attribute object
 *  and modify the copy, but that violates the pthread spec (not
 *  allowed to copy).
 *
 *  Returns: pointer to attr object that pthread_create() should use,
 *  also sets the old size, whether we need to restore the old size,
 *  and whether we need to destroy the attr object.  If anything goes
 *  wrong, use the original attributes and hope for the best.
 */
pthread_attr_t *
monitor_adjust_stack_size(pthread_attr_t *orig_attr,
			  pthread_attr_t *default_attr,
			  int *restore, int *destroy, size_t *old_size)
{
    pthread_attr_t *attr;
    size_t new_size;

    *restore = 0;
    *destroy = 0;
    if (orig_attr != NULL)
	attr = orig_attr;
    else {
	if ((*real_pthread_attr_init)(default_attr) != 0) {
	    MONITOR_WARN1("pthread_attr_init failed\n");
	    return (orig_attr);
	}
	*destroy = 1;
	attr = default_attr;
    }

    if ((*real_pthread_attr_getstacksize)(attr, old_size) != 0) {
	MONITOR_WARN1("pthread_attr_getstacksize failed\n");
	return (orig_attr);
    }

    new_size = monitor_reset_stacksize(*old_size);
    if (new_size == *old_size)
	return (orig_attr);

    if ((*real_pthread_attr_setstacksize)(attr, new_size) != 0) {
	MONITOR_WARN1("pthread_attr_setstacksize failed\n");
	return (orig_attr);
    }
    if (attr == orig_attr)
	*restore = 1;

    MONITOR_DEBUG("old size = %ld, new size = %ld\n",
		  (long)*old_size, (long)new_size);

    return (attr);
}
예제 #18
0
void
MONITOR_WRAP_NAME(mpi_finalize__)(int *ierror)
{
    int count;

    MONITOR_DEBUG1("\n");
    MONITOR_GET_REAL_NAME_WRAP(real_mpi_finalize, mpi_finalize__);
    count = monitor_mpi_fini_count(1);
    if (count == 1) {
	MONITOR_DEBUG("calling monitor_fini_mpi(), size = %d, rank = %d ...\n",
		      monitor_mpi_comm_size(), monitor_mpi_comm_rank());
	monitor_fini_mpi();
    }
    (*real_mpi_finalize)(ierror);
    if (count == 1) {
	MONITOR_DEBUG1("calling monitor_mpi_post_fini() ...\n");
	monitor_mpi_post_fini();
    }
    monitor_mpi_fini_count(-1);
}
예제 #19
0
/*{{{  MonitorRelease*/
static int MonitorRelease(struct inode*   Inode,
						  struct file*    File)
{
	struct DeviceContext_s*     Context         = (struct DeviceContext_s*)File->private_data;
	struct ModuleContext_s*     ModuleContext   = Context->ModuleContext;
	MONITOR_DEBUG("\n");
	mutex_lock(&(ModuleContext->Lock));
	Context->OpenCount--;
	if (Context->OpenCount == 0)
	{
		Context->Status.status_code       = MONITOR_STATUS_IDLE;
		Context->Status.subsystem_mask    = MONITOR_SYSTEM_GENERIC;     /* Allow all system wide events */
		/*
		Context->EventQueue.Write         = 0;
		Context->EventQueue.Read          = 0;
		Context->EventQueue.LostCount     = 0;
		*/
	}
	mutex_unlock(&(ModuleContext->Lock));
	return 0;
}
예제 #20
0
파일: pmpi.c 프로젝트: phisama/libmonitor
int
MONITOR_WRAP_NAME(PMPI_Finalize)(void)
{
    int ret, count;

    MONITOR_DEBUG1("\n");
    MONITOR_GET_REAL_NAME_WRAP(real_pmpi_finalize, PMPI_Finalize);
    count = monitor_mpi_fini_count(1);
    if (count == 1) {
	MONITOR_DEBUG("calling monitor_fini_mpi(), size = %d, rank = %d ...\n",
		      monitor_mpi_comm_size(), monitor_mpi_comm_rank());
	monitor_fini_mpi();
    }
    ret = (*real_pmpi_finalize)();
    if (count == 1) {
	MONITOR_DEBUG1("calling monitor_mpi_post_fini() ...\n");
	monitor_mpi_post_fini();
    }
    monitor_mpi_fini_count(-1);

    return (ret);
}
예제 #21
0
/*{{{ VerifyCapabilities*/
static int VerifyCapabilities(struct MMEContext_s *Context)
{
	EVENT_LOG_TransformerCapability_t EventLogCapability = {0};
	MME_TransformerCapability_t MMECapability = {0};
	MME_ERROR MMEStatus;
	MMECapability.StructSize = sizeof(MME_TransformerCapability_t);
	MMECapability.TransformerInfoSize = sizeof(EVENT_LOG_TransformerCapability_t);
	MMECapability.TransformerInfo_p = &EventLogCapability;
	MMEStatus = MME_GetTransformerCapability(Context->TransformerName, &MMECapability);
	if (MMEStatus == MME_UNKNOWN_TRANSFORMER)
	{
		MONITOR_DEBUG("%s: Transformer not found. This event source will not be monitored.\n", Context->TransformerName);
		return -EFAULT;
	}
	if (MMEStatus != MME_SUCCESS)
	{
		MONITOR_ERROR("%s: Failed to retrieve transformer capabilities - Error 0x%08x.\n", Context->TransformerName, MMEStatus);
		return -EFAULT;
	}
	MONITOR_TRACE("Found %s transformer (version %x)\n", Context->TransformerName, MMECapability.Version);
	return 0;
}
예제 #22
0
/*
 *  Called from main.c at end process time for possible thread cleanup.
 *  Note: main doesn't know if application is threaded or not.
 */
void
monitor_thread_shootdown(void)
{
    struct timeval last, now;
    struct monitor_thread_node *tn, *my_tn;
    struct sigaction my_action;
    sigset_t empty_set;
    pthread_t self;
    int num_started, num_unstarted, last_started;
    int num_finished, num_unfinished, old_state;

    if (! monitor_has_used_threads) {
	MONITOR_DEBUG1("(no threads)\n");
	return;
    }

    (*real_pthread_setcancelstate)(PTHREAD_CANCEL_DISABLE, &old_state);

    MONITOR_THREAD_LOCK;
    monitor_in_exit_cleanup = 1;
    MONITOR_THREAD_UNLOCK;
    MONITOR_DEBUG1("(threads)\n");

    /*
     * Install the signal handler for thread shootdown.
     * Note: the signal handler is process-wide.
     */
    shootdown_signal = monitor_shootdown_signal();
    MONITOR_DEBUG("using signal: %d\n", shootdown_signal);
    sigemptyset(&empty_set);
    my_action.sa_handler = monitor_shootdown_handler;
    my_action.sa_mask = empty_set;
    my_action.sa_flags = SA_RESTART;
    if ((*real_sigaction)(shootdown_signal, &my_action, NULL) != 0) {
	MONITOR_ERROR1("sigaction failed\n");
    }

    /*
     * Walk through the list of unfinished threads, send a signal to
     * force them into their fini_thread functions, and wait until
     * they all finish.  But don't signal ourself.
     *
     * Add a timeout: if we make no progress for 10 consecutive
     * seconds, then give up.  Progress means receiving the signal in
     * the other thread, the fini thread callback can take as long as
     * it likes.
     */
    self = (*real_pthread_self)();
    my_tn = NULL;
    gettimeofday(&last, NULL);
    last_started = 0;
    for (;;) {
	num_started = 0;
	num_unstarted = 0;
	num_finished = 0;
	num_unfinished = 0;
	for (tn = LIST_FIRST(&monitor_thread_list);
	     tn != NULL;
	     tn = LIST_NEXT(tn, tn_links))
	{
	    if (PTHREAD_EQUAL(self, tn->tn_self)) {
		my_tn = tn;
		continue;
	    }
	    if (tn->tn_appl_started) {
		if (tn->tn_fini_started) {
		    num_started++;
		} else {
		    (*real_pthread_kill)(tn->tn_self, shootdown_signal);
		    num_unstarted++;
		}
		if (tn->tn_fini_done)
		    num_finished++;
		else
		    num_unfinished++;
	    }
	}
	MONITOR_DEBUG("started: %d, unstarted: %d, finished: %d, unfinished: %d\n",
		      num_started, num_unstarted, num_finished, num_unfinished);
	if (num_unfinished == 0)
	    break;

	gettimeofday(&now, NULL);
	if (num_started > last_started) {
	    last = now;
	    last_started = num_started;
	} else if (now.tv_sec > last.tv_sec + MONITOR_SHOOTDOWN_TIMEOUT
		   && num_unstarted > 0) {
	    MONITOR_WARN("timeout exceeded (%d): unable to deliver "
			 "monitor_fini_thread() to %d threads\n",
			 MONITOR_SHOOTDOWN_TIMEOUT, num_unstarted);
	    break;
	}
	usleep(MONITOR_POLL_USLEEP_TIME);
    }
    monitor_fini_thread_done = 1;

    /*
     * See if we need to run fini_thread from this thread.
     */
    if (my_tn != NULL && !my_tn->tn_fini_started) {
	my_tn->tn_fini_started = 1;
	MONITOR_DEBUG("calling monitor_fini_thread(data = %p), tid = %d ...\n",
		      my_tn->tn_user_data, my_tn->tn_tid);
	monitor_fini_thread(my_tn->tn_user_data);
	my_tn->tn_fini_done = 1;
    }

    (*real_pthread_setcancelstate)(old_state, NULL);
}
예제 #23
0
static int StmMonitorProbe(struct device *dev)
{
    int                     Result;
    int                     i;
    struct platform_device *MonitorDeviceData;
    unsigned int           *Timer;
    unsigned int            TimerPhysical;

    MonitorDeviceData = to_platform_device(dev);

    if (!MonitorDeviceData) {
            MONITOR_ERROR("%s: Device probe failed.  Check your kernel SoC config!!\n",
                   __FUNCTION__);

            return -ENODEV;
    }

    ModuleContext       = kzalloc (sizeof (struct ModuleContext_s),  GFP_KERNEL);
    if (ModuleContext == NULL)
    {
        MONITOR_ERROR("Unable to allocate device memory\n");
        return -ENOMEM;
    }

    TimerPhysical = platform_get_resource(MonitorDeviceData, IORESOURCE_MEM, 0)->start;
    Timer         = ioremap(TimerPhysical,0x4);

    mutex_init (&(ModuleContext->Lock));
    mutex_lock (&(ModuleContext->Lock));

    Result      = alloc_chrdev_region (&FirstDevice, 0, MONITOR_MAX_DEVICES, DEVICE_NAME);
    if (Result < 0)
    {
        printk (KERN_ERR "%s: unable to allocate device numbers\n",__FUNCTION__);
        return -ENODEV;
    }

    ModuleContext->DeviceClass                  = class_create (THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(ModuleContext->DeviceClass))
    {
        printk (KERN_ERR "%s: unable to create device class\n",__FUNCTION__);
        ModuleContext->DeviceClass              = NULL;
        return -ENODEV;
    }

    for (i = 0; i < MONITOR_MAX_DEVICES; i++)
    {
        struct DeviceContext_s* DeviceContext   = &ModuleContext->DeviceContext[i];
        int                     DevNo           = MKDEV(MAJOR(FirstDevice), i);
        struct file_operations* FileOps;

        DeviceContext->TimerPhysical            = TimerPhysical;
        DeviceContext->Timer                    = Timer;

        FileOps                                 = MonitorInit (DeviceContext);

        DeviceContext->ModuleContext            = ModuleContext;
        cdev_init (&(DeviceContext->CDev), FileOps);
        DeviceContext->CDev.owner               = THIS_MODULE;
        kobject_set_name (&(DeviceContext->CDev.kobj), "%s%d", DEVICE_NAME, i);
        Result                                  = cdev_add (&(DeviceContext->CDev), DevNo, 1);
        if (Result != 0)
        {
            printk (KERN_ERR "%s: unable to add device\n",__FUNCTION__);
            return -ENODEV;
        }
#if defined(__TDT__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
        DeviceContext->ClassDevice              = device_create (ModuleContext->DeviceClass,
                                                                       NULL,
                                                                       DeviceContext->CDev.dev,
                                                                       NULL,
                                                                       kobject_name (&(DeviceContext->CDev.kobj)));
#else
        DeviceContext->ClassDevice              = class_device_create (ModuleContext->DeviceClass,
                                                                       NULL,
                                                                       DeviceContext->CDev.dev,
                                                                       NULL,
                                                                       kobject_name (&(DeviceContext->CDev.kobj)));
#endif
        if (IS_ERR(DeviceContext->ClassDevice))
        {
            printk (KERN_ERR "%s: unable to create class device\n",__FUNCTION__);
            DeviceContext->ClassDevice          = NULL;
            return -ENODEV;
        }

#if defined(__TDT__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30))
        class_set_devdata (DeviceContext->ClassDevice, DeviceContext);
#endif
    }

    mutex_unlock (&(ModuleContext->Lock));

    MONITOR_DEBUG("STM monitor device loaded\n");

    return 0;
}
예제 #24
0
/*
 *  Override pthread_create().
 */
int
MONITOR_WRAP_NAME(pthread_create)(PTHREAD_CREATE_PARAM_LIST)
{
    struct monitor_thread_node *tn;
    pthread_attr_t default_attr;
    int ret, restore, destroy;
    size_t old_size;

    MONITOR_DEBUG1("\n");

    /*
     * There is no race condition to get here first because until now,
     * there is only one thread.
     */
    if (! monitor_has_used_threads) {
	monitor_thread_list_init();
	monitor_has_used_threads = 1;
    }

    /*
     * If we are ignoring this thread, then call the real
     * pthread_create(), don't put it on the thread list and don't
     * give any callbacks.
     */
    tn = monitor_get_tn();
    if (tn != NULL && tn->tn_ignore_threads) {
	MONITOR_DEBUG1("ignoring this new thread\n");
	return (*real_pthread_create)(thread, attr, start_routine, arg);
    }

    /*
     * Normally, we run thread_support here, on the first call to
     * pthread_create().  But if we're here early, before
     * libc_start_main, then defer thread_support until after
     * init_process in libc_start_main.
     */
    if (! monitor_thread_support_done) {
	if (monitor_has_reached_main) {
	    monitor_call_thread_support();
	} else {
	    MONITOR_DEBUG1("deferring thread support\n");
	}
    }

    /*
     * Always launch the thread.  If we're in pthread_create() too
     * early, then the new thread will spin-wait until init_process
     * and thread_support are done.
     */
    tn = monitor_make_thread_node();
    tn->tn_start_routine = start_routine;
    tn->tn_arg = arg;
    MONITOR_DEBUG("calling monitor_thread_pre_create(start_routine = %p) ...\n",
		  start_routine);
    tn->tn_user_data = monitor_thread_pre_create();

    /*
     * Allow the client to change the thread stack size.  Note: we
     * need to restore the original size in case the application uses
     * one attribute struct for several threads (so we don't keep
     * increasing its size).
     */
    attr = monitor_adjust_stack_size((pthread_attr_t *)attr, &default_attr,
				     &restore, &destroy, &old_size);
    ret = (*real_pthread_create)(thread, attr, monitor_begin_thread,
				 (void *)tn);
    if (restore) {
	(*real_pthread_attr_setstacksize)((pthread_attr_t *)attr, old_size);
    }
    if (destroy) {
	(*real_pthread_attr_destroy)(&default_attr);
    }
    if (ret != 0) {
	MONITOR_DEBUG("real_pthread_create failed: start_routine = %p, ret = %d\n",
		      start_routine, ret);
    }

    MONITOR_DEBUG("calling monitor_thread_post_create(start_routine = %p) ...\n",
		  start_routine);
    monitor_thread_post_create(tn->tn_user_data);

    return (ret);
}