Changeset 3b3e776 in mainline for kernel/generic/src


Ignore:
Timestamp:
2010-02-05T10:57:50Z (16 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0358da0
Parents:
3f085132 (diff), b4cbef1 (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:

merged with head

Location:
kernel/generic/src
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/console/kconsole.c

    r3f085132 r3b3e776  
    289289                       
    290290                        char tmp[STR_BOUNDS(MAX_CMDLINE)];
    291                         wstr_nstr(tmp, current + beg, position - beg + 1);
     291                        wstr_to_str(tmp, position - beg + 1, current + beg);
    292292                       
    293293                        int found;
     
    543543                if (str_lcmp(hlp->name, cmdline + start,
    544544                    max(str_length(hlp->name),
    545                     str_nlength(cmdline + start, (size_t) (end - start) - 1))) == 0) {
     545                    str_nlength(cmdline + start, (size_t) (end - start)))) == 0) {
    546546                        cmd = hlp;
    547547                        break;
     
    665665               
    666666                char cmdline[STR_BOUNDS(MAX_CMDLINE)];
    667                 wstr_nstr(cmdline, tmp, STR_BOUNDS(MAX_CMDLINE));
     667                wstr_to_str(cmdline, STR_BOUNDS(MAX_CMDLINE), tmp);
    668668               
    669669                if ((!kcon) && (len == 4) && (str_lcmp(cmdline, "exit", 4) == 0))
  • kernel/generic/src/ddi/irq.c

    r3f085132 r3b3e776  
    7474#include <synch/spinlock.h>
    7575#include <console/console.h>
     76#include <interrupt.h>
    7677#include <memstr.h>
    7778#include <arch.h>
     
    169170        irq->inr = -1;
    170171        irq->devno = -1;
     172
     173        irq_initialize_arch(irq);
    171174}
    172175
  • kernel/generic/src/debug/symtab.c

    r3f085132 r3b3e776  
    4646/** Get name of a symbol that seems most likely to correspond to address.
    4747 *
    48  * @param addr Address.
    49  * @param name Place to store pointer to the symbol name.
     48 * @param addr          Address.
     49 * @param name          Place to store pointer to the symbol name.
     50 * @param offset        Place to store offset from the symbol address.
    5051 *
    5152 * @return Zero on success or negative error code, ENOENT if not found,
     
    5354 *
    5455 */
    55 int symtab_name_lookup(unative_t addr, char **name)
     56int symtab_name_lookup(uintptr_t addr, char **name, uintptr_t *offset)
    5657{
    5758#ifdef CONFIG_SYMTAB
     
    6566        if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) {
    6667                *name = symbol_table[i - 1].symbol_name;
     68                if (offset)
     69                        *offset = addr -
     70                            uint64_t_le2host(symbol_table[i - 1].address_le);
    6771                return EOK;
    6872        }
     
    8892 *
    8993 */
    90 char *symtab_fmt_name_lookup(unative_t addr)
     94char *symtab_fmt_name_lookup(uintptr_t addr)
    9195{
    9296        char *name;
    93         int rc = symtab_name_lookup(addr, &name);
     97        int rc = symtab_name_lookup(addr, &name, NULL);
    9498       
    9599        switch (rc) {
  • kernel/generic/src/interrupt/interrupt.c

    r3f085132 r3b3e776  
    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        /*
     137         * Userspace can subscribe for FAULT events to take action
     138         * whenever a thread faults. (E.g. take a dump, run a debugger).
     139         * The notification is always available, but unless Udebug is enabled,
     140         * that's all you get.
     141         */
     142        if (event_is_subscribed(EVENT_FAULT)) {
     143                /* Notify the subscriber that a fault occurred. */
     144                event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
     145                    UPPER32(TASK->taskid), (unative_t) THREAD);
     146
     147#ifdef CONFIG_UDEBUG
     148                /* Wait for a debugging session. */
     149                udebug_thread_fault();
     150#endif
     151        }
     152
     153        task_kill(task->taskid);
     154        thread_exit();
    109155}
    110156
  • kernel/generic/src/ipc/ipc.c

    r3f085132 r3b3e776  
    6262
    6363static slab_cache_t *ipc_call_slab;
     64static slab_cache_t *ipc_answerbox_slab;
    6465
    6566/** Initialize a call structure.
     
    9697}
    9798
    98 /** Initialize a statically allocated call structure.
    99  *
    100  * @param call          Statically allocated kernel call structure to be
    101  *                      initialized.
    102  */
    103 void ipc_call_static_init(call_t *call)
    104 {
    105         _ipc_call_init(call);
    106         call->flags |= IPC_CALL_STATIC_ALLOC;
    107 }
    108 
    10999/** Deallocate a call structure.
    110100 *
     
    113103void ipc_call_free(call_t *call)
    114104{
    115         ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
    116105        /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
    117106        if (call->buffer)
     
    130119        spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
    131120        waitq_initialize(&box->wq);
     121        link_initialize(&box->sync_box_link);
    132122        list_initialize(&box->connected_phones);
    133123        list_initialize(&box->calls);
     
    179169int ipc_call_sync(phone_t *phone, call_t *request)
    180170{
    181         answerbox_t sync_box;
    182 
    183         ipc_answerbox_init(&sync_box, TASK);
     171        answerbox_t *sync_box;
     172        ipl_t ipl;
     173
     174        sync_box = slab_alloc(ipc_answerbox_slab, 0);
     175        ipc_answerbox_init(sync_box, TASK);
     176
     177        /*
     178         * Put the answerbox on the TASK's list of synchronous answerboxes so
     179         * that it can be cleaned up if the call is interrupted.
     180         */
     181        ipl = interrupts_disable();
     182        spinlock_lock(&TASK->lock);
     183        list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
     184        spinlock_unlock(&TASK->lock);
     185        interrupts_restore(ipl);
    184186
    185187        /* We will receive data in a special box. */
    186         request->callerbox = &sync_box;
     188        request->callerbox = sync_box;
    187189
    188190        ipc_call(phone, request);
    189         if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT,
    190             SYNCH_FLAGS_INTERRUPTIBLE))
     191        if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
     192            SYNCH_FLAGS_INTERRUPTIBLE)) {
     193                /* The answerbox and the call will be freed by ipc_cleanup(). */
    191194                return EINTR;
     195        }
     196
     197        /*
     198         * The answer arrived without interruption so we can remove the
     199         * answerbox from the TASK's list of synchronous answerboxes.
     200         */
     201        (void) interrupts_disable();
     202        spinlock_lock(&TASK->lock);
     203        list_remove(&sync_box->sync_box_link);
     204        spinlock_unlock(&TASK->lock);
     205        interrupts_restore(ipl);
     206
     207        slab_free(ipc_answerbox_slab, sync_box);
    192208        return EOK;
    193209}
     
    196212 *
    197213 * @param call          Call structure to be answered.
    198  */
    199 static void _ipc_answer_free_call(call_t *call)
     214 * @param selflocked    If true, then TASK->answebox is locked.
     215 */
     216static void _ipc_answer_free_call(call_t *call, bool selflocked)
    200217{
    201218        answerbox_t *callerbox = call->callerbox;
     219        bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));
    202220
    203221        call->flags |= IPC_CALL_ANSWERED;
     
    210228        }
    211229
    212         spinlock_lock(&callerbox->lock);
     230        if (do_lock)
     231                spinlock_lock(&callerbox->lock);
    213232        list_append(&call->link, &callerbox->answers);
    214         spinlock_unlock(&callerbox->lock);
     233        if (do_lock)
     234                spinlock_unlock(&callerbox->lock);
    215235        waitq_wakeup(&callerbox->wq, WAKEUP_FIRST);
    216236}
     
    228248        spinlock_unlock(&box->lock);
    229249        /* Send back answer */
    230         _ipc_answer_free_call(call);
     250        _ipc_answer_free_call(call, false);
    231251}
    232252
     
    245265        atomic_inc(&phone->active_calls);
    246266        IPC_SET_RETVAL(call->data, err);
    247         _ipc_answer_free_call(call);
     267        _ipc_answer_free_call(call, false);
    248268}
    249269
     
    284304                if (call->flags & IPC_CALL_FORWARDED) {
    285305                        IPC_SET_RETVAL(call->data, EFORWARD);
    286                         _ipc_answer_free_call(call);
     306                        _ipc_answer_free_call(call, false);
    287307                } else {
    288308                        if (phone->state == IPC_PHONE_HUNGUP)
     
    439459
    440460                IPC_SET_RETVAL(call->data, EHANGUP);
    441                 _ipc_answer_free_call(call);
     461                _ipc_answer_free_call(call, true);
    442462        }
    443463}
     
    520540        int i;
    521541        call_t *call;
     542        ipl_t ipl;
    522543
    523544        /* Disconnect all our phones ('ipc_phone_hangup') */
     
    545566        spinlock_unlock(&TASK->answerbox.lock);
    546567       
    547         /* Wait for all async answers to arrive */
     568        /* Wait for all answers to interrupted synchronous calls to arrive */
     569        ipl = interrupts_disable();
     570        while (!list_empty(&TASK->sync_box_head)) {
     571                answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
     572                    answerbox_t, sync_box_link);
     573
     574                list_remove(&box->sync_box_link);
     575                call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
     576                    SYNCH_FLAGS_NONE);
     577                ipc_call_free(call);
     578                slab_free(ipc_answerbox_slab, box);
     579        }
     580        interrupts_restore(ipl);
     581
     582        /* Wait for all answers to asynchronous calls to arrive */
    548583        while (1) {
    549584                /* Go through all phones, until all are FREE... */
     
    552587                for (i = 0; i < IPC_MAX_PHONES; i++) {
    553588                        if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
    554                             atomic_get(&TASK->phones[i].active_calls) == 0)
     589                            atomic_get(&TASK->phones[i].active_calls) == 0) {
    555590                                TASK->phones[i].state = IPC_PHONE_FREE;
     591                                TASK->phones[i].callee = NULL;
     592                        }
    556593                       
    557594                        /* Just for sure, we might have had some
     
    574611                ASSERT((call->flags & IPC_CALL_ANSWERED) ||
    575612                    (call->flags & IPC_CALL_NOTIF));
    576                 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
    577613               
    578614                /*
     
    593629        ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL,
    594630            NULL, 0);
     631        ipc_answerbox_slab = slab_cache_create("ipc_answerbox",
     632            sizeof(answerbox_t), 0, NULL, NULL, 0);
    595633}
    596634
  • kernel/generic/src/ipc/irq.c

    r3f085132 r3b3e776  
    423423                case CMD_ACCEPT:
    424424                        return IRQ_ACCEPT;
    425                         break;
    426425                case CMD_DECLINE:
    427426                default:
  • kernel/generic/src/ipc/sysipc.c

    r3f085132 r3b3e776  
    6161{ \
    6262        if (phoneid > IPC_MAX_PHONES) { \
    63                 err; \
     63                err \
    6464        } \
    6565        phone = &TASK->phones[phoneid]; \
     
    122122        case IPC_M_DATA_READ:
    123123                return 1;
    124                 break;
    125124        default:
    126125                return 0;
     
    376375                phone_t *cloned_phone;
    377376                GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
    378                     return ENOENT);
     377                    return ENOENT;);
    379378                phones_lock(cloned_phone, phone);
    380379                if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
     
    531530    unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
    532531{
    533         call_t call;
     532        call_t *call;
    534533        phone_t *phone;
    535534        int res;
    536535        int rc;
    537536       
    538         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    539 
    540         ipc_call_static_init(&call);
    541         IPC_SET_METHOD(call.data, method);
    542         IPC_SET_ARG1(call.data, arg1);
    543         IPC_SET_ARG2(call.data, arg2);
    544         IPC_SET_ARG3(call.data, arg3);
     537        GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     538
     539        call = ipc_call_alloc(0);
     540        IPC_SET_METHOD(call->data, method);
     541        IPC_SET_ARG1(call->data, arg1);
     542        IPC_SET_ARG2(call->data, arg2);
     543        IPC_SET_ARG3(call->data, arg3);
    545544        /*
    546545         * To achieve deterministic behavior, zero out arguments that are beyond
    547546         * the limits of the fast version.
    548547         */
    549         IPC_SET_ARG4(call.data, 0);
    550         IPC_SET_ARG5(call.data, 0);
    551 
    552         if (!(res = request_preprocess(&call, phone))) {
     548        IPC_SET_ARG4(call->data, 0);
     549        IPC_SET_ARG5(call->data, 0);
     550
     551        if (!(res = request_preprocess(call, phone))) {
    553552#ifdef CONFIG_UDEBUG
    554553                udebug_stoppable_begin();
    555554#endif
    556                 rc = ipc_call_sync(phone, &call);
     555                rc = ipc_call_sync(phone, call);
    557556#ifdef CONFIG_UDEBUG
    558557                udebug_stoppable_end();
    559558#endif
    560                 if (rc != EOK)
     559                if (rc != EOK) {
     560                        /* The call will be freed by ipc_cleanup(). */
    561561                        return rc;
    562                 process_answer(&call);
     562                }
     563                process_answer(call);
    563564
    564565        } else {
    565                 IPC_SET_RETVAL(call.data, res);
    566         }
    567         rc = STRUCT_TO_USPACE(&data->args, &call.data.args);
     566                IPC_SET_RETVAL(call->data, res);
     567        }
     568        rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
     569        ipc_call_free(call);
    568570        if (rc != 0)
    569571                return rc;
     
    584586    ipc_data_t *reply)
    585587{
    586         call_t call;
     588        call_t *call;
    587589        phone_t *phone;
    588590        int res;
    589591        int rc;
    590592
    591         ipc_call_static_init(&call);
    592         rc = copy_from_uspace(&call.data.args, &question->args,
    593             sizeof(call.data.args));
    594         if (rc != 0)
     593        GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
     594
     595        call = ipc_call_alloc(0);
     596        rc = copy_from_uspace(&call->data.args, &question->args,
     597            sizeof(call->data.args));
     598        if (rc != 0) {
     599                ipc_call_free(call);
    595600                return (unative_t) rc;
    596 
    597         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    598 
    599         if (!(res = request_preprocess(&call, phone))) {
     601        }
     602
     603
     604        if (!(res = request_preprocess(call, phone))) {
    600605#ifdef CONFIG_UDEBUG
    601606                udebug_stoppable_begin();
    602607#endif
    603                 rc = ipc_call_sync(phone, &call);
     608                rc = ipc_call_sync(phone, call);
    604609#ifdef CONFIG_UDEBUG
    605610                udebug_stoppable_end();
    606611#endif
    607                 if (rc != EOK)
     612                if (rc != EOK) {
     613                        /* The call will be freed by ipc_cleanup(). */
    608614                        return rc;
    609                 process_answer(&call);
     615                }
     616                process_answer(call);
    610617        } else
    611                 IPC_SET_RETVAL(call.data, res);
    612 
    613         rc = STRUCT_TO_USPACE(&reply->args, &call.data.args);
     618                IPC_SET_RETVAL(call->data, res);
     619
     620        rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
     621        ipc_call_free(call);
    614622        if (rc != 0)
    615623                return rc;
     
    658666                return IPC_CALLRET_TEMPORARY;
    659667
    660         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
     668        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
    661669
    662670        call = ipc_call_alloc(0);
     
    697705                return IPC_CALLRET_TEMPORARY;
    698706
    699         GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
     707        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
    700708
    701709        call = ipc_call_alloc(0);
     
    747755        call->flags |= IPC_CALL_FORWARDED;
    748756
    749         GET_CHECK_PHONE(phone, phoneid, { 
     757        GET_CHECK_PHONE(phone, phoneid, {
    750758                IPC_SET_RETVAL(call->data, EFORWARD);
    751759                ipc_answer(&TASK->answerbox, call);
     
    952960        phone_t *phone;
    953961
    954         GET_CHECK_PHONE(phone, phoneid, return ENOENT);
     962        GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
    955963
    956964        if (ipc_phone_hangup(phone))
     
    991999
    9921000        if (call->flags & IPC_CALL_NOTIF) {
    993                 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
    994 
    9951001                /* Set in_phone_hash to the interrupt counter */
    9961002                call->data.phone = (void *) call->priv;
     
    10051011        if (call->flags & IPC_CALL_ANSWERED) {
    10061012                process_answer(call);
    1007 
    1008                 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
    10091013
    10101014                if (call->flags & IPC_CALL_DISCARD_ANSWER) {
  • kernel/generic/src/lib/elf.c

    r3f085132 r3b3e776  
    163163        case PT_LOAD:
    164164                return load_segment(entry, elf, as);
    165                 break;
    166165        case PT_DYNAMIC:
    167166        case PT_INTERP:
     
    182181        default:
    183182                return EE_UNSUPPORTED;
    184                 break;
    185183        }
    186184        return EE_OK;
  • kernel/generic/src/lib/string.c

    r3f085132 r3b3e776  
    537537 * null-terminated and containing only complete characters.
    538538 *
    539  * @param dst   Destination buffer.
     539 * @param dest   Destination buffer.
    540540 * @param count Size of the destination buffer (must be > 0).
    541541 * @param src   Source string.
     
    571571 * have to be null-terminated.
    572572 *
    573  * @param dst   Destination buffer.
     573 * @param dest   Destination buffer.
    574574 * @param count Size of the destination buffer (must be > 0).
    575575 * @param src   Source string.
     
    596596}
    597597
    598 /** Copy NULL-terminated wide string to string
    599  *
    600  * Copy source wide string @a src to destination buffer @a dst.
    601  * No more than @a size bytes are written. NULL-terminator is always
    602  * written after the last succesfully copied character (i.e. if the
    603  * destination buffer is has at least 1 byte, it will be always
    604  * NULL-terminated).
    605  *
    606  * @param src   Source wide string.
    607  * @param dst   Destination buffer.
    608  * @param count Size of the destination buffer.
    609  *
    610  */
    611 void wstr_nstr(char *dst, const wchar_t *src, size_t size)
    612 {
    613         /* No space for the NULL-terminator in the buffer */
    614         if (size == 0)
    615                 return;
    616        
     598/** Convert wide string to string.
     599 *
     600 * Convert wide string @a src to string. The output is written to the buffer
     601 * specified by @a dest and @a size. @a size must be non-zero and the string
     602 * written will always be well-formed.
     603 *
     604 * @param dest  Destination buffer.
     605 * @param size  Size of the destination buffer.
     606 * @param src   Source wide string.
     607 */
     608void wstr_to_str(char *dest, size_t size, const wchar_t *src)
     609{
    617610        wchar_t ch;
    618         size_t src_idx = 0;
    619         size_t dst_off = 0;
     611        size_t src_idx;
     612        size_t dest_off;
     613
     614        /* There must be space for a null terminator in the buffer. */
     615        ASSERT(size > 0);
     616
     617        src_idx = 0;
     618        dest_off = 0;
    620619       
    621620        while ((ch = src[src_idx++]) != 0) {
    622                 if (chr_encode(ch, dst, &dst_off, size) != EOK)
     621                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    623622                        break;
    624623        }
    625        
    626         if (dst_off >= size)
    627                 dst[size - 1] = 0;
    628         else
    629                 dst[dst_off] = 0;
     624
     625        dest[dest_off] = '\0';
    630626}
    631627
  • kernel/generic/src/mm/as.c

    r3f085132 r3b3e776  
    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/mm/backend_phys.c

    r3f085132 r3b3e776  
    4040#include <arch/types.h>
    4141#include <mm/as.h>
     42#include <mm/page.h>
    4243#include <mm/frame.h>
    4344#include <mm/slab.h>
  • kernel/generic/src/proc/task.c

    r3f085132 r3b3e776  
    5454#include <func.h>
    5555#include <string.h>
     56#include <memstr.h>
    5657#include <syscall/copy.h>
    5758#include <macros.h>
     
    7576static task_id_t task_counter = 0;
    7677
     78static slab_cache_t *task_slab;
     79
    7780/* Forward declarations. */
    7881static void task_kill_internal(task_t *);
     82static int tsk_constructor(void *, int);
    7983
    8084/** Initialize kernel tasks support. */
     
    8387        TASK = NULL;
    8488        avltree_create(&tasks_tree);
     89        task_slab = slab_cache_create("task_slab", sizeof(task_t), 0,
     90            tsk_constructor, NULL, 0);
    8591}
    8692
     
    128134}
    129135
     136int tsk_constructor(void *obj, int kmflags)
     137{
     138        task_t *ta = obj;
     139        int i;
     140
     141        atomic_set(&ta->refcount, 0);
     142        atomic_set(&ta->lifecount, 0);
     143        atomic_set(&ta->active_calls, 0);
     144
     145        spinlock_initialize(&ta->lock, "task_ta_lock");
     146        mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
     147
     148        list_initialize(&ta->th_head);
     149        list_initialize(&ta->sync_box_head);
     150
     151        ipc_answerbox_init(&ta->answerbox, ta);
     152        for (i = 0; i < IPC_MAX_PHONES; i++)
     153                ipc_phone_init(&ta->phones[i]);
     154
     155#ifdef CONFIG_UDEBUG
     156        /* Init kbox stuff */
     157        ta->kb.thread = NULL;
     158        ipc_answerbox_init(&ta->kb.box, ta);
     159        mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
     160#endif
     161
     162        return 0;
     163}
     164
    130165/** Create new task with no threads.
    131166 *
     
    140175        ipl_t ipl;
    141176        task_t *ta;
    142         int i;
    143        
    144         ta = (task_t *) malloc(sizeof(task_t), 0);
    145 
     177       
     178        ta = (task_t *) slab_alloc(task_slab, 0);
    146179        task_create_arch(ta);
    147 
    148         spinlock_initialize(&ta->lock, "task_ta_lock");
    149         list_initialize(&ta->th_head);
    150180        ta->as = as;
    151 
    152181        memcpy(ta->name, name, TASK_NAME_BUFLEN);
    153182        ta->name[TASK_NAME_BUFLEN - 1] = 0;
    154183
    155         atomic_set(&ta->refcount, 0);
    156         atomic_set(&ta->lifecount, 0);
    157184        ta->context = CONTEXT;
    158 
    159185        ta->capabilities = 0;
    160186        ta->cycles = 0;
     
    165191
    166192        /* Init kbox stuff */
    167         ipc_answerbox_init(&ta->kb.box, ta);
    168         ta->kb.thread = NULL;
    169         mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
    170193        ta->kb.finished = false;
    171194#endif
    172195
    173         ipc_answerbox_init(&ta->answerbox, ta);
    174         for (i = 0; i < IPC_MAX_PHONES; i++)
    175                 ipc_phone_init(&ta->phones[i]);
    176         if ((ipc_phone_0) && (context_check(ipc_phone_0->task->context,
    177             ta->context)))
     196        if ((ipc_phone_0) &&
     197            (context_check(ipc_phone_0->task->context, ta->context)))
    178198                ipc_phone_connect(&ta->phones[0], ipc_phone_0);
    179         atomic_set(&ta->active_calls, 0);
    180 
    181         mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
     199
    182200        btree_create(&ta->futexes);
    183201       
    184202        ipl = interrupts_disable();
    185 
    186         /*
    187          * Increment address space reference count.
    188          */
    189203        atomic_inc(&as->refcount);
    190 
    191204        spinlock_lock(&tasks_lock);
    192205        ta->taskid = ++task_counter;
     
    229242                as_destroy(t->as);
    230243       
    231         free(t);
     244        slab_free(task_slab, t);
    232245        TASK = NULL;
    233246}
  • kernel/generic/src/proc/thread.c

    r3f085132 r3b3e776  
    501501void thread_sleep(uint32_t sec)
    502502{
    503         thread_usleep(sec * 1000000);
     503        /* Sleep in 1000 second steps to support
     504           full argument range */
     505        while (sec > 0) {
     506                uint32_t period = (sec > 1000) ? 1000 : sec;
     507       
     508                thread_usleep(period * 1000000);
     509                sec -= period;
     510        }
    504511}
    505512
     
    575582{
    576583        waitq_t wq;
    577                                  
     584       
    578585        waitq_initialize(&wq);
    579 
     586       
    580587        (void) waitq_sleep_timeout(&wq, usec, SYNCH_FLAGS_NON_BLOCKING);
    581588}
     
    812819}
    813820
     821/** Syscall wrapper for sleeping. */
     822unative_t sys_thread_usleep(uint32_t usec)
     823{
     824        thread_usleep(usec);
     825        return 0;
     826}
     827
    814828/** @}
    815829 */
  • kernel/generic/src/synch/futex.c

    r3f085132 r3b3e776  
    9090/** Initialize kernel futex structure.
    9191 *
    92  * @param futex Kernel futex structure.
     92 * @param futex         Kernel futex structure.
    9393 */
    9494void futex_initialize(futex_t *futex)
     
    102102/** Sleep in futex wait queue.
    103103 *
    104  * @param uaddr Userspace address of the futex counter.
    105  * @param usec If non-zero, number of microseconds this thread is willing to
    106  *     sleep.
    107  * @param flags Select mode of operation.
    108  *
    109  * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See
    110  *     synch.h. If there is no physical mapping for uaddr ENOENT is returned.
    111  */
    112 unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec, int flags)
     104 * @param uaddr         Userspace address of the futex counter.
     105 *
     106 * @return              If there is no physical mapping for uaddr ENOENT is
     107 *                      returned. Otherwise returns a wait result as defined in
     108 *                      synch.h.
     109 */
     110unative_t sys_futex_sleep(uintptr_t uaddr)
    113111{
    114112        futex_t *futex;
     
    140138        udebug_stoppable_begin();
    141139#endif
    142         rc = waitq_sleep_timeout(&futex->wq, usec, flags |
    143             SYNCH_FLAGS_INTERRUPTIBLE);
    144 
     140        rc = waitq_sleep_timeout(&futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE);
    145141#ifdef CONFIG_UDEBUG
    146142        udebug_stoppable_end();
     
    151147/** Wakeup one thread waiting in futex wait queue.
    152148 *
    153  * @param uaddr Userspace address of the futex counter.
    154  *
    155  * @return ENOENT if there is no physical mapping for uaddr.
     149 * @param uaddr         Userspace address of the futex counter.
     150 *
     151 * @return              ENOENT if there is no physical mapping for uaddr.
    156152 */
    157153unative_t sys_futex_wakeup(uintptr_t uaddr)
     
    190186 * If the structure does not exist already, a new one is created.
    191187 *
    192  * @param paddr Physical address of the userspace futex counter.
    193  *
    194  * @return Address of the kernel futex structure.
     188 * @param paddr         Physical address of the userspace futex counter.
     189 *
     190 * @return              Address of the kernel futex structure.
    195191 */
    196192futex_t *futex_find(uintptr_t paddr)
     
    284280/** Compute hash index into futex hash table.
    285281 *
    286  * @param key Address where the key (i.e. physical address of futex counter) is
    287  *    stored.
    288  *
    289  * @return Index into futex hash table.
     282 * @param key           Address where the key (i.e. physical address of futex
     283 *                      counter) is stored.
     284 *
     285 * @return              Index into futex hash table.
    290286 */
    291287size_t futex_ht_hash(unative_t *key)
     
    296292/** Compare futex hash table item with a key.
    297293 *
    298  * @param key Address where the key (i.e. physical address of futex counter) is
    299  *    stored.
    300  *
    301  * @return True if the item matches the key. False otherwise.
     294 * @param key           Address where the key (i.e. physical address of futex
     295 *                      counter) is stored.
     296 *
     297 * @return              True if the item matches the key. False otherwise.
    302298 */
    303299bool futex_ht_compare(unative_t *key, size_t keys, link_t *item)
     
    313309/** Callback for removal items from futex hash table.
    314310 *
    315  * @param item Item removed from the hash table.
     311 * @param item          Item removed from the hash table.
    316312 */
    317313void futex_ht_remove_callback(link_t *item)
  • kernel/generic/src/syscall/syscall.c

    r3f085132 r3b3e776  
    6262
    6363#ifdef CONFIG_UDEBUG
    64         bool debug;
    65 
    6664        /*
    6765         * Early check for undebugged tasks. We do not lock anything as this
    68          * test need not be precise in either way.
     66         * test need not be precise in either direction.
    6967         */
    70         debug = THREAD->udebug.active;
    71        
    72         if (debug) {
     68        if (THREAD->udebug.active) {
    7369                udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, 0, false);
    7470        }
     
    8783       
    8884#ifdef CONFIG_UDEBUG
    89         if (debug) {
     85        if (THREAD->udebug.active) {
    9086                udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc, true);
    9187       
     
    111107        (syshandler_t) sys_thread_exit,
    112108        (syshandler_t) sys_thread_get_id,
     109        (syshandler_t) sys_thread_usleep,
    113110       
    114111        (syshandler_t) sys_task_get_id,
     
    117114       
    118115        /* Synchronization related syscalls. */
    119         (syshandler_t) sys_futex_sleep_timeout,
     116        (syshandler_t) sys_futex_sleep,
    120117        (syshandler_t) sys_futex_wakeup,
    121118        (syshandler_t) sys_smc_coherence,
  • kernel/generic/src/udebug/udebug.c

    r3f085132 r3b3e776  
    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

    r3f085132 r3b3e776  
    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

    r3f085132 r3b3e776  
    4646#include <errno.h>
    4747#include <print.h>
     48#include <string.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/**
     
    208210
    209211                mutex_lock(&t->udebug.lock);
    210                 if ((t->flags & THREAD_FLAG_USPACE) != 0)
     212                if ((t->flags & THREAD_FLAG_USPACE) != 0) {
    211213                        t->udebug.active = true;
    212                 mutex_unlock(&t->udebug.lock);
     214                        mutex_unlock(&t->udebug.lock);
     215                        condvar_broadcast(&t->udebug.active_cv);
     216                } else {
     217                        mutex_unlock(&t->udebug.lock);
     218                }
    213219        }
    214220
     
    354360 *
    355361 * 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.
     362 * as can fit are copied. The number of bytes copied is stored in @a stored.
     363 * The total number of thread bytes that could have been saved had there been
     364 * enough space is stored in @a needed.
    358365 *
    359366 * The rationale for having @a buf_size is that this function is only
     
    363370 * @param buffer        The buffer for storing thread hashes.
    364371 * @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)
     372 * @param stored        The actual number of bytes copied will be stored here.
     373 * @param needed        Total number of hashes that could have been saved.
     374 */
     375int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored,
     376    size_t *needed)
    368377{
    369378        thread_t *t;
    370379        link_t *cur;
    371380        unative_t tid;
    372         unsigned copied_ids;
     381        size_t copied_ids;
     382        size_t extra_ids;
    373383        ipl_t ipl;
    374384        unative_t *id_buffer;
     
    379389
    380390        /* Allocate a buffer to hold thread IDs */
    381         id_buffer = malloc(buf_size, 0);
     391        id_buffer = malloc(buf_size + 1, 0);
    382392
    383393        mutex_lock(&TASK->udebug.lock);
     
    395405        max_ids = buf_size / sizeof(unative_t);
    396406        copied_ids = 0;
     407        extra_ids = 0;
    397408
    398409        /* FIXME: make sure the thread isn't past debug shutdown... */
    399410        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 
    403411                t = list_get_instance(cur, thread_t, th_link);
    404412
     
    408416
    409417                /* Not interested in kernel threads. */
    410                 if ((flags & THREAD_FLAG_USPACE) != 0) {
     418                if ((flags & THREAD_FLAG_USPACE) == 0)
     419                        continue;
     420
     421                if (copied_ids < max_ids) {
    411422                        /* Using thread struct pointer as identification hash */
    412423                        tid = (unative_t) t;
    413424                        id_buffer[copied_ids++] = tid;
     425                } else {
     426                        extra_ids++;
    414427                }
    415428        }
     
    421434
    422435        *buffer = id_buffer;
    423         *n = copied_ids * sizeof(unative_t);
     436        *stored = copied_ids * sizeof(unative_t);
     437        *needed = (copied_ids + extra_ids) * sizeof(unative_t);
     438
     439        return 0;
     440}
     441
     442/** Read task name.
     443 *
     444 * Returns task name as non-terminated string in a newly allocated buffer.
     445 * Also returns the size of the data.
     446 *
     447 * @param data          Place to store pointer to newly allocated block.
     448 * @param data_size     Place to store size of the data.
     449 *
     450 * @returns             EOK.
     451 */
     452int udebug_name_read(char **data, size_t *data_size)
     453{
     454        size_t name_size;
     455
     456        name_size = str_size(TASK->name) + 1;
     457        *data = malloc(name_size, 0);
     458        *data_size = name_size;
     459
     460        memcpy(*data, TASK->name, name_size);
    424461
    425462        return 0;
     
    436473 * this function will fail with an EINVAL error code.
    437474 *
    438  * @param buffer        The buffer for storing thread hashes.
     475 * @param t             Thread where call arguments are to be read.
     476 * @param buffer        Place to store pointer to new buffer.
     477 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     478 *                      if thread state is not valid for this operation.
    439479 */
    440480int udebug_args_read(thread_t *t, void **buffer)
     
    468508}
    469509
     510/** Read the register state of the thread.
     511 *
     512 * The contents of the thread's istate structure are copied to a newly
     513 * allocated buffer and a pointer to it is written to @a buffer. The size of
     514 * the buffer will be sizeof(istate_t).
     515 *
     516 * Currently register state cannot be read if the thread is inside a system
     517 * call (as opposed to an exception). This is an implementation limit.
     518 *
     519 * @param t             Thread whose state is to be read.
     520 * @param buffer        Place to store pointer to new buffer.
     521 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     522 *                      if thread is not in valid state, EBUSY if istate
     523 *                      is not available.
     524 */
     525int udebug_regs_read(thread_t *t, void **buffer)
     526{
     527        istate_t *state, *state_buf;
     528        int rc;
     529
     530        /* Prepare a buffer to hold the data. */
     531        state_buf = malloc(sizeof(istate_t), 0);
     532
     533        /* On success, this will lock t->udebug.lock */
     534        rc = _thread_op_begin(t, false);
     535        if (rc != EOK) {
     536                return rc;
     537        }
     538
     539        state = t->udebug.uspace_state;
     540        if (state == NULL) {
     541                _thread_op_end(t);
     542                return EBUSY;
     543        }
     544
     545        /* Copy to the allocated buffer */
     546        memcpy(state_buf, state, sizeof(istate_t));
     547
     548        _thread_op_end(t);
     549
     550        *buffer = (void *) state_buf;
     551        return 0;
     552}
     553
    470554/** Read the memory of the debugged task.
    471555 *
Note: See TracChangeset for help on using the changeset viewer.