Ignore:
Timestamp:
2010-05-24T18:57:31Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0095368
Parents:
666f492
Message:

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
File:
1 edited

Legend:

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

    r666f492 rda1bafb  
    3333/**
    3434 * @file
    35  * @brief       Udebug operations.
     35 * @brief Udebug operations.
    3636 *
    3737 * Udebug operations on tasks and threads are implemented here. The
     
    3939 * when servicing udebug IPC messages.
    4040 */
    41  
     41
    4242#include <debug.h>
    4343#include <proc/task.h>
     
    5353#include <memstr.h>
    5454
    55 /**
    56  * Prepare a thread for a debugging operation.
     55/** Prepare a thread for a debugging operation.
    5756 *
    5857 * Simply put, return thread t with t->udebug.lock held,
     
    7372 * the t->lock spinlock to the t->udebug.lock mutex.
    7473 *
    75  * @param t             Pointer, need not at all be valid.
    76  * @param being_go      Required thread state.
     74 * @param thread   Pointer, need not at all be valid.
     75 * @param being_go Required thread state.
    7776 *
    7877 * Returns EOK if all went well, or an error code otherwise.
    79  */
    80 static int _thread_op_begin(thread_t *t, bool being_go)
    81 {
    82         ipl_t ipl;
    83 
    84         mutex_lock(&TASK->udebug.lock);
    85 
     78 *
     79 */
     80static int _thread_op_begin(thread_t *thread, bool being_go)
     81{
     82        mutex_lock(&TASK->udebug.lock);
     83       
    8684        /* thread_exists() must be called with threads_lock held */
    87         ipl = interrupts_disable();
    88         spinlock_lock(&threads_lock);
    89 
    90         if (!thread_exists(t)) {
    91                 spinlock_unlock(&threads_lock);
    92                 interrupts_restore(ipl);
     85        irq_spinlock_lock(&threads_lock, true);
     86       
     87        if (!thread_exists(thread)) {
     88                irq_spinlock_unlock(&threads_lock, true);
    9389                mutex_unlock(&TASK->udebug.lock);
    9490                return ENOENT;
    9591        }
    96 
    97         /* t->lock is enough to ensure the thread's existence */
    98         spinlock_lock(&t->lock);
    99         spinlock_unlock(&threads_lock);
    100 
    101         /* Verify that 't' is a userspace thread. */
    102         if ((t->flags & THREAD_FLAG_USPACE) == 0) {
     92       
     93        /* thread->lock is enough to ensure the thread's existence */
     94        irq_spinlock_exchange(&threads_lock, &thread->lock);
     95       
     96        /* Verify that 'thread' is a userspace thread. */
     97        if ((thread->flags & THREAD_FLAG_USPACE) == 0) {
    10398                /* It's not, deny its existence */
    104                 spinlock_unlock(&t->lock);
    105                 interrupts_restore(ipl);
     99                irq_spinlock_unlock(&thread->lock, true);
    106100                mutex_unlock(&TASK->udebug.lock);
    107101                return ENOENT;
    108102        }
    109 
     103       
    110104        /* Verify debugging state. */
    111         if (t->udebug.active != true) {
     105        if (thread->udebug.active != true) {
    112106                /* Not in debugging session or undesired GO state */
    113                 spinlock_unlock(&t->lock);
    114                 interrupts_restore(ipl);
     107                irq_spinlock_unlock(&thread->lock, true);
    115108                mutex_unlock(&TASK->udebug.lock);
    116109                return ENOENT;
    117110        }
    118 
     111       
    119112        /*
    120113         * Since the thread has active == true, TASK->udebug.lock
    121114         * is enough to ensure its existence and that active remains
    122115         * true.
     116         *
    123117         */
    124         spinlock_unlock(&t->lock);
    125         interrupts_restore(ipl);
    126 
     118        irq_spinlock_unlock(&thread->lock, true);
     119       
    127120        /* Only mutex TASK->udebug.lock left. */
    128121       
    129122        /* Now verify that the thread belongs to the current task. */
    130         if (t->task != TASK) {
     123        if (thread->task != TASK) {
    131124                /* No such thread belonging this task*/
    132125                mutex_unlock(&TASK->udebug.lock);
    133126                return ENOENT;
    134127        }
    135 
     128       
    136129        /*
    137130         * Now we need to grab the thread's debug lock for synchronization
    138131         * of the threads stoppability/stop state.
     132         *
    139133         */
    140         mutex_lock(&t->udebug.lock);
    141 
     134        mutex_lock(&thread->udebug.lock);
     135       
    142136        /* The big task mutex is no longer needed. */
    143137        mutex_unlock(&TASK->udebug.lock);
    144 
    145         if (t->udebug.go != being_go) {
     138       
     139        if (thread->udebug.go != being_go) {
    146140                /* Not in debugging session or undesired GO state. */
    147                 mutex_unlock(&t->udebug.lock);
     141                mutex_unlock(&thread->udebug.lock);
    148142                return EINVAL;
    149143        }
    150 
    151         /* Only t->udebug.lock left. */
    152 
    153         return EOK;     /* All went well. */
     144       
     145        /* Only thread->udebug.lock left. */
     146       
     147        return EOK;  /* All went well. */
    154148}
    155149
    156150/** End debugging operation on a thread. */
    157 static void _thread_op_end(thread_t *t)
    158 {
    159         mutex_unlock(&t->udebug.lock);
     151static void _thread_op_end(thread_t *thread)
     152{
     153        mutex_unlock(&thread->udebug.lock);
    160154}
    161155
     
    171165 * all the threads become stoppable (i.e. they can be considered stopped).
    172166 *
    173  * @param call  The BEGIN call we are servicing.
    174  * @return      0 (OK, but not done yet), 1 (done) or negative error code.
     167 * @param call The BEGIN call we are servicing.
     168 *
     169 * @return 0 (OK, but not done yet), 1 (done) or negative error code.
     170 *
    175171 */
    176172int udebug_begin(call_t *call)
    177173{
    178         int reply;
    179 
    180         thread_t *t;
    181         link_t *cur;
    182 
    183         LOG("Debugging task %llu", TASK->taskid);
    184         mutex_lock(&TASK->udebug.lock);
    185 
     174        LOG("Debugging task %" PRIu64, TASK->taskid);
     175       
     176        mutex_lock(&TASK->udebug.lock);
     177       
    186178        if (TASK->udebug.dt_state != UDEBUG_TS_INACTIVE) {
    187179                mutex_unlock(&TASK->udebug.lock);
    188180                return EBUSY;
    189181        }
    190 
     182       
    191183        TASK->udebug.dt_state = UDEBUG_TS_BEGINNING;
    192184        TASK->udebug.begin_call = call;
    193185        TASK->udebug.debugger = call->sender;
    194 
     186       
     187        int reply;
     188       
    195189        if (TASK->udebug.not_stoppable_count == 0) {
    196190                TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
    197191                TASK->udebug.begin_call = NULL;
    198                 reply = 1; /* immediate reply */
    199         } else {
    200                 reply = 0; /* no reply */
    201         }
     192                reply = 1;  /* immediate reply */
     193        } else
     194                reply = 0;  /* no reply */
    202195       
    203196        /* Set udebug.active on all of the task's userspace threads. */
    204 
     197       
     198        link_t *cur;
    205199        for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
    206                 t = list_get_instance(cur, thread_t, th_link);
    207 
    208                 mutex_lock(&t->udebug.lock);
    209                 if ((t->flags & THREAD_FLAG_USPACE) != 0) {
    210                         t->udebug.active = true;
    211                         mutex_unlock(&t->udebug.lock);
    212                         condvar_broadcast(&t->udebug.active_cv);
    213                 } else {
    214                         mutex_unlock(&t->udebug.lock);
    215                 }
    216         }
    217 
     200                thread_t *thread = list_get_instance(cur, thread_t, th_link);
     201               
     202                mutex_lock(&thread->udebug.lock);
     203                if ((thread->flags & THREAD_FLAG_USPACE) != 0) {
     204                        thread->udebug.active = true;
     205                        mutex_unlock(&thread->udebug.lock);
     206                        condvar_broadcast(&thread->udebug.active_cv);
     207                } else
     208                        mutex_unlock(&thread->udebug.lock);
     209        }
     210       
    218211        mutex_unlock(&TASK->udebug.lock);
    219212        return reply;
     
    223216 *
    224217 * Closes the debugging session for the current task.
     218 *
    225219 * @return Zero on success or negative error code.
     220 *
    226221 */
    227222int udebug_end(void)
    228223{
    229         int rc;
    230 
    231224        LOG("Task %" PRIu64, TASK->taskid);
    232 
    233         mutex_lock(&TASK->udebug.lock);
    234         rc = udebug_task_cleanup(TASK);
    235         mutex_unlock(&TASK->udebug.lock);
    236 
     225       
     226        mutex_lock(&TASK->udebug.lock);
     227        int rc = udebug_task_cleanup(TASK);
     228        mutex_unlock(&TASK->udebug.lock);
     229       
    237230        return rc;
    238231}
     
    242235 * Sets the event mask that determines which events are enabled.
    243236 *
    244  * @param mask  Or combination of events that should be enabled.
    245  * @return      Zero on success or negative error code.
     237 * @param mask Or combination of events that should be enabled.
     238 *
     239 * @return Zero on success or negative error code.
     240 *
    246241 */
    247242int udebug_set_evmask(udebug_evmask_t mask)
    248243{
    249244        LOG("mask = 0x%x", mask);
    250 
    251         mutex_lock(&TASK->udebug.lock);
    252 
     245       
     246        mutex_lock(&TASK->udebug.lock);
     247       
    253248        if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
    254249                mutex_unlock(&TASK->udebug.lock);
    255250                return EINVAL;
    256251        }
    257 
     252       
    258253        TASK->udebug.evmask = mask;
    259254        mutex_unlock(&TASK->udebug.lock);
    260 
     255       
    261256        return 0;
    262257}
     
    268263 * a debugging event or STOP occurs, at which point the thread loses GO.
    269264 *
    270  * @param t     The thread to operate on (unlocked and need not be valid).
    271  * @param call  The GO call that we are servicing.
    272  */
    273 int udebug_go(thread_t *t, call_t *call)
    274 {
    275         int rc;
    276 
    277         /* On success, this will lock t->udebug.lock. */
    278         rc = _thread_op_begin(t, false);
    279         if (rc != EOK) {
     265 * @param thread The thread to operate on (unlocked and need not be valid).
     266 * @param call   The GO call that we are servicing.
     267 *
     268 */
     269int udebug_go(thread_t *thread, call_t *call)
     270{
     271        /* On success, this will lock thread->udebug.lock. */
     272        int rc = _thread_op_begin(thread, false);
     273        if (rc != EOK)
    280274                return rc;
    281         }
    282 
    283         t->udebug.go_call = call;
    284         t->udebug.go = true;
    285         t->udebug.cur_event = 0;        /* none */
    286 
     275       
     276        thread->udebug.go_call = call;
     277        thread->udebug.go = true;
     278        thread->udebug.cur_event = 0;  /* none */
     279       
    287280        /*
    288          * Neither t's lock nor threads_lock may be held during wakeup.
     281         * Neither thread's lock nor threads_lock may be held during wakeup.
     282         *
    289283         */
    290         waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
    291 
    292         _thread_op_end(t);
    293 
     284        waitq_wakeup(&thread->udebug.go_wq, WAKEUP_FIRST);
     285       
     286        _thread_op_end(thread);
     287       
    294288        return 0;
    295289}
     
    300294 * can be considered stopped).
    301295 *
    302  * @param t     The thread to operate on (unlocked and need not be valid).
    303  * @param call  The GO call that we are servicing.
    304  */
    305 int udebug_stop(thread_t *t, call_t *call)
    306 {
    307         int rc;
    308 
     296 * @param thread The thread to operate on (unlocked and need not be valid).
     297 * @param call   The GO call that we are servicing.
     298 *
     299 */
     300int udebug_stop(thread_t *thread, call_t *call)
     301{
    309302        LOG("udebug_stop()");
    310 
     303       
    311304        /*
    312          * On success, this will lock t->udebug.lock. Note that this makes sure
    313          * the thread is not stopped.
     305         * On success, this will lock thread->udebug.lock. Note that this
     306         * makes sure the thread is not stopped.
     307         *
    314308         */
    315         rc = _thread_op_begin(t, true);
    316         if (rc != EOK) {
     309        int rc = _thread_op_begin(thread, true);
     310        if (rc != EOK)
    317311                return rc;
    318         }
    319 
     312       
    320313        /* Take GO away from the thread. */
    321         t->udebug.go = false;
    322 
    323         if (t->udebug.stoppable != true) {
     314        thread->udebug.go = false;
     315       
     316        if (thread->udebug.stoppable != true) {
    324317                /* Answer will be sent when the thread becomes stoppable. */
    325                 _thread_op_end(t);
     318                _thread_op_end(thread);
    326319                return 0;
    327320        }
    328 
     321       
    329322        /*
    330323         * Answer GO call.
     324         *
    331325         */
    332 
     326       
    333327        /* Make sure nobody takes this call away from us. */
    334         call = t->udebug.go_call;
    335         t->udebug.go_call = NULL;
    336 
     328        call = thread->udebug.go_call;
     329        thread->udebug.go_call = NULL;
     330       
    337331        IPC_SET_RETVAL(call->data, 0);
    338332        IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP);
    339 
     333       
    340334        THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
    341 
    342         _thread_op_end(t);
    343 
     335       
     336        _thread_op_end(thread);
     337       
    344338        mutex_lock(&TASK->udebug.lock);
    345339        ipc_answer(&TASK->answerbox, call);
    346340        mutex_unlock(&TASK->udebug.lock);
    347 
     341       
    348342        return 0;
    349343}
     
    365359 * a maximum size for the userspace buffer.
    366360 *
    367  * @param buffer        The buffer for storing thread hashes.
    368  * @param buf_size      Buffer size in bytes.
    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.
     361 * @param buffer   The buffer for storing thread hashes.
     362 * @param buf_size Buffer size in bytes.
     363 * @param stored   The actual number of bytes copied will be stored here.
     364 * @param needed   Total number of hashes that could have been saved.
     365 *
    371366 */
    372367int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored,
    373368    size_t *needed)
    374369{
    375         thread_t *t;
    376         link_t *cur;
    377         unative_t tid;
    378         size_t copied_ids;
    379         size_t extra_ids;
    380         ipl_t ipl;
    381         unative_t *id_buffer;
    382         int flags;
    383         size_t max_ids;
    384 
    385370        LOG("udebug_thread_read()");
    386 
     371       
    387372        /* Allocate a buffer to hold thread IDs */
    388         id_buffer = malloc(buf_size + 1, 0);
    389 
    390         mutex_lock(&TASK->udebug.lock);
    391 
     373        unative_t *id_buffer = malloc(buf_size + 1, 0);
     374       
     375        mutex_lock(&TASK->udebug.lock);
     376       
    392377        /* Verify task state */
    393378        if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
     
    395380                return EINVAL;
    396381        }
    397 
    398         ipl = interrupts_disable();
    399         spinlock_lock(&TASK->lock);
     382       
     383        irq_spinlock_lock(&TASK->lock, true);
     384       
    400385        /* Copy down the thread IDs */
    401 
    402         max_ids = buf_size / sizeof(unative_t);
    403         copied_ids = 0;
    404         extra_ids = 0;
    405 
     386       
     387        size_t max_ids = buf_size / sizeof(unative_t);
     388        size_t copied_ids = 0;
     389        size_t extra_ids = 0;
     390       
    406391        /* FIXME: make sure the thread isn't past debug shutdown... */
     392        link_t *cur;
    407393        for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
    408                 t = list_get_instance(cur, thread_t, th_link);
    409 
    410                 spinlock_lock(&t->lock);
    411                 flags = t->flags;
    412                 spinlock_unlock(&t->lock);
    413 
     394                thread_t *thread = list_get_instance(cur, thread_t, th_link);
     395               
     396                irq_spinlock_lock(&thread->lock, false);
     397                int flags = thread->flags;
     398                irq_spinlock_unlock(&thread->lock, false);
     399               
    414400                /* Not interested in kernel threads. */
    415401                if ((flags & THREAD_FLAG_USPACE) == 0)
    416402                        continue;
    417 
     403               
    418404                if (copied_ids < max_ids) {
    419405                        /* Using thread struct pointer as identification hash */
    420                         tid = (unative_t) t;
    421                         id_buffer[copied_ids++] = tid;
    422                 } else {
     406                        id_buffer[copied_ids++] = (unative_t) thread;
     407                } else
    423408                        extra_ids++;
    424                 }
    425         }
    426 
    427         spinlock_unlock(&TASK->lock);
    428         interrupts_restore(ipl);
    429 
    430         mutex_unlock(&TASK->udebug.lock);
    431 
     409        }
     410       
     411        irq_spinlock_unlock(&TASK->lock, true);
     412       
     413        mutex_unlock(&TASK->udebug.lock);
     414       
    432415        *buffer = id_buffer;
    433416        *stored = copied_ids * sizeof(unative_t);
    434417        *needed = (copied_ids + extra_ids) * sizeof(unative_t);
    435 
     418       
    436419        return 0;
    437420}
     
    442425 * Also returns the size of the data.
    443426 *
    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.
     427 * @param data      Place to store pointer to newly allocated block.
     428 * @param data_size Place to store size of the data.
     429 *
     430 * @returns EOK.
     431 *
    448432 */
    449433int udebug_name_read(char **data, size_t *data_size)
    450434{
    451         size_t name_size;
    452 
    453         name_size = str_size(TASK->name) + 1;
     435        size_t name_size = str_size(TASK->name) + 1;
     436       
    454437        *data = malloc(name_size, 0);
    455438        *data_size = name_size;
    456 
     439       
    457440        memcpy(*data, TASK->name, name_size);
    458 
     441       
    459442        return 0;
    460443}
     
    470453 * this function will fail with an EINVAL error code.
    471454 *
    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.
    476  */
    477 int udebug_args_read(thread_t *t, void **buffer)
    478 {
    479         int rc;
    480         unative_t *arg_buffer;
    481 
     455 * @param thread Thread where call arguments are to be read.
     456 * @param buffer Place to store pointer to new buffer.
     457 *
     458 * @return EOK on success, ENOENT if @a t is invalid, EINVAL
     459 *         if thread state is not valid for this operation.
     460 *
     461 */
     462int udebug_args_read(thread_t *thread, void **buffer)
     463{
    482464        /* Prepare a buffer to hold the arguments. */
    483         arg_buffer = malloc(6 * sizeof(unative_t), 0);
    484 
     465        unative_t *arg_buffer = malloc(6 * sizeof(unative_t), 0);
     466       
    485467        /* On success, this will lock t->udebug.lock. */
    486         rc = _thread_op_begin(t, false);
    487         if (rc != EOK) {
     468        int rc = _thread_op_begin(thread, false);
     469        if (rc != EOK)
    488470                return rc;
    489         }
    490 
     471       
    491472        /* Additionally we need to verify that we are inside a syscall. */
    492         if (t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_B &&
    493             t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_E) {
    494                 _thread_op_end(t);
     473        if ((thread->udebug.cur_event != UDEBUG_EVENT_SYSCALL_B) &&
     474            (thread->udebug.cur_event != UDEBUG_EVENT_SYSCALL_E)) {
     475                _thread_op_end(thread);
    495476                return EINVAL;
    496477        }
    497 
     478       
    498479        /* Copy to a local buffer before releasing the lock. */
    499         memcpy(arg_buffer, t->udebug.syscall_args, 6 * sizeof(unative_t));
    500 
    501         _thread_op_end(t);
    502 
     480        memcpy(arg_buffer, thread->udebug.syscall_args, 6 * sizeof(unative_t));
     481       
     482        _thread_op_end(thread);
     483       
    503484        *buffer = arg_buffer;
    504485        return 0;
     
    514495 * call (as opposed to an exception). This is an implementation limit.
    515496 *
    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  */
    522 int udebug_regs_read(thread_t *t, void **buffer)
    523 {
    524         istate_t *state, *state_buf;
    525         int rc;
    526 
     497 * @param thread Thread whose state is to be read.
     498 * @param buffer Place to store pointer to new buffer.
     499 *
     500 * @return EOK on success, ENOENT if @a t is invalid, EINVAL
     501 *         if thread is not in valid state, EBUSY if istate
     502 *         is not available.
     503 *
     504 */
     505int udebug_regs_read(thread_t *thread, void **buffer)
     506{
    527507        /* Prepare a buffer to hold the data. */
    528         state_buf = malloc(sizeof(istate_t), 0);
    529 
     508        istate_t *state_buf = malloc(sizeof(istate_t), 0);
     509       
    530510        /* On success, this will lock t->udebug.lock */
    531         rc = _thread_op_begin(t, false);
    532         if (rc != EOK) {
     511        int rc = _thread_op_begin(thread, false);
     512        if (rc != EOK)
    533513                return rc;
    534         }
    535 
    536         state = t->udebug.uspace_state;
     514       
     515        istate_t *state = thread->udebug.uspace_state;
    537516        if (state == NULL) {
    538                 _thread_op_end(t);
     517                _thread_op_end(thread);
    539518                return EBUSY;
    540519        }
    541 
     520       
    542521        /* Copy to the allocated buffer */
    543522        memcpy(state_buf, state, sizeof(istate_t));
    544 
    545         _thread_op_end(t);
    546 
     523       
     524        _thread_op_end(thread);
     525       
    547526        *buffer = (void *) state_buf;
    548527        return 0;
     
    555534 * and a pointer to it is written into @a buffer.
    556535 *
    557  * @param uspace_addr   Address from where to start reading.
    558  * @param n             Number of bytes to read.
    559  * @param buffer        For storing a pointer to the allocated buffer.
     536 * @param uspace_addr Address from where to start reading.
     537 * @param n           Number of bytes to read.
     538 * @param buffer      For storing a pointer to the allocated buffer.
     539 *
    560540 */
    561541int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer)
    562542{
    563         void *data_buffer;
    564         int rc;
    565 
    566543        /* Verify task state */
    567544        mutex_lock(&TASK->udebug.lock);
    568 
     545       
    569546        if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) {
    570547                mutex_unlock(&TASK->udebug.lock);
    571548                return EBUSY;
    572549        }
    573 
    574         data_buffer = malloc(n, 0);
    575 
    576         /* NOTE: this is not strictly from a syscall... but that shouldn't
    577          * be a problem */
    578         rc = copy_from_uspace(data_buffer, (void *)uspace_addr, n);
    579         mutex_unlock(&TASK->udebug.lock);
    580 
    581         if (rc != 0) return rc;
    582 
     550       
     551        void *data_buffer = malloc(n, 0);
     552       
     553        /*
     554         * NOTE: this is not strictly from a syscall... but that shouldn't
     555         * be a problem
     556         *
     557         */
     558        int rc = copy_from_uspace(data_buffer, (void *) uspace_addr, n);
     559        mutex_unlock(&TASK->udebug.lock);
     560       
     561        if (rc != 0)
     562                return rc;
     563       
    583564        *buffer = data_buffer;
    584565        return 0;
Note: See TracChangeset for help on using the changeset viewer.