Changeset df58e44 in mainline


Ignore:
Timestamp:
2011-01-27T16:36:35Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5b7a107
Parents:
0843f02
Message:
  • add support for printing uspace stack traces from kernel console (as a last resort debugging means)
  • change the semantics of waitq_interrupt_sleep() (require threads_lock to be held even before it is called)
  • minor cstyle
Location:
kernel/generic
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/proc/thread.h

    r0843f02 rdf58e44  
    9191       
    9292        /** Function implementing the thread. */
    93         void (* thread_code)(void *);
     93        void (*thread_code)(void *);
    9494        /** Argument passed to thread_code() function. */
    9595        void *thread_arg;
    9696       
    9797        /**
    98          * From here, the stored context is restored when the thread is
    99          * scheduled.
     98         * From here, the stored context is restored
     99         * when the thread is scheduled.
    100100         */
    101101        context_t saved_context;
    102         /**
    103          * From here, the stored timeout context is restored when sleep times
    104          * out.
     102       
     103        /**
     104         * From here, the stored timeout context
     105         * is restored when sleep times out.
    105106         */
    106107        context_t sleep_timeout_context;
    107         /**
    108          * From here, the stored interruption context is restored when sleep is
    109          * interrupted.
     108       
     109        /**
     110         * From here, the stored interruption context
     111         * is restored when sleep is interrupted.
    110112         */
    111113        context_t sleep_interruption_context;
     
    125127         */
    126128        bool in_copy_from_uspace;
     129       
    127130        /**
    128131         * True if this thread is executing copy_to_uspace().
     
    136139         */
    137140        bool interrupted;
     141       
     142        /**
     143         * If true, the scheduler will print a stack trace
     144         * to the kernel console upon scheduling this thread.
     145         */
     146        bool btrace;
    138147       
    139148        /** If true, thread_join_timeout() cannot be used on this thread. */
     
    236245extern void thread_update_accounting(bool);
    237246extern bool thread_exists(thread_t *);
     247extern void thread_stack_trace(thread_id_t);
    238248
    239249/** Fpu context slab cache. */
  • kernel/generic/src/console/cmd.c

    r0843f02 rdf58e44  
    7878static cmd_info_t help_info = {
    7979        .name = "help",
    80         .description = "List of supported commands.",
     80        .description = "List supported commands.",
    8181        .func = cmd_help,
    8282        .argc = 0
    8383};
    8484
     85/* Data and methods for 'reboot' command. */
    8586static int cmd_reboot(cmd_arg_t *argv);
    8687static cmd_info_t reboot_info = {
    8788        .name = "reboot",
    88         .description = "Reboot.",
     89        .description = "Reboot system.",
    8990        .func = cmd_reboot,
    9091        .argc = 0
    9192};
    9293
     94/* Data and methods for 'uptime' command. */
    9395static int cmd_uptime(cmd_arg_t *argv);
    9496static cmd_info_t uptime_info = {
    9597        .name = "uptime",
    96         .description = "Print uptime information.",
     98        .description = "Show system uptime.",
    9799        .func = cmd_uptime,
    98100        .argc = 0
    99101};
    100102
     103/* Data and methods for 'continue' command. */
    101104static int cmd_continue(cmd_arg_t *argv);
    102105static cmd_info_t continue_info = {
     
    108111
    109112#ifdef CONFIG_TEST
     113/* Data and methods for 'test' command. */
    110114static char test_buf[MAX_CMDLINE + 1];
    111115static int cmd_test(cmd_arg_t *argv);
     
    119123static cmd_info_t test_info = {
    120124        .name = "test",
    121         .description = "Print list of kernel tests or run a test.",
     125        .description = "<test> List kernel tests or run a test.",
    122126        .func = cmd_test,
    123127        .argc = 1,
     
    125129};
    126130
     131/* Data and methods for 'bench' command. */
    127132static int cmd_bench(cmd_arg_t *argv);
    128133static cmd_arg_t bench_argv[] = {
     
    138143static cmd_info_t bench_info = {
    139144        .name = "bench",
    140         .description = "Run kernel test as benchmark.",
     145        .description = "<test> <count> Run kernel test as benchmark.",
    141146        .func = cmd_bench,
    142147        .argc = 2,
     
    148153static int cmd_desc(cmd_arg_t *argv);
    149154static void desc_help(void);
    150 static char desc_buf[MAX_CMDLINE+1];
     155static char desc_buf[MAX_CMDLINE + 1];
    151156static cmd_arg_t desc_argv = {
    152157        .type = ARG_TYPE_STRING,
     
    156161static cmd_info_t desc_info = {
    157162        .name = "describe",
    158         .description = "Describe specified command.",
     163        .description = "<command> Describe specified command.",
    159164        .help = desc_help,
    160165        .func = cmd_desc,
     
    165170/* Data and methods for 'symaddr' command. */
    166171static int cmd_symaddr(cmd_arg_t *argv);
    167 static char symaddr_buf[MAX_CMDLINE+1];
     172static char symaddr_buf[MAX_CMDLINE + 1];
    168173static cmd_arg_t symaddr_argv = {
    169174        .type = ARG_TYPE_STRING,
     
    173178static cmd_info_t symaddr_info = {
    174179        .name = "symaddr",
    175         .description = "Return symbol address.",
     180        .description = "<symbol> Return symbol address.",
    176181        .func = cmd_symaddr,
    177182        .argc = 1,
     
    179184};
    180185
    181 static char set_buf[MAX_CMDLINE+1];
     186/* Data and methods for 'set4' command. */
     187static char set_buf[MAX_CMDLINE + 1];
    182188static int cmd_set4(cmd_arg_t *argv);
    183189static cmd_arg_t set4_argv[] = {
     
    193199static cmd_info_t set4_info = {
    194200        .name = "set4",
    195         .description = "set <dest_addr> <value> - 4byte version",
     201        .description = "<addr> <value> Set 4B memory location to a value.",
    196202        .func = cmd_set4,
    197203        .argc = 2,
     
    213219static cmd_info_t call0_info = {
    214220        .name = "call0",
    215         .description = "call0 <function> -> call function().",
     221        .description = "<function> Call function().",
    216222        .func = cmd_call0,
    217223        .argc = 1,
     
    228234static cmd_info_t mcall0_info = {
    229235        .name = "mcall0",
    230         .description = "mcall0 <function> -> call function() on each CPU.",
     236        .description = "<function> Call function() on each CPU.",
    231237        .func = cmd_mcall0,
    232238        .argc = 1,
     
    250256static cmd_info_t call1_info = {
    251257        .name = "call1",
    252         .description = "call1 <function> <arg1> -> call function(arg1).",
     258        .description = "<function> <arg1> Call function(arg1).",
    253259        .func = cmd_call1,
    254260        .argc = 2,
     
    277283static cmd_info_t call2_info = {
    278284        .name = "call2",
    279         .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
     285        .description = "<function> <arg1> <arg2> Call function(arg1, arg2).",
    280286        .func = cmd_call2,
    281287        .argc = 3,
     
    310316static cmd_info_t call3_info = {
    311317        .name = "call3",
    312         .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
     318        .description = "<function> <arg1> <arg2> <arg3> Call function(arg1, arg2, arg3).",
    313319        .func = cmd_call3,
    314320        .argc = 4,
     
    340346cmd_info_t tlb_info = {
    341347        .name = "tlb",
    342         .description = "Print TLB of current processor.",
     348        .description = "Print TLB of the current CPU.",
    343349        .help = NULL,
    344350        .func = cmd_tlb,
     
    377383};
    378384
     385/* Data and methods for 'btrace' command */
     386static int cmd_btrace(cmd_arg_t *argv);
     387static cmd_arg_t btrace_argv = {
     388        .type = ARG_TYPE_INT,
     389};
     390static cmd_info_t btrace_info = {
     391        .name = "btrace",
     392        .description = "<threadid> Show thread stack trace.",
     393        .func = cmd_btrace,
     394        .argc = 1,
     395        .argv = &btrace_argv
     396};
    379397
    380398static int cmd_sched(cmd_arg_t *argv);
    381399static cmd_info_t sched_info = {
    382400        .name = "scheduler",
    383         .description = "List all scheduler information.",
     401        .description = "Show scheduler information.",
    384402        .func = cmd_sched,
    385403        .argc = 0
     
    406424static cmd_info_t zones_info = {
    407425        .name = "zones",
    408         .description = "List of memory zones.",
     426        .description = "List memory zones.",
    409427        .func = cmd_zones,
    410428        .argc = 0
     429};
     430
     431/* Data and methods for 'zone' command */
     432static int cmd_zone(cmd_arg_t *argv);
     433static cmd_arg_t zone_argv = {
     434        .type = ARG_TYPE_INT,
     435};
     436
     437static cmd_info_t zone_info = {
     438        .name = "zone",
     439        .description = "<zone> Show memory zone structure.",
     440        .func = cmd_zone,
     441        .argc = 1,
     442        .argv = &zone_argv
    411443};
    412444
     
    418450static cmd_info_t ipc_info = {
    419451        .name = "ipc",
    420         .description = "ipc <taskid> Show IPC information of given task.",
     452        .description = "<taskid> Show IPC information of a task.",
    421453        .func = cmd_ipc,
    422454        .argc = 1,
     
    431463static cmd_info_t kill_info = {
    432464        .name = "kill",
    433         .description = "kill <taskid> Kill a task.",
     465        .description = "<taskid> Kill a task.",
    434466        .func = cmd_kill,
    435467        .argc = 1,
    436468        .argv = &kill_argv
    437 };
    438 
    439 /* Data and methods for 'zone' command */
    440 static int cmd_zone(cmd_arg_t *argv);
    441 static cmd_arg_t zone_argv = {
    442         .type = ARG_TYPE_INT,
    443 };
    444 
    445 static cmd_info_t zone_info = {
    446         .name = "zone",
    447         .description = "Show memory zone structure.",
    448         .func = cmd_zone,
    449         .argc = 1,
    450         .argv = &zone_argv
    451469};
    452470
     
    474492
    475493static cmd_info_t *basic_commands[] = {
     494        &btrace_info,
    476495        &call0_info,
    477496        &mcall0_info,
     
    482501        &cpus_info,
    483502        &desc_info,
    484         &reboot_info,
    485         &uptime_info,
    486503        &halt_info,
    487504        &help_info,
    488505        &ipc_info,
    489506        &kill_info,
     507        &physmem_info,
     508        &reboot_info,
     509        &sched_info,
    490510        &set4_info,
    491511        &slabs_info,
     512        &symaddr_info,
    492513        &sysinfo_info,
    493         &symaddr_info,
    494         &sched_info,
     514        &tasks_info,
    495515        &threads_info,
    496         &tasks_info,
    497         &physmem_info,
    498516        &tlb_info,
     517        &uptime_info,
    499518        &version_info,
    500519        &zones_info,
     
    531550}
    532551
    533 
    534552/** List supported commands.
    535553 *
     
    574592}
    575593
    576 
    577594/** Reboot the system.
    578595 *
     
    588605        return 1;
    589606}
    590 
    591607
    592608/** Print system uptime information.
     
    824840}
    825841
    826 
    827842/** Print detailed description of 'describe' command. */
    828843void desc_help(void)
     
    911926 * @return Always 1
    912927 */
    913 int cmd_slabs(cmd_arg_t * argv)
     928int cmd_slabs(cmd_arg_t *argv)
    914929{
    915930        slab_print_list();
     
    923938 * @return Always 1
    924939 */
    925 int cmd_sysinfo(cmd_arg_t * argv)
     940int cmd_sysinfo(cmd_arg_t *argv)
    926941{
    927942        sysinfo_dump(NULL);
     
    929944}
    930945
    931 
    932 /** Command for listings Thread information
     946/** Command for listing thread information
    933947 *
    934948 * @param argv Ignored
     
    948962}
    949963
    950 /** Command for listings Task information
     964/** Command for listing task information
    951965 *
    952966 * @param argv Ignored
     
    966980}
    967981
    968 /** Command for listings Thread information
     982/** Command for printing thread stack trace
     983 *
     984 * @param argv Integer argument from cmdline expected
     985 *
     986 * return Always 1
     987 *
     988 */
     989int cmd_btrace(cmd_arg_t *argv)
     990{
     991        thread_stack_trace(argv[0].intval);
     992        return 1;
     993}
     994
     995/** Command for printing scheduler information
    969996 *
    970997 * @param argv Ignores
     
    972999 * @return Always 1
    9731000 */
    974 int cmd_sched(cmd_arg_t * argv)
     1001int cmd_sched(cmd_arg_t *argv)
    9751002{
    9761003        sched_print_list();
     
    9841011 * return Always 1
    9851012 */
    986 int cmd_zones(cmd_arg_t * argv)
     1013int cmd_zones(cmd_arg_t *argv)
    9871014{
    9881015        zones_print_list();
     
    9961023 * return Always 1
    9971024 */
    998 int cmd_zone(cmd_arg_t * argv)
     1025int cmd_zone(cmd_arg_t *argv)
    9991026{
    10001027        zone_print_one(argv[0].intval);
     
    10021029}
    10031030
    1004 /** Command for printing task ipc details
     1031/** Command for printing task IPC details
    10051032 *
    10061033 * @param argv Integer argument from cmdline expected
     
    10081035 * return Always 1
    10091036 */
    1010 int cmd_ipc(cmd_arg_t * argv)
     1037int cmd_ipc(cmd_arg_t *argv)
    10111038{
    10121039        ipc_print_task(argv[0].intval);
     
    10201047 * return 0 on failure, 1 on success.
    10211048 */
    1022 int cmd_kill(cmd_arg_t * argv)
     1049int cmd_kill(cmd_arg_t *argv)
    10231050{
    10241051        if (task_kill(argv[0].intval) != EOK)
  • kernel/generic/src/proc/scheduler.c

    r0843f02 rdf58e44  
    6262#include <print.h>
    6363#include <debug.h>
     64#include <stacktrace.h>
    6465
    6566static void scheduler_separated_stack(void);
     
    7778 * Perform actions that need to be
    7879 * taken before the newly selected
    79  * tread is passed control.
     80 * thread is passed control.
    8081 *
    8182 * THREAD->lock is locked on entry
     
    8788       
    8889#ifdef CONFIG_FPU_LAZY
    89         if(THREAD == CPU->fpu_owner)
     90        if (THREAD == CPU->fpu_owner)
    9091                fpu_enable();
    9192        else
     
    100101        }
    101102#endif
     103       
     104        if (THREAD->btrace) {
     105                istate_t *istate = THREAD->udebug.uspace_state;
     106                if (istate != NULL) {
     107                        printf("Thread %" PRIu64 " stack trace:\n", THREAD->tid);
     108                        stack_trace_istate(istate);
     109                }
     110               
     111                THREAD->btrace = false;
     112        }
    102113}
    103114
     
    645656                                /*
    646657                                 * Ready thread on local CPU
    647                                  *
    648658                                 */
    649659                               
  • kernel/generic/src/proc/task.c

    r0843f02 rdf58e44  
    449449static void task_kill_internal(task_t *task)
    450450{
     451        irq_spinlock_lock(&task->lock, false);
     452        irq_spinlock_lock(&threads_lock, false);
     453       
     454        /*
     455         * Interrupt all threads.
     456         */
     457       
    451458        link_t *cur;
    452        
    453         /*
    454          * Interrupt all threads.
    455          */
    456         irq_spinlock_lock(&task->lock, false);
    457459        for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
    458460                thread_t *thread = list_get_instance(cur, thread_t, th_link);
     
    471473        }
    472474       
     475        irq_spinlock_unlock(&threads_lock, false);
    473476        irq_spinlock_unlock(&task->lock, false);
    474477}
  • kernel/generic/src/proc/thread.c

    r0843f02 rdf58e44  
    239239 * Switch thread to the ready state.
    240240 *
    241  * @param t Thread to make ready.
     241 * @param thread Thread to make ready.
    242242 *
    243243 */
     
    246246        irq_spinlock_lock(&thread->lock, true);
    247247       
    248         ASSERT(!(thread->state == Ready));
     248        ASSERT(thread->state != Ready);
    249249       
    250250        int i = (thread->priority < RQ_COUNT - 1)
     
    338338       
    339339        thread->interrupted = false;
     340        thread->btrace = false;
    340341        thread->detached = false;
    341342        waitq_initialize(&thread->join_wq);
     
    535536/** Detach thread.
    536537 *
    537  * Mark the thread as detached, if the thread is already in the Lingering
    538  * state, deallocate its resources.
     538 * Mark the thread as detached. If the thread is already
     539 * in the Lingering state, deallocate its resources.
    539540 *
    540541 * @param thread Thread to be detached.
     
    740741        ASSERT(interrupts_disabled());
    741742        ASSERT(irq_spinlock_locked(&threads_lock));
    742 
     743       
    743744        thread_iterator_t iterator;
    744745       
     
    751752}
    752753
     754void thread_stack_trace(thread_id_t thread_id)
     755{
     756        irq_spinlock_lock(&threads_lock, true);
     757       
     758        thread_t *thread = thread_find_by_id(thread_id);
     759        if (thread == NULL) {
     760                printf("No such thread.\n");
     761                irq_spinlock_unlock(&threads_lock, true);
     762                return;
     763        }
     764       
     765        irq_spinlock_lock(&thread->lock, false);
     766       
     767        /*
     768         * Schedule a stack trace to be printed
     769         * just before the thread is scheduled next.
     770         *
     771         * If the thread is sleeping then try to interrupt
     772         * the sleep. Any request for printing an uspace stack
     773         * trace from within the kernel should be always
     774         * considered a last resort debugging means, therefore
     775         * forcing the thread's sleep to be interrupted
     776         * is probably justifiable.
     777         */
     778       
     779        bool sleeping = false;
     780        istate_t *istate = thread->udebug.uspace_state;
     781        if (istate != NULL) {
     782                printf("Scheduling thread stack trace.\n");
     783                thread->btrace = true;
     784                if (thread->state == Sleeping)
     785                        sleeping = true;
     786        } else
     787                printf("Thread interrupt state not available.\n");
     788       
     789        irq_spinlock_unlock(&thread->lock, false);
     790       
     791        if (sleeping)
     792                waitq_interrupt_sleep(thread);
     793       
     794        irq_spinlock_unlock(&threads_lock, true);
     795}
    753796
    754797/** Process syscall to create new thread.
     
    793836                                 * has already been created. We need to undo its
    794837                                 * creation now.
    795                                  *
    796838                                 */
    797839                               
     
    815857                 * THREAD_B events for threads that already existed
    816858                 * and could be detected with THREAD_READ before.
    817                  *
    818859                 */
    819860                udebug_thread_b_event_attach(thread, TASK);
  • kernel/generic/src/synch/waitq.c

    r0843f02 rdf58e44  
    127127/** Interrupt sleeping thread.
    128128 *
    129  * This routine attempts to interrupt a thread from its sleep in a waitqueue.
    130  * If the thread is not found sleeping, no action is taken.
     129 * This routine attempts to interrupt a thread from its sleep in
     130 * a waitqueue. If the thread is not found sleeping, no action
     131 * is taken.
     132 *
     133 * The threads_lock must be already held and interrupts must be
     134 * disabled upon calling this function.
    131135 *
    132136 * @param thread Thread to be interrupted.
     
    138142        DEADLOCK_PROBE_INIT(p_wqlock);
    139143       
    140         irq_spinlock_lock(&threads_lock, true);
    141         if (!thread_exists(thread))
    142                 goto out;
     144        /*
     145         * The thread is quaranteed to exist because
     146         * threads_lock is held.
     147         */
    143148       
    144149grab_locks:
     
    150155                        /*
    151156                         * The sleep cannot be interrupted.
    152                          *
    153157                         */
    154158                        irq_spinlock_unlock(&thread->lock, false);
    155                         goto out;
     159                        return;
    156160                }
    157161               
    158162                if (!irq_spinlock_trylock(&wq->lock)) {
     163                        /* Avoid deadlock */
    159164                        irq_spinlock_unlock(&thread->lock, false);
    160165                        DEADLOCK_PROBE(p_wqlock, DEADLOCK_THRESHOLD);
    161                         /* Avoid deadlock */
    162166                        goto grab_locks;
    163167                }
     
    173177                irq_spinlock_unlock(&wq->lock, false);
    174178        }
     179       
    175180        irq_spinlock_unlock(&thread->lock, false);
    176181       
    177182        if (do_wakeup)
    178183                thread_ready(thread);
    179        
    180 out:
    181         irq_spinlock_unlock(&threads_lock, true);
    182184}
    183185
     
    370372                 * If the thread was already interrupted,
    371373                 * don't go to sleep at all.
    372                  *
    373374                 */
    374375                if (THREAD->interrupted) {
     
    381382                 * Set context that will be restored if the sleep
    382383                 * of this thread is ever interrupted.
    383                  *
    384384                 */
    385385                THREAD->sleep_interruptible = true;
Note: See TracChangeset for help on using the changeset viewer.