Changeset 371bd7d in mainline for kernel/generic/src/udebug


Ignore:
Timestamp:
2010-03-27T09:22:17Z (16 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
36a75a2
Parents:
cd82bb1 (diff), eaf22d4 (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 mainline changes.

Location:
kernel/generic/src/udebug
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/udebug/udebug.c

    rcd82bb1 r371bd7d  
    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
     
    456460}
    457461
     462/** Wait for debugger to handle a fault in this thread.
     463 *
     464 * When a thread faults and someone is subscribed to the FAULT kernel event,
     465 * this function is called to wait for a debugging session to give userspace
     466 * a chance to examine the faulting thead/task. When the debugging session
     467 * is over, this function returns (so that thread/task cleanup can continue).
     468 */
     469void udebug_thread_fault(void)
     470{
     471        udebug_stoppable_begin();
     472
     473        /* Wait until a debugger attends to us. */
     474        mutex_lock(&THREAD->udebug.lock);
     475        while (!THREAD->udebug.active)
     476                condvar_wait(&THREAD->udebug.active_cv, &THREAD->udebug.lock);
     477        mutex_unlock(&THREAD->udebug.lock);
     478
     479        /* Make sure the debugging session is over before proceeding. */
     480        mutex_lock(&THREAD->udebug.lock);
     481        while (THREAD->udebug.active)
     482                condvar_wait(&THREAD->udebug.active_cv, &THREAD->udebug.lock);
     483        mutex_unlock(&THREAD->udebug.lock);
     484
     485        udebug_stoppable_end();
     486}
    458487
    459488/** @}
  • kernel/generic/src/udebug/udebug_ipc.c

    rcd82bb1 r371bd7d  
    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 a NAME_READ call.
     205 *
     206 * Returns a string containing the name of the task.
     207 *
     208 * @param call  The call structure.
     209 */
     210static void udebug_receive_name_read(call_t *call)
     211{
    167212        unative_t uspace_addr;
    168213        unative_t to_copy;
    169         unsigned total_bytes;
    170         unsigned buf_size;
    171         void *buffer;
    172         size_t n;
    173         int rc;
     214        size_t data_size;
     215        size_t buf_size;
     216        void *data;
    174217
    175218        uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
     
    177220
    178221        /*
    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;
     222         * Read task name.
     223         */
     224        udebug_name_read((char **) &data, &data_size);
     225
     226        /* Copy MAX(buf_size, data_size) bytes */
     227
     228        if (buf_size > data_size)
     229                to_copy = data_size;
    195230        else
    196231                to_copy = buf_size;
     
    207242        IPC_SET_ARG2(call->data, to_copy);
    208243
    209         IPC_SET_ARG3(call->data, total_bytes);
    210         call->buffer = buffer;
    211 
    212         ipc_answer(&TASK->kb.box, call);
    213 }
     244        IPC_SET_ARG3(call->data, data_size);
     245        call->buffer = data;
     246
     247        ipc_answer(&TASK->kb.box, call);
     248}
     249
     250/** Process an AREAS_READ call.
     251 *
     252 * Returns a list of address space areas in the current task, as an array
     253 * of as_area_info_t structures.
     254 *
     255 * @param call  The call structure.
     256 */
     257static void udebug_receive_areas_read(call_t *call)
     258{
     259        unative_t uspace_addr;
     260        unative_t to_copy;
     261        size_t data_size;
     262        size_t buf_size;
     263        void *data;
     264
     265        uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
     266        buf_size = IPC_GET_ARG3(call->data);    /* Dest. buffer size */
     267
     268        /*
     269         * Read area list.
     270         */
     271        as_get_area_info(AS, (as_area_info_t **) &data, &data_size);
     272
     273        /* Copy MAX(buf_size, data_size) bytes */
     274
     275        if (buf_size > data_size)
     276                to_copy = data_size;
     277        else
     278                to_copy = buf_size;
     279
     280        /*
     281         * Make use of call->buffer to transfer data to caller's userspace
     282         */
     283
     284        IPC_SET_RETVAL(call->data, 0);
     285        /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
     286           same code in process_answer() can be used
     287           (no way to distinguish method in answer) */
     288        IPC_SET_ARG1(call->data, uspace_addr);
     289        IPC_SET_ARG2(call->data, to_copy);
     290
     291        IPC_SET_ARG3(call->data, data_size);
     292        call->buffer = data;
     293
     294        ipc_answer(&TASK->kb.box, call);
     295}
     296
    214297
    215298/** Process an ARGS_READ call.
     
    250333        ipc_answer(&TASK->kb.box, call);
    251334}
     335
     336/** Receive a REGS_READ call.
     337 *
     338 * Reads the thread's register state (istate structure).
     339 */
     340static void udebug_receive_regs_read(call_t *call)
     341{
     342        thread_t *t;
     343        unative_t uspace_addr;
     344        unative_t to_copy;
     345        void *buffer;
     346        int rc;
     347
     348        t = (thread_t *) IPC_GET_ARG2(call->data);
     349
     350        rc = udebug_regs_read(t, &buffer);
     351        if (rc < 0) {
     352                IPC_SET_RETVAL(call->data, rc);
     353                ipc_answer(&TASK->kb.box, call);
     354                return;
     355        }
     356
     357        /*
     358         * Make use of call->buffer to transfer data to caller's userspace
     359         */
     360
     361        uspace_addr = IPC_GET_ARG3(call->data);
     362        to_copy = sizeof(istate_t);
     363
     364        IPC_SET_RETVAL(call->data, 0);
     365        /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
     366           same code in process_answer() can be used
     367           (no way to distinguish method in answer) */
     368        IPC_SET_ARG1(call->data, uspace_addr);
     369        IPC_SET_ARG2(call->data, to_copy);
     370
     371        call->buffer = buffer;
     372
     373        ipc_answer(&TASK->kb.box, call);
     374}
     375
    252376
    253377/** Process an MEM_READ call.
     
    331455                udebug_receive_thread_read(call);
    332456                break;
     457        case UDEBUG_M_NAME_READ:
     458                udebug_receive_name_read(call);
     459                break;
     460        case UDEBUG_M_AREAS_READ:
     461                udebug_receive_areas_read(call);
     462                break;
    333463        case UDEBUG_M_ARGS_READ:
    334464                udebug_receive_args_read(call);
    335465                break;
     466        case UDEBUG_M_REGS_READ:
     467                udebug_receive_regs_read(call);
     468                break;
    336469        case UDEBUG_M_MEM_READ:
    337470                udebug_receive_mem_read(call);
  • kernel/generic/src/udebug/udebug_ops.c

    rcd82bb1 r371bd7d  
    4646#include <errno.h>
    4747#include <print.h>
     48#include <str.h>
    4849#include <syscall/copy.h>
    4950#include <ipc/ipc.h>
    5051#include <udebug/udebug.h>
    5152#include <udebug/udebug_ops.h>
     53#include <memstr.h>
    5254
    5355/**
     
    7880static int _thread_op_begin(thread_t *t, bool being_go)
    7981{
    80         task_id_t taskid;
    8182        ipl_t ipl;
    82 
    83         taskid = TASK->taskid;
    8483
    8584        mutex_lock(&TASK->udebug.lock);
     
    208207
    209208                mutex_lock(&t->udebug.lock);
    210                 if ((t->flags & THREAD_FLAG_USPACE) != 0)
     209                if ((t->flags & THREAD_FLAG_USPACE) != 0) {
    211210                        t->udebug.active = true;
    212                 mutex_unlock(&t->udebug.lock);
     211                        mutex_unlock(&t->udebug.lock);
     212                        condvar_broadcast(&t->udebug.active_cv);
     213                } else {
     214                        mutex_unlock(&t->udebug.lock);
     215                }
    213216        }
    214217
     
    354357 *
    355358 * If the sequence is longer than @a buf_size bytes, only as much hashes
    356  * as can fit are copied. The number of thread hashes copied is stored
    357  * in @a n.
     359 * as can fit are copied. The number of bytes copied is stored in @a stored.
     360 * The total number of thread bytes that could have been saved had there been
     361 * enough space is stored in @a needed.
    358362 *
    359363 * The rationale for having @a buf_size is that this function is only
     
    363367 * @param buffer        The buffer for storing thread hashes.
    364368 * @param buf_size      Buffer size in bytes.
    365  * @param n             The actual number of hashes copied will be stored here.
    366  */
    367 int udebug_thread_read(void **buffer, size_t buf_size, size_t *n)
     369 * @param stored        The actual number of bytes copied will be stored here.
     370 * @param needed        Total number of hashes that could have been saved.
     371 */
     372int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored,
     373    size_t *needed)
    368374{
    369375        thread_t *t;
    370376        link_t *cur;
    371377        unative_t tid;
    372         unsigned copied_ids;
     378        size_t copied_ids;
     379        size_t extra_ids;
    373380        ipl_t ipl;
    374381        unative_t *id_buffer;
     
    379386
    380387        /* Allocate a buffer to hold thread IDs */
    381         id_buffer = malloc(buf_size, 0);
     388        id_buffer = malloc(buf_size + 1, 0);
    382389
    383390        mutex_lock(&TASK->udebug.lock);
     
    395402        max_ids = buf_size / sizeof(unative_t);
    396403        copied_ids = 0;
     404        extra_ids = 0;
    397405
    398406        /* FIXME: make sure the thread isn't past debug shutdown... */
    399407        for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
    400                 /* Do not write past end of buffer */
    401                 if (copied_ids >= max_ids) break;
    402 
    403408                t = list_get_instance(cur, thread_t, th_link);
    404409
     
    408413
    409414                /* Not interested in kernel threads. */
    410                 if ((flags & THREAD_FLAG_USPACE) != 0) {
     415                if ((flags & THREAD_FLAG_USPACE) == 0)
     416                        continue;
     417
     418                if (copied_ids < max_ids) {
    411419                        /* Using thread struct pointer as identification hash */
    412420                        tid = (unative_t) t;
    413421                        id_buffer[copied_ids++] = tid;
     422                } else {
     423                        extra_ids++;
    414424                }
    415425        }
     
    421431
    422432        *buffer = id_buffer;
    423         *n = copied_ids * sizeof(unative_t);
     433        *stored = copied_ids * sizeof(unative_t);
     434        *needed = (copied_ids + extra_ids) * sizeof(unative_t);
     435
     436        return 0;
     437}
     438
     439/** Read task name.
     440 *
     441 * Returns task name as non-terminated string in a newly allocated buffer.
     442 * Also returns the size of the data.
     443 *
     444 * @param data          Place to store pointer to newly allocated block.
     445 * @param data_size     Place to store size of the data.
     446 *
     447 * @returns             EOK.
     448 */
     449int udebug_name_read(char **data, size_t *data_size)
     450{
     451        size_t name_size;
     452
     453        name_size = str_size(TASK->name) + 1;
     454        *data = malloc(name_size, 0);
     455        *data_size = name_size;
     456
     457        memcpy(*data, TASK->name, name_size);
    424458
    425459        return 0;
     
    436470 * this function will fail with an EINVAL error code.
    437471 *
    438  * @param buffer        The buffer for storing thread hashes.
     472 * @param t             Thread where call arguments are to be read.
     473 * @param buffer        Place to store pointer to new buffer.
     474 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     475 *                      if thread state is not valid for this operation.
    439476 */
    440477int udebug_args_read(thread_t *t, void **buffer)
     
    468505}
    469506
     507/** Read the register state of the thread.
     508 *
     509 * The contents of the thread's istate structure are copied to a newly
     510 * allocated buffer and a pointer to it is written to @a buffer. The size of
     511 * the buffer will be sizeof(istate_t).
     512 *
     513 * Currently register state cannot be read if the thread is inside a system
     514 * call (as opposed to an exception). This is an implementation limit.
     515 *
     516 * @param t             Thread whose state is to be read.
     517 * @param buffer        Place to store pointer to new buffer.
     518 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     519 *                      if thread is not in valid state, EBUSY if istate
     520 *                      is not available.
     521 */
     522int udebug_regs_read(thread_t *t, void **buffer)
     523{
     524        istate_t *state, *state_buf;
     525        int rc;
     526
     527        /* Prepare a buffer to hold the data. */
     528        state_buf = malloc(sizeof(istate_t), 0);
     529
     530        /* On success, this will lock t->udebug.lock */
     531        rc = _thread_op_begin(t, false);
     532        if (rc != EOK) {
     533                return rc;
     534        }
     535
     536        state = t->udebug.uspace_state;
     537        if (state == NULL) {
     538                _thread_op_end(t);
     539                return EBUSY;
     540        }
     541
     542        /* Copy to the allocated buffer */
     543        memcpy(state_buf, state, sizeof(istate_t));
     544
     545        _thread_op_end(t);
     546
     547        *buffer = (void *) state_buf;
     548        return 0;
     549}
     550
    470551/** Read the memory of the debugged task.
    471552 *
Note: See TracChangeset for help on using the changeset viewer.