Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset fea0ce6 in mainline


Ignore:
Timestamp:
2010-01-23T20:20:54Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
e095644
Parents:
9d3133d (diff), bc310a05 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge task dump infrastructure.

Files:
4 added
16 edited

Legend:

Unmodified
Added
Removed
  • HelenOS.config

    r9d3133d rfea0ce6  
    486486% Mount /data on startup
    487487! [CONFIG_START_BD=y] CONFIG_MOUNT_DATA (n/y)
     488
     489% Verbose task dumps
     490! CONFIG_VERBOSE_DUMPS (n/y)
  • boot/Makefile.common

    r9d3133d rfea0ce6  
    5656        $(USPACEDIR)/srv/fs/devfs/devfs \
    5757        $(USPACEDIR)/srv/fs/tmpfs/tmpfs \
    58         $(USPACEDIR)/srv/fs/fat/fat
     58        $(USPACEDIR)/srv/fs/fat/fat \
     59        $(USPACEDIR)/srv/taskmon/taskmon
    5960
    6061RD_APPS = \
     
    6566        $(USPACEDIR)/app/mkfat/mkfat \
    6667        $(USPACEDIR)/app/redir/redir \
     68        $(USPACEDIR)/app/taskdump/taskdump \
    6769        $(USPACEDIR)/app/tester/tester \
    6870        $(USPACEDIR)/app/tetris/tetris \
  • kernel/generic/include/interrupt.h

    r9d3133d rfea0ce6  
    4646typedef void (* iroutine)(int n, istate_t *istate);
    4747
    48 #define fault_if_from_uspace(istate, fmt, ...) \
    49 { \
    50         if (istate_from_uspace(istate)) { \
    51                 task_t *task = TASK; \
    52                 printf("Task %s (%" PRIu64 ") killed due to an exception at " \
    53                     "program counter %p.\n", task->name, task->taskid, istate_get_pc(istate)); \
    54                 stack_trace_istate(istate); \
    55                 printf("Kill message: " fmt "\n", ##__VA_ARGS__); \
    56                 task_kill(task->taskid); \
    57                 thread_exit(); \
    58         } \
    59 }
    60 
     48extern void fault_if_from_uspace(istate_t *istate, char *fmt, ...);
    6149extern iroutine exc_register(int n, const char *name, iroutine f);
    6250extern void exc_dispatch(int n, istate_t *t);
  • kernel/generic/include/ipc/event_types.h

    r9d3133d rfea0ce6  
    3737
    3838typedef enum event_type {
     39        /** New data available in kernel log */
    3940        EVENT_KLOG = 0,
     41        /** Returning from kernel console to userspace */
    4042        EVENT_KCONSOLE,
     43        /** A thread has faulted and will be terminated */
     44        EVENT_FAULT,
    4145        EVENT_END
    4246} event_type_t;
  • kernel/generic/include/mm/as.h

    r9d3133d rfea0ce6  
    3636#define KERN_AS_H_
    3737
     38#ifdef KERNEL
     39#include <arch/types.h>
     40#else
     41#include <sys/types.h>
     42#endif
     43
    3844/** Address space area flags. */
    3945#define AS_AREA_READ            1
     
    4147#define AS_AREA_EXEC            4
    4248#define AS_AREA_CACHEABLE       8
     49
     50/** Address space area info exported to userspace. */
     51typedef struct {
     52        /** Starting address */
     53        uintptr_t start_addr;
     54
     55        /** Area size */
     56        size_t size;
     57
     58        /** Area flags */
     59        int flags;
     60} as_area_info_t;
    4361
    4462#ifdef KERNEL
     
    268286
    269287/* Introspection functions. */
     288extern void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize);
    270289extern void as_print(as_t *as);
    271290
  • kernel/generic/include/udebug/udebug.h

    r9d3133d rfea0ce6  
    9696 */
    9797UDEBUG_M_THREAD_READ,
     98
     99/** Read the list of the debugged task's address space areas.
     100 *
     101 * - ARG2 - destination address in the caller's address space
     102 * - ARG3 - size of receiving buffer in bytes
     103 *
     104 * The kernel fills the buffer with a series of as_area_info_t structures.
     105 * Upon answer, the kernel will set:
     106 *
     107 * - ARG2 - number of bytes that were actually copied
     108 * - ARG3 - number of bytes of the complete data
     109 *
     110 */
     111UDEBUG_M_AREAS_READ,
    98112
    99113/** Read the debugged tasks's memory.
     
    139153
    140154#include <synch/mutex.h>
     155#include <synch/condvar.h>
    141156#include <arch/interrupt.h>
    142157#include <atomic.h>
     
    181196        bool stoppable;         /**< thread is stoppable */
    182197        bool active;            /**< thread is in a debugging session */
     198        condvar_t active_cv;
    183199} udebug_thread_t;
    184200
  • kernel/generic/include/udebug/udebug_ops.h

    r9d3133d rfea0ce6  
    4545int udebug_stop(thread_t *t, call_t *call);
    4646
    47 int udebug_thread_read(void **buffer, size_t buf_size, size_t *n);
     47int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored,
     48    size_t *needed);
    4849int udebug_args_read(thread_t *t, void **buffer);
    4950
  • kernel/generic/src/interrupt/interrupt.c

    r9d3133d rfea0ce6  
    4444#include <console/console.h>
    4545#include <console/cmd.h>
     46#include <ipc/event.h>
     47#include <synch/mutex.h>
     48#include <time/delay.h>
     49#include <macros.h>
    4650#include <panic.h>
    4751#include <print.h>
     
    107111        fault_if_from_uspace(istate, "Unhandled exception %d.", n);
    108112        panic("Unhandled exception %d.", n);
     113}
     114
     115/** Terminate thread and task if exception came from userspace. */
     116void fault_if_from_uspace(istate_t *istate, char *fmt, ...)
     117{
     118        task_t *task = TASK;
     119        va_list args;
     120
     121        if (!istate_from_uspace(istate))
     122                return;
     123
     124        printf("Task %s (%" PRIu64 ") killed due to an exception at "
     125            "program counter %p.\n", task->name, task->taskid,
     126            istate_get_pc(istate));
     127
     128        stack_trace_istate(istate);
     129
     130        printf("Kill message: ");
     131        va_start(args, fmt);
     132        vprintf(fmt, args);
     133        va_end(args);
     134        printf("\n");
     135
     136        if (event_is_subscribed(EVENT_FAULT)) {
     137                event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
     138                    UPPER32(TASK->taskid), (unative_t) THREAD);
     139        }
     140
     141#ifdef CONFIG_UDEBUG
     142        /* Wait until a debugger attends to us. */
     143        mutex_lock(&THREAD->udebug.lock);
     144        while (!THREAD->udebug.active)
     145                condvar_wait(&THREAD->udebug.active_cv, &THREAD->udebug.lock);
     146        mutex_unlock(&THREAD->udebug.lock);
     147
     148        udebug_stoppable_begin();
     149        udebug_stoppable_end();
     150
     151        /* Make sure the debugging session is over before proceeding. */
     152        mutex_lock(&THREAD->udebug.lock);
     153        while (THREAD->udebug.active)
     154                condvar_wait(&THREAD->udebug.active_cv, &THREAD->udebug.lock);
     155        mutex_unlock(&THREAD->udebug.lock);
     156#endif
     157
     158        task_kill(task->taskid);
     159        thread_exit();
    109160}
    110161
  • kernel/generic/src/mm/as.c

    r9d3133d rfea0ce6  
    19201920}
    19211921
     1922/** Get list of adress space areas.
     1923 *
     1924 * @param as            Address space.
     1925 * @param obuf          Place to save pointer to returned buffer.
     1926 * @param osize         Place to save size of returned buffer.
     1927 */
     1928void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
     1929{
     1930        ipl_t ipl;
     1931        size_t area_cnt, area_idx, i;
     1932        link_t *cur;
     1933
     1934        as_area_info_t *info;
     1935        size_t isize;
     1936
     1937        ipl = interrupts_disable();
     1938        mutex_lock(&as->lock);
     1939
     1940        /* First pass, count number of areas. */
     1941
     1942        area_cnt = 0;
     1943
     1944        for (cur = as->as_area_btree.leaf_head.next;
     1945            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
     1946                btree_node_t *node;
     1947
     1948                node = list_get_instance(cur, btree_node_t, leaf_link);
     1949                area_cnt += node->keys;
     1950        }
     1951
     1952        isize = area_cnt * sizeof(as_area_info_t);
     1953        info = malloc(isize, 0);
     1954
     1955        /* Second pass, record data. */
     1956
     1957        area_idx = 0;
     1958
     1959        for (cur = as->as_area_btree.leaf_head.next;
     1960            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
     1961                btree_node_t *node;
     1962
     1963                node = list_get_instance(cur, btree_node_t, leaf_link);
     1964
     1965                for (i = 0; i < node->keys; i++) {
     1966                        as_area_t *area = node->value[i];
     1967
     1968                        ASSERT(area_idx < area_cnt);
     1969                        mutex_lock(&area->lock);
     1970
     1971                        info[area_idx].start_addr = area->base;
     1972                        info[area_idx].size = FRAMES2SIZE(area->pages);
     1973                        info[area_idx].flags = area->flags;
     1974                        ++area_idx;
     1975
     1976                        mutex_unlock(&area->lock);
     1977                }
     1978        }
     1979
     1980        mutex_unlock(&as->lock);
     1981        interrupts_restore(ipl);
     1982
     1983        *obuf = info;
     1984        *osize = isize;
     1985}
     1986
     1987
    19221988/** Print out information about address space.
    19231989 *
  • kernel/generic/src/udebug/udebug.c

    r9d3133d rfea0ce6  
    6969        mutex_initialize(&ut->lock, MUTEX_PASSIVE);
    7070        waitq_initialize(&ut->go_wq);
     71        condvar_initialize(&ut->active_cv);
    7172
    7273        ut->go_call = NULL;
     
    446447                                waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
    447448                        }
     449                        mutex_unlock(&t->udebug.lock);
     450                        condvar_broadcast(&t->udebug.active_cv);
     451                } else {
     452                        mutex_unlock(&t->udebug.lock);
    448453                }
    449                 mutex_unlock(&t->udebug.lock);
    450454        }
    451455
  • kernel/generic/src/udebug/udebug_ipc.c

    r9d3133d rfea0ce6  
    4141#include <proc/task.h>
    4242#include <proc/thread.h>
     43#include <mm/as.h>
    4344#include <arch.h>
    4445#include <errno.h>
     
    165166static void udebug_receive_thread_read(call_t *call)
    166167{
     168        uintptr_t uspace_addr;
     169        size_t buf_size;
     170        void *buffer;
     171        size_t copied, needed;
     172        int rc;
     173
     174        uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
     175        buf_size = IPC_GET_ARG3(call->data);    /* Dest. buffer size */
     176
     177        /*
     178         * Read thread list. Variable n will be filled with actual number
     179         * of threads times thread-id size.
     180         */
     181        rc = udebug_thread_read(&buffer, buf_size, &copied, &needed);
     182        if (rc < 0) {
     183                IPC_SET_RETVAL(call->data, rc);
     184                ipc_answer(&TASK->kb.box, call);
     185                return;
     186        }
     187
     188        /*
     189         * Make use of call->buffer to transfer data to caller's userspace
     190         */
     191
     192        IPC_SET_RETVAL(call->data, 0);
     193        /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
     194           same code in process_answer() can be used
     195           (no way to distinguish method in answer) */
     196        IPC_SET_ARG1(call->data, uspace_addr);
     197        IPC_SET_ARG2(call->data, copied);
     198        IPC_SET_ARG3(call->data, needed);
     199        call->buffer = buffer;
     200
     201        ipc_answer(&TASK->kb.box, call);
     202}
     203
     204/** Process an AREAS_READ call.
     205 *
     206 * Returns a list of address space areas in the current task, as an array
     207 * of as_area_info_t structures.
     208 *
     209 * @param call  The call structure.
     210 */
     211static void udebug_receive_areas_read(call_t *call)
     212{
    167213        unative_t uspace_addr;
    168214        unative_t to_copy;
    169         unsigned total_bytes;
    170         unsigned buf_size;
    171         void *buffer;
    172         size_t n;
    173         int rc;
     215        size_t data_size;
     216        size_t buf_size;
     217        void *data;
    174218
    175219        uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
     
    177221
    178222        /*
    179          * Read thread list. Variable n will be filled with actual number
    180          * of threads times thread-id size.
    181          */
    182         rc = udebug_thread_read(&buffer, buf_size, &n);
    183         if (rc < 0) {
    184                 IPC_SET_RETVAL(call->data, rc);
    185                 ipc_answer(&TASK->kb.box, call);
    186                 return;
    187         }
    188 
    189         total_bytes = n;
    190 
    191         /* Copy MAX(buf_size, total_bytes) bytes */
    192 
    193         if (buf_size > total_bytes)
    194                 to_copy = total_bytes;
     223         * Read area list.
     224         */
     225        as_get_area_info(AS, (as_area_info_t **) &data, &data_size);
     226
     227        /* Copy MAX(buf_size, data_size) bytes */
     228
     229        if (buf_size > data_size)
     230                to_copy = data_size;
    195231        else
    196232                to_copy = buf_size;
     
    207243        IPC_SET_ARG2(call->data, to_copy);
    208244
    209         IPC_SET_ARG3(call->data, total_bytes);
    210         call->buffer = buffer;
    211 
    212         ipc_answer(&TASK->kb.box, call);
    213 }
     245        IPC_SET_ARG3(call->data, data_size);
     246        call->buffer = data;
     247
     248        ipc_answer(&TASK->kb.box, call);
     249}
     250
    214251
    215252/** Process an ARGS_READ call.
     
    331368                udebug_receive_thread_read(call);
    332369                break;
     370        case UDEBUG_M_AREAS_READ:
     371                udebug_receive_areas_read(call);
     372                break;
    333373        case UDEBUG_M_ARGS_READ:
    334374                udebug_receive_args_read(call);
  • kernel/generic/src/udebug/udebug_ops.c

    r9d3133d rfea0ce6  
    209209
    210210                mutex_lock(&t->udebug.lock);
    211                 if ((t->flags & THREAD_FLAG_USPACE) != 0)
     211                if ((t->flags & THREAD_FLAG_USPACE) != 0) {
    212212                        t->udebug.active = true;
    213                 mutex_unlock(&t->udebug.lock);
     213                        mutex_unlock(&t->udebug.lock);
     214                        condvar_broadcast(&t->udebug.active_cv);
     215                } else {
     216                        mutex_unlock(&t->udebug.lock);
     217                }
    214218        }
    215219
     
    355359 *
    356360 * If the sequence is longer than @a buf_size bytes, only as much hashes
    357  * as can fit are copied. The number of thread hashes copied is stored
    358  * in @a n.
     361 * as can fit are copied. The number of bytes copied is stored in @a stored.
     362 * The total number of thread bytes that could have been saved had there been
     363 * enough space is stored in @a needed.
    359364 *
    360365 * The rationale for having @a buf_size is that this function is only
     
    364369 * @param buffer        The buffer for storing thread hashes.
    365370 * @param buf_size      Buffer size in bytes.
    366  * @param n             The actual number of hashes copied will be stored here.
    367  */
    368 int udebug_thread_read(void **buffer, size_t buf_size, size_t *n)
     371 * @param stored        The actual number of bytes copied will be stored here.
     372 * @param needed        Total number of hashes that could have been saved.
     373 */
     374int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored,
     375    size_t *needed)
    369376{
    370377        thread_t *t;
    371378        link_t *cur;
    372379        unative_t tid;
    373         unsigned copied_ids;
     380        size_t copied_ids;
     381        size_t extra_ids;
    374382        ipl_t ipl;
    375383        unative_t *id_buffer;
     
    380388
    381389        /* Allocate a buffer to hold thread IDs */
    382         id_buffer = malloc(buf_size, 0);
     390        id_buffer = malloc(buf_size + 1, 0);
    383391
    384392        mutex_lock(&TASK->udebug.lock);
     
    396404        max_ids = buf_size / sizeof(unative_t);
    397405        copied_ids = 0;
     406        extra_ids = 0;
    398407
    399408        /* FIXME: make sure the thread isn't past debug shutdown... */
    400409        for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
    401                 /* Do not write past end of buffer */
    402                 if (copied_ids >= max_ids) break;
    403 
    404410                t = list_get_instance(cur, thread_t, th_link);
    405411
     
    409415
    410416                /* Not interested in kernel threads. */
    411                 if ((flags & THREAD_FLAG_USPACE) != 0) {
     417                if ((flags & THREAD_FLAG_USPACE) == 0)
     418                        continue;
     419
     420                if (copied_ids < max_ids) {
    412421                        /* Using thread struct pointer as identification hash */
    413422                        tid = (unative_t) t;
    414423                        id_buffer[copied_ids++] = tid;
     424                } else {
     425                        extra_ids++;
    415426                }
    416427        }
     
    422433
    423434        *buffer = id_buffer;
    424         *n = copied_ids * sizeof(unative_t);
     435        *stored = copied_ids * sizeof(unative_t);
     436        *needed = (copied_ids + extra_ids) * sizeof(unative_t);
    425437
    426438        return 0;
  • uspace/Makefile

    r9d3133d rfea0ce6  
    4040        app/mkfat \
    4141        app/redir \
     42        app/taskdump \
    4243        app/tester \
    4344        app/tetris \
     
    4748        srv/loader \
    4849        srv/ns \
     50        srv/taskmon \
    4951        srv/vfs \
    5052        srv/bd/ata_bd \
  • uspace/app/init/init.c

    r9d3133d rfea0ce6  
    233233}
    234234
     235static void mount_scratch(void)
     236{
     237        int rc;
     238
     239        printf("Trying to mount null/0 on /scratch... ");
     240        fflush(stdout);
     241
     242        rc = mount("tmpfs", "/scratch", "null/0", "", 0);
     243        if (rc == EOK)
     244                printf("OK\n");
     245        else
     246                printf("Failed\n");
     247}
     248
    235249static void mount_data(void)
    236250{
     
    255269                return -1;
    256270        }
     271
     272        /* Make sure tmpfs is running. */
     273        if (str_cmp(STRING(RDFMT), "tmpfs") != 0) {
     274                spawn("/srv/tmpfs");
     275        }
    257276       
    258277        spawn("/srv/devfs");
     278        spawn("/srv/taskmon");
    259279       
    260280        if (!mount_devfs()) {
     
    262282                return -2;
    263283        }
     284
     285        mount_scratch();
    264286       
    265287        spawn("/srv/fhc");
  • uspace/lib/libc/generic/udebug.c

    r9d3133d rfea0ce6  
    6969}
    7070
     71int udebug_areas_read(int phoneid, void *buffer, size_t n,
     72        size_t *copied, size_t *needed)
     73{
     74        ipcarg_t a_copied, a_needed;
     75        int rc;
     76
     77        rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_AREAS_READ,
     78                (sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
     79
     80        *copied = (size_t)a_copied;
     81        *needed = (size_t)a_needed;
     82
     83        return rc;
     84}
     85
     86
    7187int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n)
    7288{
  • uspace/lib/libc/include/udebug.h

    r9d3133d rfea0ce6  
    4747int udebug_thread_read(int phoneid, void *buffer, size_t n,
    4848        size_t *copied, size_t *needed);
     49int udebug_areas_read(int phoneid, void *buffer, size_t n,
     50        size_t *copied, size_t *needed);
    4951int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n);
    5052int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer);
Note: See TracChangeset for help on using the changeset viewer.