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); }
/* * 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); }
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; }
/*{{{ 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; }
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; }
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); }
/* * 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); }
/*{{{ 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; }
/*{{{ 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; }
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; }
/* * 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; }
/*{{{ 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; }
/*{{{ 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; }
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; }
/* * 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); }
/*{{{ 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; }
/* * 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); }
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); }
/*{{{ 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; }
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); }
/*{{{ 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; }
/* * 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); }
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; }
/* * 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); }