/* -*- linux-c -*- * Context Runtime Functions * Copyright (C) 2012 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 _LINUX_RUNTIME_CONTEXT_H_ #define _LINUX_RUNTIME_CONTEXT_H_ static struct context *contexts[NR_CPUS] = { NULL }; static int _stp_runtime_contexts_alloc(void) { int cpu; for_each_possible_cpu(cpu) { /* Module init, so in user context, safe to use * "sleeping" allocation. */ contexts[cpu] = _stp_kzalloc_gfp(sizeof(struct context), STP_ALLOC_SLEEP_FLAGS); if (contexts[cpu] == NULL) { _stp_error ("context (size %lu) allocation failed", (unsigned long) sizeof (struct context)); return -ENOMEM; } } return 0; } static void _stp_runtime_contexts_free(void) { int cpu; for_each_possible_cpu(cpu) { if (contexts[cpu] != NULL) { _stp_kfree(contexts[cpu]); contexts[cpu] = NULL; } } } static struct context * _stp_runtime_entryfn_get_context(void) { return contexts[smp_processor_id()]; } static inline void _stp_runtime_entryfn_put_context(struct context *c __attribute__((unused))) { /* Do nothing. */ return; } static inline struct context * _stp_runtime_get_context(void) { return contexts[smp_processor_id()]; } static void _stp_runtime_context_wait(void) { int holdon; unsigned long hold_start; int hold_index; hold_start = jiffies; hold_index = -1; do { int i; holdon = 0; for_each_possible_cpu(i) { if (contexts[i] != NULL && atomic_read (& contexts[i]->busy)) { holdon = 1; /* Just in case things are really * stuck, let's print some diagnostics. */ if (time_after(jiffies, hold_start + HZ) // > 1 second && (i > hold_index)) { // not already printed hold_index = i; printk(KERN_ERR "%s context[%d] stuck: %s\n", THIS_MODULE->name, i, contexts[i]->probe_point); } } } /* * Just in case things are really really stuck, a * handler probably suffered a fault, and the kernel * probably killed a task/thread already. We can't be * quite sure in what state everything is in, however * auxiliary stuff like kprobes / uprobes / locks have * already been unregistered. So it's *probably* safe * to pretend/assume/hope everything is OK, and let * the cleanup finish. * * In the worst case, there may occur a fault, as a * genuinely running probe handler tries to access * script globals (about to be freed), or something * accesses module memory (about to be unloaded). * This is sometimes stinky, so the alternative * (default) is to change from a livelock to a * livelock that sleeps awhile. */ #ifdef STAP_OVERRIDE_STUCK_CONTEXT if (time_after(jiffies, hold_start + HZ*10)) { // > 10 seconds printk(KERN_ERR "%s overriding stuck context to allow module shutdown.", THIS_MODULE->name); holdon = 0; // allow loop to exit } #else /* at least stop sucking down the staprun cpu */ msleep(250); #endif /* NB: we run at least one of these during the * shutdown sequence: */ yield(); /* aka schedule() and then some */ } while (holdon); } #endif /* _LINUX_RUNTIME_CONTEXT_H_ */