Changes in / [ef7052ec:42a619b] in mainline


Ignore:
Files:
38 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    ref7052ec r42a619b  
    5454
    5555cscope:
    56         find kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
     56        find abi kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
    5757
    5858# Pre-integration build check
  • abi/include/ipc/event.h

    ref7052ec r42a619b  
    4646} event_type_t;
    4747
     48/** Per-task events. */
     49typedef enum event_task_type {
     50        EVENT_TASK_STATE_CHANGE = EVENT_END,
     51        EVENT_TASK_END
     52} event_task_type_t;
     53
    4854#endif
    4955
  • abi/include/ipc/methods.h

    ref7052ec r42a619b  
    171171#define IPC_M_DATA_READ  8
    172172
     173/** Authorize change of recipient's state in a third party task.
     174 * - ARG1 - user protocol defined data
     175 * - ARG2 - user protocol defined data
     176 * - ARG3 - user protocol defined data
     177 * - ARG5 - sender's phone to the third party task
     178 *
     179 * on EOK answer, the recipient must set:
     180 *
     181 * - ARG1 - recipient's phone to the third party task
     182 */
     183#define IPC_M_STATE_CHANGE_AUTHORIZE    9
     184
    173185/** Debug the recipient.
    174186 * - ARG1 - specifies the debug method (from udebug_method_t)
     
    176188 *
    177189 */
    178 #define IPC_M_DEBUG  9
     190#define IPC_M_DEBUG 10
    179191
    180192/** Last system IPC method */
  • kernel/generic/include/console/console.h

    ref7052ec r42a619b  
    6363
    6464extern void klog_init(void);
    65 extern void klog_update(void);
     65extern void klog_update(void *);
    6666
    6767extern wchar_t getc(indev_t *indev);
  • kernel/generic/include/ipc/event.h

    ref7052ec r42a619b  
    4141#include <ipc/ipc.h>
    4242
    43 typedef void (*event_callback_t)(void);
     43typedef struct task task_t;
     44
     45typedef void (*event_callback_t)(void *);
    4446
    4547/** Event notification structure. */
     
    6163
    6264extern void event_init(void);
     65extern void event_task_init(task_t *);
    6366extern void event_cleanup_answerbox(answerbox_t *);
    6467extern void event_set_unmask_callback(event_type_t, event_callback_t);
     68extern void event_task_set_unmask_callback(task_t *, event_task_type_t,
     69    event_callback_t);
    6570
    6671#define event_notify_0(e, m) \
     
    7782        event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
    7883
     84#define event_task_notify_0(t, e, m) \
     85        event_task_notify((t), (e), (m), 0, 0, 0, 0, 0)
     86#define event_task_notify_1(t, e, m, a1) \
     87        event_task_notify((t), (e), (m), (a1), 0, 0, 0, 0)
     88#define event_task_notify_2(t, e, m, a1, a2) \
     89        event_task_notify((t), (e), (m), (a1), (a2), 0, 0, 0)
     90#define event_task_notify_3(t, e, m, a1, a2, a3) \
     91        event_task_notify((t), (e), (m), (a1), (a2), (a3), 0, 0)
     92#define event_task_notify_4(t, e, m, a1, a2, a3, a4) \
     93        event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), 0)
     94#define event_task_notify_5(t, e, m, a1, a2, a3, a4, a5) \
     95        event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), (a5))
     96
    7997extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
    8098    sysarg_t, sysarg_t);
     99extern int event_task_notify(task_t *, event_task_type_t, bool, sysarg_t, sysarg_t,
     100    sysarg_t, sysarg_t, sysarg_t);
    81101
    82102extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
  • kernel/generic/include/proc/task.h

    ref7052ec r42a619b  
    3838#include <cpu.h>
    3939#include <ipc/ipc.h>
     40#include <ipc/event.h>
     41#include <ipc/kbox.h>
    4042#include <synch/spinlock.h>
    4143#include <synch/mutex.h>
     
    5355#include <proc/scheduler.h>
    5456#include <udebug/udebug.h>
    55 #include <ipc/kbox.h>
    5657#include <mm/as.h>
    5758#include <abi/sysinfo.h>
     
    9394        phone_t phones[IPC_MAX_PHONES];
    9495        stats_ipc_t ipc_info;   /**< IPC statistics */
    95         /** List of synchronous answerboxes. */
    96         list_t sync_boxes;
     96        list_t sync_boxes;      /**< List of synchronous answerboxes. */
     97        event_t events[EVENT_TASK_END - EVENT_END];
    9798       
    9899#ifdef CONFIG_UDEBUG
  • kernel/generic/src/console/console.c

    ref7052ec r42a619b  
    248248}
    249249
    250 void klog_update(void)
     250void klog_update(void *e)
    251251{
    252252        if (!atomic_get(&klog_inited))
     
    327327        /* Force notification on newline */
    328328        if (ch == '\n')
    329                 klog_update();
     329                klog_update(NULL);
    330330}
    331331
     
    358358                free(data);
    359359        } else
    360                 klog_update();
     360                klog_update(NULL);
    361361       
    362362        return size;
  • kernel/generic/src/ipc/event.c

    ref7052ec r42a619b  
    4040#include <synch/spinlock.h>
    4141#include <console/console.h>
     42#include <proc/task.h>
    4243#include <memstr.h>
    4344#include <errno.h>
     
    4748static event_t events[EVENT_END];
    4849
     50static void event_initialize(event_t *event)
     51{
     52        spinlock_initialize(&event->lock, "event.lock");
     53        event->answerbox = NULL;
     54        event->counter = 0;
     55        event->imethod = 0;
     56        event->masked = false;
     57        event->unmask_callback = NULL;
     58}
     59
     60static event_t *evno2event(int evno, task_t *t)
     61{
     62        ASSERT(evno < EVENT_TASK_END);
     63
     64        event_t *event;
     65
     66        if (evno < EVENT_END)
     67                event = &events[(event_type_t) evno];
     68        else
     69                event = &t->events[(event_task_type_t) evno - EVENT_END];
     70
     71        return event;
     72}
     73
    4974/** Initialize kernel events.
    5075 *
     
    5277void event_init(void)
    5378{
    54         for (unsigned int i = 0; i < EVENT_END; i++) {
    55                 spinlock_initialize(&events[i].lock, "event.lock");
    56                 events[i].answerbox = NULL;
    57                 events[i].counter = 0;
    58                 events[i].imethod = 0;
    59                 events[i].masked = false;
    60                 events[i].unmask_callback = NULL;
    61         }
    62 }
     79        for (unsigned int i = 0; i < EVENT_END; i++)
     80                event_initialize(evno2event(i, NULL));
     81}
     82
     83void event_task_init(task_t *t)
     84{
     85        for (unsigned int i = EVENT_END; i < EVENT_TASK_END; i++)
     86                event_initialize(evno2event(i, t));
     87}
     88
    6389
    6490/** Unsubscribe kernel events associated with an answerbox
     
    83109}
    84110
     111static void _event_set_unmask_callback(event_t *event, event_callback_t callback)
     112{
     113        spinlock_lock(&event->lock);
     114        event->unmask_callback = callback;
     115        spinlock_unlock(&event->lock);
     116}
     117
    85118/** Define a callback function for the event unmask event.
    86119 *
     
    94127        ASSERT(evno < EVENT_END);
    95128       
    96         spinlock_lock(&events[evno].lock);
    97         events[evno].unmask_callback = callback;
    98         spinlock_unlock(&events[evno].lock);
     129        _event_set_unmask_callback(evno2event(evno, NULL), callback);
     130}
     131
     132void event_task_set_unmask_callback(task_t *t, event_task_type_t evno,
     133    event_callback_t callback)
     134{
     135        ASSERT(evno >= (int) EVENT_END);
     136        ASSERT(evno < EVENT_TASK_END);
     137               
     138        _event_set_unmask_callback(evno2event(evno, t), callback);
     139}
     140
     141static int event_enqueue(event_t *event, bool mask, sysarg_t a1, sysarg_t a2,
     142    sysarg_t a3, sysarg_t a4, sysarg_t a5)
     143{
     144        int res;
     145
     146        spinlock_lock(&event->lock);
     147       
     148        if (event->answerbox != NULL) {
     149                if (!event->masked) {
     150                        call_t *call = ipc_call_alloc(FRAME_ATOMIC);
     151                       
     152                        if (call) {
     153                                call->flags |= IPC_CALL_NOTIF;
     154                                call->priv = ++event->counter;
     155                               
     156                                IPC_SET_IMETHOD(call->data, event->imethod);
     157                                IPC_SET_ARG1(call->data, a1);
     158                                IPC_SET_ARG2(call->data, a2);
     159                                IPC_SET_ARG3(call->data, a3);
     160                                IPC_SET_ARG4(call->data, a4);
     161                                IPC_SET_ARG5(call->data, a5);
     162                               
     163                                irq_spinlock_lock(&event->answerbox->irq_lock, true);
     164                                list_append(&call->link, &event->answerbox->irq_notifs);
     165                                irq_spinlock_unlock(&event->answerbox->irq_lock, true);
     166                               
     167                                waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST);
     168                               
     169                                if (mask)
     170                                        event->masked = true;
     171                               
     172                                res = EOK;
     173                        } else
     174                                res = ENOMEM;
     175                } else
     176                        res = EBUSY;
     177        } else
     178                res = ENOENT;
     179       
     180        spinlock_unlock(&event->lock);
     181        return res;
    99182}
    100183
     
    123206        ASSERT(evno < EVENT_END);
    124207       
    125         spinlock_lock(&events[evno].lock);
    126        
    127         int ret;
    128        
    129         if (events[evno].answerbox != NULL) {
    130                 if (!events[evno].masked) {
    131                         call_t *call = ipc_call_alloc(FRAME_ATOMIC);
    132                        
    133                         if (call) {
    134                                 call->flags |= IPC_CALL_NOTIF;
    135                                 call->priv = ++events[evno].counter;
    136                                
    137                                 IPC_SET_IMETHOD(call->data, events[evno].imethod);
    138                                 IPC_SET_ARG1(call->data, a1);
    139                                 IPC_SET_ARG2(call->data, a2);
    140                                 IPC_SET_ARG3(call->data, a3);
    141                                 IPC_SET_ARG4(call->data, a4);
    142                                 IPC_SET_ARG5(call->data, a5);
    143                                
    144                                 irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
    145                                 list_append(&call->link, &events[evno].answerbox->irq_notifs);
    146                                 irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
    147                                
    148                                 waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
    149                                
    150                                 if (mask)
    151                                         events[evno].masked = true;
    152                                
    153                                 ret = EOK;
    154                         } else
    155                                 ret = ENOMEM;
    156                 } else
    157                         ret = EBUSY;
    158         } else
    159                 ret = ENOENT;
    160        
    161         spinlock_unlock(&events[evno].lock);
    162        
    163         return ret;
     208        return event_enqueue(evno2event(evno, NULL), mask, a1, a2, a3, a4, a5);
     209}
     210
     211/** Send per-task kernel notification event
     212 *
     213 * @param t    Destination task.
     214 * @param evno Event type.
     215 * @param mask Mask further notifications after a successful
     216 *             sending.
     217 * @param a1   First argument.
     218 * @param a2   Second argument.
     219 * @param a3   Third argument.
     220 * @param a4   Fourth argument.
     221 * @param a5   Fifth argument.
     222 *
     223 * @return EOK if notification was successfully sent.
     224 * @return ENOMEM if the notification IPC message failed to allocate.
     225 * @return EBUSY if the notifications of the given type are
     226 *         currently masked.
     227 * @return ENOENT if the notifications of the given type are
     228 *         currently not subscribed.
     229 *
     230 */
     231int event_task_notify(task_t *t, event_task_type_t evno, bool mask, sysarg_t a1,
     232    sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5)
     233{
     234        ASSERT(evno >= (int) EVENT_END);
     235        ASSERT(evno < EVENT_TASK_END);
     236       
     237        return event_enqueue(evno2event(evno, t), mask, a1, a2, a3, a4, a5);
    164238}
    165239
     
    176250 *
    177251 */
    178 static int event_subscribe(event_type_t evno, sysarg_t imethod,
     252static int event_subscribe(event_t *event, sysarg_t imethod,
    179253    answerbox_t *answerbox)
    180254{
    181         ASSERT(evno < EVENT_END);
    182        
    183         spinlock_lock(&events[evno].lock);
    184        
    185255        int res;
    186        
    187         if (events[evno].answerbox == NULL) {
    188                 events[evno].answerbox = answerbox;
    189                 events[evno].imethod = imethod;
    190                 events[evno].counter = 0;
    191                 events[evno].masked = false;
     256
     257        spinlock_lock(&event->lock);
     258       
     259        if (event->answerbox == NULL) {
     260                event->answerbox = answerbox;
     261                event->imethod = imethod;
     262                event->counter = 0;
     263                event->masked = false;
    192264                res = EOK;
    193265        } else
    194266                res = EEXISTS;
    195267       
    196         spinlock_unlock(&events[evno].lock);
     268        spinlock_unlock(&event->lock);
    197269       
    198270        return res;
     
    204276 *
    205277 */
    206 static void event_unmask(event_type_t evno)
    207 {
    208         ASSERT(evno < EVENT_END);
    209        
    210         spinlock_lock(&events[evno].lock);
    211         events[evno].masked = false;
    212         event_callback_t callback = events[evno].unmask_callback;
    213         spinlock_unlock(&events[evno].lock);
     278static void event_unmask(event_t *event)
     279{
     280        spinlock_lock(&event->lock);
     281        event->masked = false;
     282        event_callback_t callback = event->unmask_callback;
     283        spinlock_unlock(&event->lock);
    214284       
    215285        /*
     
    218288         */
    219289        if (callback != NULL)
    220                 callback();
     290                callback(event);
    221291}
    222292
     
    235305sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    236306{
    237         if (evno >= EVENT_END)
     307        if (evno >= EVENT_TASK_END)
    238308                return ELIMIT;
    239309       
    240         return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    241             imethod, &TASK->answerbox);
     310        return (sysarg_t) event_subscribe(evno2event(evno, TASK),
     311            (sysarg_t) imethod, &TASK->answerbox);
    242312}
    243313
     
    257327sysarg_t sys_event_unmask(sysarg_t evno)
    258328{
    259         if (evno >= EVENT_END)
     329        if (evno >= EVENT_TASK_END)
    260330                return ELIMIT;
    261331       
    262         event_unmask((event_type_t) evno);
     332        event_unmask(evno2event(evno, TASK));
     333
    263334        return EOK;
    264335}
  • kernel/generic/src/ipc/sysipc.c

    ref7052ec r42a619b  
    4444#include <ipc/irq.h>
    4545#include <ipc/ipcrsc.h>
     46#include <ipc/event.h>
    4647#include <ipc/kbox.h>
    4748#include <synch/waitq.h>
     
    134135        case IPC_M_DATA_WRITE:
    135136        case IPC_M_DATA_READ:
     137        case IPC_M_STATE_CHANGE_AUTHORIZE:
    136138                return true;
    137139        default:
     
    164166        case IPC_M_DATA_WRITE:
    165167        case IPC_M_DATA_READ:
     168        case IPC_M_STATE_CHANGE_AUTHORIZE:
    166169                return true;
    167170        default:
     
    334337                free(answer->buffer);
    335338                answer->buffer = NULL;
     339        } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_STATE_CHANGE_AUTHORIZE) {
     340                if (!IPC_GET_RETVAL(answer->data)) {
     341                        /* The recipient authorized the change of state. */
     342                        phone_t *recipient_phone;
     343                        task_t *other_task_s;
     344                        task_t *other_task_r;
     345                        int rc;
     346
     347                        rc = phone_get(IPC_GET_ARG1(answer->data),
     348                            &recipient_phone);
     349                        if (rc != EOK) {
     350                                IPC_SET_RETVAL(answer->data, ENOENT);
     351                                return ENOENT;
     352                        }
     353
     354                        mutex_lock(&recipient_phone->lock);
     355                        if (recipient_phone->state != IPC_PHONE_CONNECTED) {
     356                                mutex_unlock(&recipient_phone->lock);
     357                                IPC_SET_RETVAL(answer->data, EINVAL);
     358                                return EINVAL;
     359                        }
     360
     361                        other_task_r = recipient_phone->callee->task;
     362                        other_task_s = (task_t *) IPC_GET_ARG5(*olddata);
     363
     364                        /*
     365                         * See if both the sender and the recipient meant the
     366                         * same third party task.
     367                         */
     368                        if (other_task_r != other_task_s) {
     369                                IPC_SET_RETVAL(answer->data, EINVAL);
     370                                rc = EINVAL;
     371                        } else {
     372                                rc = event_task_notify_5(other_task_r,
     373                                    EVENT_TASK_STATE_CHANGE, false,
     374                                    IPC_GET_ARG1(*olddata),
     375                                    IPC_GET_ARG2(*olddata),
     376                                    IPC_GET_ARG3(*olddata),
     377                                    (sysarg_t) olddata->task,
     378                                    (sysarg_t) TASK);
     379                                IPC_SET_RETVAL(answer->data, rc);
     380                        }
     381
     382                        mutex_unlock(&recipient_phone->lock);
     383                        return rc;
     384                }
    336385        }
    337386       
     
    456505                }
    457506               
     507                break;
     508        }
     509        case IPC_M_STATE_CHANGE_AUTHORIZE: {
     510                phone_t *sender_phone;
     511                task_t *other_task_s;
     512
     513                if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
     514                        return ENOENT;
     515
     516                mutex_lock(&sender_phone->lock);
     517                if (sender_phone->state != IPC_PHONE_CONNECTED) {
     518                        mutex_unlock(&sender_phone->lock);
     519                        return EINVAL;
     520                }
     521
     522                other_task_s = sender_phone->callee->task;
     523
     524                mutex_unlock(&sender_phone->lock);
     525
     526                /* Remember the third party task hash. */
     527                IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
    458528                break;
    459529        }
  • kernel/generic/src/proc/task.c

    ref7052ec r42a619b  
    5050#include <ipc/ipc.h>
    5151#include <ipc/ipcrsc.h>
     52#include <ipc/event.h>
    5253#include <print.h>
    5354#include <errno.h>
     
    5758#include <syscall/copy.h>
    5859#include <macros.h>
    59 #include <ipc/event.h>
    6060
    6161/** Spinlock protecting the tasks_tree AVL tree. */
     
    201201        task->ipc_info.irq_notif_received = 0;
    202202        task->ipc_info.forwarded = 0;
     203
     204        event_task_init(task);
    203205       
    204206#ifdef CONFIG_UDEBUG
  • uspace/app/bdsh/exec.c

    ref7052ec r42a619b  
    4040#include <str_error.h>
    4141#include <errno.h>
     42#include <vfs/vfs.h>
    4243
    4344#include "config.h"
     
    99100        char *tmp;
    100101        int rc, retval, i;
    101         fdi_node_t file_nodes[3];
    102         fdi_node_t *file_nodes_p[4];
     102        int file_handles[3];
     103        int *file_handles_p[4];
    103104        FILE *files[3];
    104105
     
    111112       
    112113        for (i = 0; i < 3 && files[i] != NULL; i++) {
    113                 if (fnode(files[i], &file_nodes[i]) == EOK) {
    114                         file_nodes_p[i] = &file_nodes[i];
     114                if (fhandle(files[i], &file_handles[i]) == EOK) {
     115                        file_handles_p[i] = &file_handles[i];
    115116                }
    116117                else {
    117                         file_nodes_p[i] = NULL;
     118                        file_handles_p[i] = NULL;
    118119                }
    119120        }
    120         file_nodes_p[i] = NULL;
     121        file_handles_p[i] = NULL;
    121122
    122         rc = task_spawnvf(&tid, tmp, (const char **) argv, file_nodes_p);
     123        rc = task_spawnvf(&tid, tmp, (const char **) argv, file_handles_p);
    123124        free(tmp);
    124125
  • uspace/app/trace/trace.c

    ref7052ec r42a619b  
    5050#include <sys/types.h>
    5151#include <sys/typefmt.h>
     52#include <vfs/vfs.h>
    5253
    5354#include <libc.h>
     
    586587
    587588        /* Send default files */
    588         fdi_node_t *files[4];
    589         fdi_node_t stdin_node;
    590         fdi_node_t stdout_node;
    591         fdi_node_t stderr_node;
    592        
    593         if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
    594                 files[0] = &stdin_node;
     589        int *files[4];
     590        int fd_stdin;
     591        int fd_stdout;
     592        int fd_stderr;
     593       
     594        if ((stdin != NULL) && (fhandle(stdin, &fd_stdin) == EOK))
     595                files[0] = &fd_stdin;
    595596        else
    596597                files[0] = NULL;
    597598       
    598         if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
    599                 files[1] = &stdout_node;
     599        if ((stdout != NULL) && (fhandle(stdout, &fd_stdout) == EOK))
     600                files[1] = &fd_stdout;
    600601        else
    601602                files[1] = NULL;
    602603       
    603         if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
    604                 files[2] = &stderr_node;
     604        if ((stderr != NULL) && (fhandle(stderr, &fd_stderr) == EOK))
     605                files[2] = &fd_stderr;
    605606        else
    606607                files[2] = NULL;
     
    761762        o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
    762763        proto_add_oper(p, VFS_IN_OPEN, o);
    763         o = oper_new("open_node", 4, arg_def, V_INT_ERRNO, 0, resp_def);
    764         proto_add_oper(p, VFS_IN_OPEN_NODE, o);
    765764        o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def);
    766765        proto_add_oper(p, VFS_IN_READ, o);
  • uspace/lib/c/generic/async.c

    ref7052ec r42a619b  
    201201{
    202202        async_client_data_destroy = dtor;
    203 }
    204 
    205 void *async_get_client_data(void)
    206 {
    207         assert(fibril_connection);
    208         return fibril_connection->client->data;
    209203}
    210204
     
    580574}
    581575
     576static client_t *async_client_get(sysarg_t client_hash, bool create)
     577{
     578        unsigned long key = client_hash;
     579        client_t *client = NULL;
     580
     581        futex_down(&async_futex);
     582        link_t *lnk = hash_table_find(&client_hash_table, &key);
     583        if (lnk) {
     584                client = hash_table_get_instance(lnk, client_t, link);
     585                atomic_inc(&client->refcnt);
     586        } else if (create) {
     587                client = malloc(sizeof(client_t));
     588                if (client) {
     589                        client->in_task_hash = client_hash;
     590                        client->data = async_client_data_create();
     591               
     592                        atomic_set(&client->refcnt, 1);
     593                        hash_table_insert(&client_hash_table, &key, &client->link);
     594                }
     595        }
     596
     597        futex_up(&async_futex);
     598        return client;
     599}
     600
     601static void async_client_put(client_t *client)
     602{
     603        bool destroy;
     604        unsigned long key = client->in_task_hash;
     605       
     606        futex_down(&async_futex);
     607       
     608        if (atomic_predec(&client->refcnt) == 0) {
     609                hash_table_remove(&client_hash_table, &key, 1);
     610                destroy = true;
     611        } else
     612                destroy = false;
     613       
     614        futex_up(&async_futex);
     615       
     616        if (destroy) {
     617                if (client->data)
     618                        async_client_data_destroy(client->data);
     619               
     620                free(client);
     621        }
     622}
     623
     624void *async_get_client_data(void)
     625{
     626        assert(fibril_connection);
     627        return fibril_connection->client->data;
     628}
     629
     630void *async_get_client_data_by_hash(sysarg_t client_hash)
     631{
     632        client_t *client = async_client_get(client_hash, false);
     633        if (!client)
     634                return NULL;
     635        if (!client->data) {
     636                async_client_put(client);
     637                return NULL;
     638        }
     639
     640        return client->data;
     641}
     642
     643void async_put_client_data_by_hash(sysarg_t client_hash)
     644{
     645        client_t *client = async_client_get(client_hash, false);
     646
     647        assert(client);
     648        assert(client->data);
     649
     650        /* Drop the reference we got in async_get_client_data_by_hash(). */
     651        async_client_put(client);
     652
     653        /* Drop our own reference we got at the beginning of this function. */
     654        async_client_put(client);
     655}
     656
    582657/** Wrapper for client connection fibril.
    583658 *
     
    598673         */
    599674        fibril_connection = (connection_t *) arg;
    600        
    601         futex_down(&async_futex);
    602675       
    603676        /*
     
    606679         * hash in a new tracking structure.
    607680         */
    608        
    609         unsigned long key = fibril_connection->in_task_hash;
    610         link_t *lnk = hash_table_find(&client_hash_table, &key);
    611        
    612         client_t *client;
    613        
    614         if (lnk) {
    615                 client = hash_table_get_instance(lnk, client_t, link);
    616                 atomic_inc(&client->refcnt);
    617         } else {
    618                 client = malloc(sizeof(client_t));
    619                 if (!client) {
    620                         ipc_answer_0(fibril_connection->callid, ENOMEM);
    621                         futex_up(&async_futex);
    622                         return 0;
    623                 }
    624                
    625                 client->in_task_hash = fibril_connection->in_task_hash;
    626                 client->data = async_client_data_create();
    627                
    628                 atomic_set(&client->refcnt, 1);
    629                 hash_table_insert(&client_hash_table, &key, &client->link);
    630         }
    631        
    632         futex_up(&async_futex);
    633        
     681
     682        client_t *client = async_client_get(fibril_connection->in_task_hash, true);
     683        if (!client) {
     684                ipc_answer_0(fibril_connection->callid, ENOMEM);
     685                return 0;
     686        }
     687
    634688        fibril_connection->client = client;
    635689       
     
    643697         * Remove the reference for this client task connection.
    644698         */
    645         bool destroy;
    646        
    647         futex_down(&async_futex);
    648        
    649         if (atomic_predec(&client->refcnt) == 0) {
    650                 hash_table_remove(&client_hash_table, &key, 1);
    651                 destroy = true;
    652         } else
    653                 destroy = false;
    654        
    655         futex_up(&async_futex);
    656        
    657         if (destroy) {
    658                 if (client->data)
    659                         async_client_data_destroy(client->data);
    660                
    661                 free(client);
    662         }
     699        async_client_put(client);
    663700       
    664701        /*
     
    666703         */
    667704        futex_down(&async_futex);
    668         key = fibril_connection->in_phone_hash;
     705        unsigned long key = fibril_connection->in_phone_hash;
    669706        hash_table_remove(&conn_hash_table, &key, 1);
    670707        futex_up(&async_futex);
     
    24292466}
    24302467
     2468int async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
     2469    sysarg_t arg3, async_exch_t *other_exch)
     2470{
     2471        return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE,
     2472            arg1, arg2, arg3, 0, other_exch->phone);
     2473}
     2474
     2475bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1,
     2476    sysarg_t *arg2, sysarg_t *arg3)
     2477{
     2478        assert(callid);
     2479
     2480        ipc_call_t call;
     2481        *callid = async_get_call(&call);
     2482
     2483        if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE)
     2484                return false;
     2485       
     2486        if (arg1)
     2487                *arg1 = IPC_GET_ARG1(call);
     2488        if (arg2)
     2489                *arg2 = IPC_GET_ARG2(call);
     2490        if (arg3)
     2491                *arg3 = IPC_GET_ARG3(call);
     2492
     2493        return true;
     2494}
     2495
     2496int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch)
     2497{
     2498        return ipc_answer_1(callid, EOK, other_exch->phone);
     2499}
     2500
    24312501/** @}
    24322502 */
  • uspace/lib/c/generic/event.c

    ref7052ec r42a619b  
    5454}
    5555
     56int event_task_subscribe(event_task_type_t evno, sysarg_t imethod)
     57{
     58        return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
     59            (sysarg_t) imethod);
     60}
     61
    5662/** Unmask event notifications.
    5763 *
     
    6672}
    6773
     74int event_task_unmask(event_task_type_t evno)
     75{
     76        return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
     77}
     78
    6879/** @}
    6980 */
  • uspace/lib/c/generic/io/io.c

    ref7052ec r42a619b  
    101101static LIST_INITIALIZE(files);
    102102
    103 void __stdio_init(int filc, fdi_node_t *filv[])
     103void __stdio_init(int filc)
    104104{
    105105        if (filc > 0) {
    106                 stdin = fopen_node(filv[0], "r");
     106                stdin = fdopen(0, "r");
    107107        } else {
    108108                stdin = &stdin_null;
     
    111111       
    112112        if (filc > 1) {
    113                 stdout = fopen_node(filv[1], "w");
     113                stdout = fdopen(1, "w");
    114114        } else {
    115115                stdout = &stdout_klog;
     
    118118       
    119119        if (filc > 2) {
    120                 stderr = fopen_node(filv[2], "w");
     120                stderr = fdopen(2, "w");
    121121        } else {
    122122                stderr = &stderr_klog;
     
    285285}
    286286
    287 FILE *fopen_node(fdi_node_t *node, const char *mode)
    288 {
    289         int flags;
    290         if (!parse_mode(mode, &flags))
    291                 return NULL;
    292        
    293         /* Open file. */
    294         FILE *stream = malloc(sizeof(FILE));
    295         if (stream == NULL) {
    296                 errno = ENOMEM;
    297                 return NULL;
    298         }
    299        
    300         stream->fd = open_node(node, flags);
    301         if (stream->fd < 0) {
    302                 /* errno was set by open_node() */
    303                 free(stream);
    304                 return NULL;
    305         }
    306        
    307         stream->error = false;
    308         stream->eof = false;
    309         stream->klog = false;
    310         stream->sess = NULL;
    311         stream->need_sync = false;
    312         _setvbuf(stream);
    313        
    314         list_append(&stream->link, &files);
    315        
    316         return stream;
    317 }
    318 
    319287int fclose(FILE *stream)
    320288{
     
    780748}
    781749
    782 int fnode(FILE *stream, fdi_node_t *node)
    783 {
    784         if (stream->fd >= 0)
    785                 return fd_node(stream->fd, node);
     750int fhandle(FILE *stream, int *handle)
     751{
     752        if (stream->fd >= 0) {
     753                *handle = stream->fd;
     754                return EOK;
     755        }
    786756       
    787757        return ENOENT;
  • uspace/lib/c/generic/libc.c

    ref7052ec r42a619b  
    9191                argc = 0;
    9292                argv = NULL;
    93                 __stdio_init(0, NULL);
     93                __stdio_init(0);
    9494        } else {
    9595                argc = __pcb->argc;
    9696                argv = __pcb->argv;
    97                 __stdio_init(__pcb->filc, __pcb->filv);
     97                __stdio_init(__pcb->filc);
    9898                (void) chdir(__pcb->cwd);
    9999        }
  • uspace/lib/c/generic/loader.c

    ref7052ec r42a619b  
    256256 *
    257257 */
    258 int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
    259 {
    260         /*
    261          * Serialize the arguments into a single array. First
    262          * compute size of the buffer needed.
    263          */
    264         fdi_node_t *const *ap = files;
    265         size_t count = 0;
    266         while (*ap != NULL) {
    267                 count++;
    268                 ap++;
    269         }
    270        
    271         fdi_node_t *files_buf;
    272         files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
    273         if (files_buf == NULL)
    274                 return ENOMEM;
    275        
    276         /* Fill the buffer */
    277         size_t i;
    278         for (i = 0; i < count; i++)
    279                 files_buf[i] = *files[i];
    280        
     258int loader_set_files(loader_t *ldr, int * const files[])
     259{
    281260        /* Send serialized files to the loader */
    282261        async_exch_t *exch = async_exchange_begin(ldr->sess);
    283        
    284         ipc_call_t answer;
    285         aid_t req = async_send_0(exch, LOADER_SET_FILES, &answer);
    286         sysarg_t rc = async_data_write_start(exch, (void *) files_buf,
    287             count * sizeof(fdi_node_t));
    288        
    289         async_exchange_end(exch);
    290         free(files_buf);
    291        
     262        async_exch_t *vfs_exch = vfs_exchange_begin();
     263       
     264        int i;
     265        for (i = 0; files[i]; i++)
     266                ;
     267
     268        ipc_call_t answer;
     269        aid_t req = async_send_1(exch, LOADER_SET_FILES, i, &answer);
     270
     271        sysarg_t rc = EOK;
     272       
     273        for (i = 0; files[i]; i++) {
     274                rc = async_state_change_start(exch, VFS_PASS_HANDLE, *files[i],
     275                    0, vfs_exch);
     276                if (rc != EOK)
     277                        break;
     278        }
     279       
     280        vfs_exchange_end(vfs_exch);
     281        async_exchange_end(exch);
     282
    292283        if (rc != EOK) {
    293284                async_wait_for(req, NULL);
  • uspace/lib/c/generic/private/async.h

    ref7052ec r42a619b  
    3636#define LIBC_PRIVATE_ASYNC_H_
    3737
     38#include <ipc/common.h>
    3839#include <adt/list.h>
    3940#include <fibril.h>
  • uspace/lib/c/generic/private/io.h

    ref7052ec r42a619b  
    3636#define LIBC_PRIVATE_IO_H_
    3737
    38 #include <vfs/vfs.h>
    39 
    40 extern void __stdio_init(int filc, fdi_node_t *filv[]);
     38extern void __stdio_init(int);
    4139extern void __stdio_done(void);
    4240
  • uspace/lib/c/generic/task.c

    ref7052ec r42a619b  
    4646#include <libc.h>
    4747#include "private/ns.h"
     48#include <vfs/vfs.h>
    4849
    4950task_id_t task_get_id(void)
     
    102103{
    103104        /* Send default files */
    104         fdi_node_t *files[4];
    105         fdi_node_t stdin_node;
    106         fdi_node_t stdout_node;
    107         fdi_node_t stderr_node;
    108        
    109         if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
    110                 files[0] = &stdin_node;
     105        int *files[4];
     106        int fd_stdin;
     107        int fd_stdout;
     108        int fd_stderr;
     109       
     110        if ((stdin != NULL) && (fhandle(stdin, &fd_stdin) == EOK))
     111                files[0] = &fd_stdin;
    111112        else
    112113                files[0] = NULL;
    113114       
    114         if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
    115                 files[1] = &stdout_node;
     115        if ((stdout != NULL) && (fhandle(stdout, &fd_stdout) == EOK))
     116                files[1] = &fd_stdout;
    116117        else
    117118                files[1] = NULL;
    118119       
    119         if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
    120                 files[2] = &stderr_node;
     120        if ((stderr != NULL) && (fhandle(stderr, &fd_stderr) == EOK))
     121                files[2] = &fd_stderr;
    121122        else
    122123                files[2] = NULL;
     
    142143 */
    143144int task_spawnvf(task_id_t *id, const char *path, const char *const args[],
    144     fdi_node_t *const files[])
     145    int *const files[])
    145146{
    146147        /* Connect to a program loader. */
  • uspace/lib/c/generic/vfs/vfs.c

    ref7052ec r42a619b  
    6969 *
    7070 */
    71 static async_exch_t *vfs_exchange_begin(void)
     71async_exch_t *vfs_exchange_begin(void)
    7272{
    7373        fibril_mutex_lock(&vfs_mutex);
     
    8787 *
    8888 */
    89 static void vfs_exchange_end(async_exch_t *exch)
     89void vfs_exchange_end(async_exch_t *exch)
    9090{
    9191        async_exchange_end(exch);
     
    329329}
    330330
    331 int open_node(fdi_node_t *node, int oflag)
    332 {
    333         async_exch_t *exch = vfs_exchange_begin();
    334        
    335         ipc_call_t answer;
    336         aid_t req = async_send_4(exch, VFS_IN_OPEN_NODE, node->fs_handle,
    337             node->service_id, node->index, oflag, &answer);
    338        
    339         vfs_exchange_end(exch);
    340 
    341         sysarg_t rc;
    342         async_wait_for(req, &rc);
    343        
    344         if (rc != EOK)
    345                 return (int) rc;
    346        
    347         return (int) IPC_GET_ARG1(answer);
    348 }
    349 
    350331int close(int fildes)
    351332{
     
    819800}
    820801
    821 int fd_node(int fildes, fdi_node_t *node)
    822 {
    823         struct stat stat;
    824         int rc = fstat(fildes, &stat);
    825        
    826         if (rc == EOK) {
    827                 node->fs_handle = stat.fs_handle;
    828                 node->service_id = stat.service_id;
    829                 node->index = stat.index;
    830         }
    831        
    832         return rc;
    833 }
    834 
    835802int dup2(int oldfd, int newfd)
    836803{
     
    848815}
    849816
     817int fd_wait(void)
     818{
     819        async_exch_t *exch = vfs_exchange_begin();
     820       
     821        sysarg_t ret;
     822        sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
     823       
     824        vfs_exchange_end(exch);
     825       
     826        if (rc == EOK)
     827                return (int) ret;
     828       
     829        return (int) rc;
     830}
     831
    850832/** @}
    851833 */
  • uspace/lib/c/include/async.h

    ref7052ec r42a619b  
    186186extern void async_set_client_data_destructor(async_client_data_dtor_t);
    187187extern void *async_get_client_data(void);
     188extern void *async_get_client_data_by_hash(sysarg_t);
     189extern void async_put_client_data_by_hash(sysarg_t);
    188190
    189191extern void async_set_client_connection(async_client_conn_t);
     
    477479extern async_sess_t *async_callback_receive_start(exch_mgmt_t, ipc_call_t *);
    478480
     481extern int async_state_change_start(async_exch_t *, sysarg_t, sysarg_t,
     482    sysarg_t, async_exch_t *);
     483extern bool async_state_change_receive(ipc_callid_t *, sysarg_t *, sysarg_t *,
     484    sysarg_t *);
     485extern int async_state_change_finalize(ipc_callid_t, async_exch_t *);
     486
    479487#endif
    480488
  • uspace/lib/c/include/event.h

    ref7052ec r42a619b  
    3737
    3838#include <abi/ipc/event.h>
     39#include <libarch/types.h>
    3940
    4041extern int event_subscribe(event_type_t, sysarg_t);
     42extern int event_task_subscribe(event_task_type_t, sysarg_t);
    4143extern int event_unmask(event_type_t);
     44extern int event_task_unmask(event_task_type_t);
    4245
    4346#endif
  • uspace/lib/c/include/ipc/vfs.h

    ref7052ec r42a619b  
    6262typedef enum {
    6363        VFS_IN_OPEN = IPC_FIRST_USER_METHOD,
    64         VFS_IN_OPEN_NODE,
    6564        VFS_IN_READ,
    6665        VFS_IN_WRITE,
     
    7877        VFS_IN_RENAME,
    7978        VFS_IN_STAT,
    80         VFS_IN_DUP
     79        VFS_IN_DUP,
     80        VFS_IN_WAIT_HANDLE,
    8181} vfs_in_request_t;
    8282
  • uspace/lib/c/include/loader/loader.h

    ref7052ec r42a619b  
    3838
    3939#include <task.h>
    40 #include <vfs/vfs.h>
    4140
    4241/** Forward declararion */
     
    5049extern int loader_set_pathname(loader_t *, const char *);
    5150extern int loader_set_args(loader_t *, const char *const[]);
    52 extern int loader_set_files(loader_t *, fdi_node_t *const[]);
     51extern int loader_set_files(loader_t *, int *const[]);
    5352extern int loader_load_program(loader_t *);
    5453extern int loader_run(loader_t *);
  • uspace/lib/c/include/loader/pcb.h

    ref7052ec r42a619b  
    3838
    3939#include <sys/types.h>
    40 #include <vfs/vfs.h>
    4140
    4241typedef void (*entry_point_t)(void);
     
    6261       
    6362        /** Number of preset files. */
    64         int filc;
    65         /** Preset files. */
    66         fdi_node_t **filv;
     63        unsigned int filc;
    6764       
    6865        /*
  • uspace/lib/c/include/task.h

    ref7052ec r42a619b  
    3737
    3838#include <sys/types.h>
    39 #include <vfs/vfs.h>
    4039
    4140typedef uint64_t task_id_t;
     
    5352extern int task_spawnv(task_id_t *, const char *path, const char *const []);
    5453extern int task_spawnvf(task_id_t *, const char *path, const char *const [],
    55     fdi_node_t *const []);
     54    int *const []);
    5655extern int task_spawnl(task_id_t *, const char *path, ...);
    5756
  • uspace/lib/c/include/vfs/vfs.h

    ref7052ec r42a619b  
    4040#include <ipc/loc.h>
    4141#include <stdio.h>
     42#include <async.h>
    4243
    43 /** Libc version of the VFS triplet.
    44  *
    45  * Unique identification of a file system node
    46  * within a file system instance.
    47  *
    48  */
    49 typedef struct {
    50         fs_handle_t fs_handle;
    51         service_id_t service_id;
    52         fs_index_t index;
    53 } fdi_node_t;
     44enum vfs_change_state_type {
     45        VFS_PASS_HANDLE
     46};
    5447
    5548extern char *absolutize(const char *, size_t *);
     
    5952extern int unmount(const char *);
    6053
    61 extern int open_node(fdi_node_t *, int);
    62 extern int fd_node(int, fdi_node_t *);
     54extern int fhandle(FILE *, int *);
    6355
    64 extern FILE *fopen_node(fdi_node_t *, const char *);
    65 extern int fnode(FILE *, fdi_node_t *);
     56extern int fd_wait(void);
     57
     58extern async_exch_t *vfs_exchange_begin(void);
     59extern void vfs_exchange_end(async_exch_t *);
    6660
    6761#endif
  • uspace/srv/hid/input/port/adb_mouse.c

    ref7052ec r42a619b  
    4242#include <errno.h>
    4343#include <loc.h>
     44#include <stdio.h>
    4445
    4546static mouse_dev_t *mouse_dev;
  • uspace/srv/hw/irc/apic/apic.c

    ref7052ec r42a619b  
    4545#include <errno.h>
    4646#include <async.h>
     47#include <stdio.h>
    4748
    4849#define NAME  "apic"
  • uspace/srv/loader/main.c

    ref7052ec r42a619b  
    6161#include <elf/elf.h>
    6262#include <elf/elf_load.h>
     63#include <vfs/vfs.h>
    6364
    6465#ifdef CONFIG_RTLD
     
    8990
    9091/** Number of preset files */
    91 static int filc = 0;
    92 /** Preset files vector */
    93 static fdi_node_t **filv = NULL;
    94 /** Buffer holding all preset files */
    95 static fdi_node_t *fil_buf = NULL;
     92static unsigned int filc = 0;
    9693
    9794static elf_info_t prog_info;
     
    239236static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
    240237{
    241         fdi_node_t *buf;
    242         size_t buf_size;
    243         int rc = async_data_write_accept((void **) &buf, false, 0, 0,
    244             sizeof(fdi_node_t), &buf_size);
    245        
    246         if (rc == EOK) {
    247                 int count = buf_size / sizeof(fdi_node_t);
    248                
    249                 /*
    250                  * Allocate new filv
    251                  */
    252                 fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *));
    253                 if (_filv == NULL) {
    254                         free(buf);
    255                         async_answer_0(rid, ENOMEM);
    256                         return;
     238        size_t count = IPC_GET_ARG1(*request);
     239
     240        async_exch_t *vfs_exch = vfs_exchange_begin();
     241
     242        for (filc = 0; filc < count; filc++) {
     243                ipc_callid_t callid;
     244                int fd;
     245
     246                if (!async_state_change_receive(&callid, NULL, NULL, NULL)) {
     247                        async_answer_0(callid, EINVAL);
     248                        break;
    257249                }
    258                
    259                 /*
    260                  * Fill the new filv with argument pointers
    261                  */
    262                 int i;
    263                 for (i = 0; i < count; i++)
    264                         _filv[i] = &buf[i];
    265                
    266                 _filv[count] = NULL;
    267                
    268                 /*
    269                  * Copy temporary data to global variables
    270                  */
    271                 if (fil_buf != NULL)
    272                         free(fil_buf);
    273                
    274                 if (filv != NULL)
    275                         free(filv);
    276                
    277                 filc = count;
    278                 fil_buf = buf;
    279                 filv = _filv;
    280         }
    281        
     250                async_state_change_finalize(callid, vfs_exch);
     251                fd = fd_wait();
     252                assert(fd == (int) filc);
     253        }
     254
     255        vfs_exchange_end(vfs_exch);
     256
    282257        async_answer_0(rid, EOK);
    283258}
     
    308283       
    309284        pcb.filc = filc;
    310         pcb.filv = filv;
    311285       
    312286        if (prog_info.interp == NULL) {
  • uspace/srv/loc/loc.h

    ref7052ec r42a619b  
    3636#define LOC_H_
    3737
     38#include <ipc/loc.h>
    3839#include <async.h>
    3940#include <fibril_synch.h>
  • uspace/srv/vfs/vfs.c

    ref7052ec r42a619b  
    3737
    3838#include <ipc/services.h>
     39#include <abi/ipc/event.h>
     40#include <event.h>
    3941#include <ns.h>
    4042#include <async.h>
     
    4547#include <as.h>
    4648#include <atomic.h>
     49#include <vfs/vfs.h>
    4750#include "vfs.h"
    4851
     
    8083                        vfs_open(callid, &call);
    8184                        break;
    82                 case VFS_IN_OPEN_NODE:
    83                         vfs_open_node(callid, &call);
    84                         break;
    8585                case VFS_IN_CLOSE:
    8686                        vfs_close(callid, &call);
     
    118118                case VFS_IN_DUP:
    119119                        vfs_dup(callid, &call);
     120                        break;
     121                case VFS_IN_WAIT_HANDLE:
     122                        vfs_wait_handle(callid, &call);
     123                        break;
    120124                default:
    121125                        async_answer_0(callid, ENOTSUP);
     
    128132         * connection fibril terminates.
    129133         */
     134}
     135
     136enum {
     137        VFS_TASK_STATE_CHANGE
     138};
     139
     140static void notification_received(ipc_callid_t callid, ipc_call_t *call)
     141{
     142        switch (IPC_GET_IMETHOD(*call)) {
     143        case VFS_TASK_STATE_CHANGE:
     144                if (IPC_GET_ARG1(*call) == VFS_PASS_HANDLE)
     145                        vfs_pass_handle(IPC_GET_ARG4(*call),
     146                            IPC_GET_ARG5(*call), (int) IPC_GET_ARG2(*call));
     147                break;
     148        default:
     149                break;
     150        }
    130151}
    131152
     
    170191
    171192        /*
     193         * Set notification handler and subscribe to notifications.
     194         */
     195        async_set_interrupt_received(notification_received);
     196        event_task_subscribe(EVENT_TASK_STATE_CHANGE, VFS_TASK_STATE_CHANGE);
     197
     198        /*
    172199         * Register at the naming service.
    173200         */
  • uspace/srv/vfs/vfs.h

    ref7052ec r42a619b  
    175175extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
    176176    vfs_pair_t *, ...);
    177 extern int vfs_open_node_internal(vfs_lookup_res_t *);
    178177
    179178extern bool vfs_nodes_init(void);
     
    189188extern void vfs_client_data_destroy(void *);
    190189
     190extern void vfs_pass_handle(sysarg_t, sysarg_t, int);
     191extern int vfs_wait_handle_internal(void);
     192
    191193extern vfs_file_t *vfs_file_get(int);
    192194extern void vfs_file_put(vfs_file_t *);
     
    197199extern void vfs_node_addref(vfs_node_t *);
    198200extern void vfs_node_delref(vfs_node_t *);
     201extern int vfs_open_node_remote(vfs_node_t *);
    199202
    200203extern void vfs_register(ipc_callid_t, ipc_call_t *);
     
    202205extern void vfs_unmount(ipc_callid_t, ipc_call_t *);
    203206extern void vfs_open(ipc_callid_t, ipc_call_t *);
    204 extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
    205207extern void vfs_sync(ipc_callid_t, ipc_call_t *);
    206208extern void vfs_dup(ipc_callid_t, ipc_call_t *);
     
    215217extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
    216218extern void vfs_rename(ipc_callid_t, ipc_call_t *);
     219extern void vfs_wait_handle(ipc_callid_t, ipc_call_t *);
    217220
    218221#endif
  • uspace/srv/vfs/vfs_file.c

    ref7052ec r42a619b  
    4343#include <fibril.h>
    4444#include <fibril_synch.h>
     45#include <adt/list.h>
    4546#include "vfs.h"
    4647
     
    5051typedef struct {
    5152        fibril_mutex_t lock;
     53        fibril_condvar_t cv;
     54        list_t passed_handles;
    5255        vfs_file_t **files;
    5356} vfs_client_data_t;
    5457
     58typedef struct {
     59        link_t link;
     60        int handle;
     61} vfs_boxed_handle_t;
     62
     63static int _vfs_fd_free(vfs_client_data_t *, int);
     64
    5565/** Initialize the table of open files. */
    56 static bool vfs_files_init(void)
    57 {
    58         fibril_mutex_lock(&VFS_DATA->lock);
    59         if (!FILES) {
    60                 FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
    61                 if (!FILES) {
    62                         fibril_mutex_unlock(&VFS_DATA->lock);
     66static bool vfs_files_init(vfs_client_data_t *vfs_data)
     67{
     68        fibril_mutex_lock(&vfs_data->lock);
     69        if (!vfs_data->files) {
     70                vfs_data->files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
     71                if (!vfs_data->files) {
     72                        fibril_mutex_unlock(&vfs_data->lock);
    6373                        return false;
    6474                }
    65                 memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
    66         }
    67         fibril_mutex_unlock(&VFS_DATA->lock);
     75                memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     76        }
     77        fibril_mutex_unlock(&vfs_data->lock);
    6878        return true;
    6979}
    7080
    7181/** Cleanup the table of open files. */
    72 static void vfs_files_done(void)
     82static void vfs_files_done(vfs_client_data_t *vfs_data)
    7383{
    7484        int i;
    7585
    76         if (!FILES)
     86        if (!vfs_data->files)
    7787                return;
    7888
    7989        for (i = 0; i < MAX_OPEN_FILES; i++) {
    80                 if (FILES[i]) {
    81                         (void) vfs_fd_free(i);
    82                 }
    83         }
    84        
    85         free(FILES);
     90                if (vfs_data->files[i])
     91                        (void) _vfs_fd_free(vfs_data, i);
     92        }
     93       
     94        free(vfs_data->files);
     95
     96        while (!list_empty(&vfs_data->passed_handles)) {
     97                link_t *lnk;
     98                vfs_boxed_handle_t *bh;
     99               
     100                lnk = list_first(&vfs_data->passed_handles);
     101                list_remove(lnk);
     102
     103                bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
     104                free(bh);
     105        }
    86106}
    87107
     
    93113        if (vfs_data) {
    94114                fibril_mutex_initialize(&vfs_data->lock);
     115                fibril_condvar_initialize(&vfs_data->cv);
     116                list_initialize(&vfs_data->passed_handles);
    95117                vfs_data->files = NULL;
    96118        }
     
    103125        vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
    104126
    105         vfs_files_done();
     127        vfs_files_done(vfs_data);
    106128        free(vfs_data);
    107129}
     
    131153 *                      incremented.
    132154 */
    133 static void vfs_file_addref(vfs_file_t *file)
    134 {
    135         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
     155static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file)
     156{
     157        assert(fibril_mutex_is_locked(&vfs_data->lock));
    136158
    137159        file->refcnt++;
     
    143165 *                      decremented.
    144166 */
    145 static int vfs_file_delref(vfs_file_t *file)
     167static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
    146168{
    147169        int rc = EOK;
    148170
    149         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
     171        assert(fibril_mutex_is_locked(&vfs_data->lock));
    150172
    151173        if (file->refcnt-- == 1) {
     
    162184}
    163185
    164 
    165 /** Allocate a file descriptor.
    166  *
    167  * @param desc If true, look for an available file descriptor
    168  *             in a descending order.
    169  *
    170  * @return First available file descriptor or a negative error
    171  *         code.
    172  */
    173 int vfs_fd_alloc(bool desc)
    174 {
    175         if (!vfs_files_init())
     186static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
     187{
     188        if (!vfs_files_init(vfs_data))
    176189                return ENOMEM;
    177190       
     
    182195                i = 0;
    183196       
    184         fibril_mutex_lock(&VFS_DATA->lock);
     197        fibril_mutex_lock(&vfs_data->lock);
    185198        while (true) {
    186                 if (!FILES[i]) {
    187                         FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
    188                         if (!FILES[i]) {
    189                                 fibril_mutex_unlock(&VFS_DATA->lock);
     199                if (!vfs_data->files[i]) {
     200                        vfs_data->files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     201                        if (!vfs_data->files[i]) {
     202                                fibril_mutex_unlock(&vfs_data->lock);
    190203                                return ENOMEM;
    191204                        }
    192205                       
    193                         memset(FILES[i], 0, sizeof(vfs_file_t));
    194                         fibril_mutex_initialize(&FILES[i]->lock);
    195                         vfs_file_addref(FILES[i]);
    196                         fibril_mutex_unlock(&VFS_DATA->lock);
     206                        memset(vfs_data->files[i], 0, sizeof(vfs_file_t));
     207                        fibril_mutex_initialize(&vfs_data->files[i]->lock);
     208                        vfs_file_addref(vfs_data, vfs_data->files[i]);
     209                        fibril_mutex_unlock(&vfs_data->lock);
    197210                        return (int) i;
    198211                }
     
    210223                }
    211224        }
    212         fibril_mutex_unlock(&VFS_DATA->lock);
     225        fibril_mutex_unlock(&vfs_data->lock);
    213226       
    214227        return EMFILE;
     228}
     229
     230/** Allocate a file descriptor.
     231 *
     232 * @param desc If true, look for an available file descriptor
     233 *             in a descending order.
     234 *
     235 * @return First available file descriptor or a negative error
     236 *         code.
     237 */
     238int vfs_fd_alloc(bool desc)
     239{
     240        return _vfs_fd_alloc(VFS_DATA, desc);
     241}
     242
     243static int _vfs_fd_free(vfs_client_data_t *vfs_data, int fd)
     244{
     245        int rc;
     246
     247        if (!vfs_files_init(vfs_data))
     248                return ENOMEM;
     249
     250        fibril_mutex_lock(&vfs_data->lock);     
     251        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) {
     252                fibril_mutex_unlock(&vfs_data->lock);
     253                return EBADF;
     254        }
     255       
     256        rc = vfs_file_delref(vfs_data, vfs_data->files[fd]);
     257        vfs_data->files[fd] = NULL;
     258        fibril_mutex_unlock(&vfs_data->lock);
     259       
     260        return rc;
    215261}
    216262
     
    224270int vfs_fd_free(int fd)
    225271{
    226         int rc;
    227 
    228         if (!vfs_files_init())
    229                 return ENOMEM;
    230 
    231         fibril_mutex_lock(&VFS_DATA->lock);     
    232         if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
    233                 fibril_mutex_unlock(&VFS_DATA->lock);
    234                 return EBADF;
    235         }
    236        
    237         rc = vfs_file_delref(FILES[fd]);
    238         FILES[fd] = NULL;
    239         fibril_mutex_unlock(&VFS_DATA->lock);
    240        
    241         return rc;
     272        return _vfs_fd_free(VFS_DATA, fd);
    242273}
    243274
     
    253284int vfs_fd_assign(vfs_file_t *file, int fd)
    254285{
    255         if (!vfs_files_init())
     286        if (!vfs_files_init(VFS_DATA))
    256287                return ENOMEM;
    257288
     
    263294       
    264295        FILES[fd] = file;
    265         vfs_file_addref(FILES[fd]);
     296        vfs_file_addref(VFS_DATA, FILES[fd]);
    266297        fibril_mutex_unlock(&VFS_DATA->lock);
    267298       
     
    269300}
    270301
    271 /** Find VFS file structure for a given file descriptor.
    272  *
    273  * @param fd            File descriptor.
    274  *
    275  * @return              VFS file structure corresponding to fd.
    276  */
    277 vfs_file_t *vfs_file_get(int fd)
    278 {
    279         if (!vfs_files_init())
     302static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
     303{
     304        if (!vfs_files_init(vfs_data))
    280305                return NULL;
    281306       
    282         fibril_mutex_lock(&VFS_DATA->lock);
     307        fibril_mutex_lock(&vfs_data->lock);
    283308        if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    284                 vfs_file_t *file = FILES[fd];
     309                vfs_file_t *file = vfs_data->files[fd];
    285310                if (file != NULL) {
    286                         vfs_file_addref(file);
    287                         fibril_mutex_unlock(&VFS_DATA->lock);
     311                        vfs_file_addref(vfs_data, file);
     312                        fibril_mutex_unlock(&vfs_data->lock);
    288313                        return file;
    289314                }
    290315        }
    291         fibril_mutex_unlock(&VFS_DATA->lock);
     316        fibril_mutex_unlock(&vfs_data->lock);
    292317       
    293318        return NULL;
    294319}
    295320
     321/** Find VFS file structure for a given file descriptor.
     322 *
     323 * @param fd            File descriptor.
     324 *
     325 * @return              VFS file structure corresponding to fd.
     326 */
     327vfs_file_t *vfs_file_get(int fd)
     328{
     329        return _vfs_file_get(VFS_DATA, fd);
     330}
     331
     332static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
     333{
     334        fibril_mutex_lock(&vfs_data->lock);
     335        vfs_file_delref(vfs_data, file);
     336        fibril_mutex_unlock(&vfs_data->lock);
     337}
     338
    296339/** Stop using a file structure.
    297340 *
     
    300343void vfs_file_put(vfs_file_t *file)
    301344{
    302         fibril_mutex_lock(&VFS_DATA->lock);
    303         vfs_file_delref(file);
    304         fibril_mutex_unlock(&VFS_DATA->lock);
     345        _vfs_file_put(VFS_DATA, file);
     346}
     347
     348void vfs_pass_handle(sysarg_t donor_hash, sysarg_t acceptor_hash, int donor_fd)
     349{
     350        vfs_client_data_t *donor_data = NULL;
     351        vfs_client_data_t *acceptor_data = NULL;
     352        vfs_file_t *donor_file = NULL;
     353        vfs_file_t *acceptor_file = NULL;
     354        vfs_boxed_handle_t *bh;
     355        int acceptor_fd;
     356
     357        acceptor_data = async_get_client_data_by_hash(acceptor_hash);
     358        if (!acceptor_data)
     359                return;
     360
     361        bh = malloc(sizeof(vfs_boxed_handle_t));
     362        assert(bh);
     363
     364        link_initialize(&bh->link);
     365        bh->handle = -1;
     366
     367        donor_data = async_get_client_data_by_hash(donor_hash);
     368        if (!donor_data)
     369                goto out;
     370
     371        donor_file = _vfs_file_get(donor_data, donor_fd);
     372        if (!donor_file)
     373                goto out;
     374
     375        acceptor_fd = _vfs_fd_alloc(acceptor_data, false);
     376        if (acceptor_fd < 0)
     377                goto out;
     378
     379        bh->handle = acceptor_fd;
     380
     381        /*
     382         * Add a new reference to the underlying VFS node.
     383         */
     384        vfs_node_addref(donor_file->node);
     385        (void) vfs_open_node_remote(donor_file->node);
     386
     387        acceptor_file = _vfs_file_get(acceptor_data, acceptor_fd);
     388        assert(acceptor_file);
     389
     390        /*
     391         * Inherit attributes from the donor.
     392         */
     393        acceptor_file->node = donor_file->node;
     394        acceptor_file->append = donor_file->append;
     395        acceptor_file->pos = donor_file->pos;
     396
     397out:
     398        fibril_mutex_lock(&acceptor_data->lock);
     399        list_append(&bh->link, &acceptor_data->passed_handles);
     400        fibril_condvar_broadcast(&acceptor_data->cv);
     401        fibril_mutex_unlock(&acceptor_data->lock);
     402
     403        if (donor_data)
     404                async_put_client_data_by_hash(donor_hash);
     405        if (acceptor_data)
     406                async_put_client_data_by_hash(acceptor_hash);
     407        if (donor_file)
     408                _vfs_file_put(donor_data, donor_file);
     409        if (acceptor_file)
     410                _vfs_file_put(acceptor_data, acceptor_file);
     411
     412}
     413
     414int vfs_wait_handle_internal(void)
     415{
     416        vfs_client_data_t *vfs_data = VFS_DATA;
     417        int fd;
     418       
     419        fibril_mutex_lock(&vfs_data->lock);
     420        while (list_empty(&vfs_data->passed_handles))
     421                fibril_condvar_wait(&vfs_data->cv, &vfs_data->lock);
     422        link_t *lnk = list_first(&vfs_data->passed_handles);
     423        list_remove(lnk);
     424        fibril_mutex_unlock(&vfs_data->lock);
     425
     426        vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
     427        fd = bh->handle;
     428        free(bh);
     429
     430        return fd;
    305431}
    306432
  • uspace/srv/vfs/vfs_lookup.c

    ref7052ec r42a619b  
    201201}
    202202
    203 /** Perform a node open operation.
    204  *
    205  * @return EOK on success or an error code from errno.h.
    206  *
    207  */
    208 int vfs_open_node_internal(vfs_lookup_res_t *result)
    209 {
    210         async_exch_t *exch = vfs_exchange_grab(result->triplet.fs_handle);
    211        
    212         ipc_call_t answer;
    213         aid_t req = async_send_2(exch, VFS_OUT_OPEN_NODE,
    214             (sysarg_t) result->triplet.service_id,
    215             (sysarg_t) result->triplet.index, &answer);
    216        
    217         sysarg_t rc;
    218         async_wait_for(req, &rc);
    219         vfs_exchange_release(exch);
    220        
    221         if (rc == EOK) {
    222                 result->size =
    223                     MERGE_LOUP32(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer));
    224                 result->lnkcnt = (unsigned int) IPC_GET_ARG3(answer);
    225                 if (IPC_GET_ARG4(answer) & L_FILE)
    226                         result->type = VFS_NODE_FILE;
    227                 else if (IPC_GET_ARG4(answer) & L_DIRECTORY)
    228                         result->type = VFS_NODE_DIRECTORY;
    229                 else
    230                         result->type = VFS_NODE_UNKNOWN;
    231         }
    232        
    233         return rc;
    234 }
    235 
    236203/**
    237204 * @}
  • uspace/srv/vfs/vfs_node.c

    ref7052ec r42a619b  
    293293}
    294294
     295
     296/** Perform a remote node open operation.
     297 *
     298 * @return EOK on success or an error code from errno.h.
     299 *
     300 */
     301int vfs_open_node_remote(vfs_node_t *node)
     302{
     303        async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
     304       
     305        ipc_call_t answer;
     306        aid_t req = async_send_2(exch, VFS_OUT_OPEN_NODE,
     307            (sysarg_t) node->service_id, (sysarg_t) node->index, &answer);
     308       
     309        vfs_exchange_release(exch);
     310
     311        sysarg_t rc;
     312        async_wait_for(req, &rc);
     313       
     314        return rc;
     315}
     316
    295317/**
    296318 * @}
  • uspace/srv/vfs/vfs_ops.c

    ref7052ec r42a619b  
    618618}
    619619
    620 void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
    621 {
    622         // FIXME: check for sanity of the supplied fs, dev and index
    623        
    624         /*
    625          * The interface is open_node(fs, dev, index, oflag).
    626          */
    627         vfs_lookup_res_t lr;
    628        
    629         lr.triplet.fs_handle = IPC_GET_ARG1(*request);
    630         lr.triplet.service_id = IPC_GET_ARG2(*request);
    631         lr.triplet.index = IPC_GET_ARG3(*request);
    632         int oflag = IPC_GET_ARG4(*request);
    633        
    634         fibril_rwlock_read_lock(&namespace_rwlock);
    635        
    636         int rc = vfs_open_node_internal(&lr);
    637         if (rc != EOK) {
    638                 fibril_rwlock_read_unlock(&namespace_rwlock);
    639                 async_answer_0(rid, rc);
    640                 return;
    641         }
    642        
    643         vfs_node_t *node = vfs_node_get(&lr);
    644         fibril_rwlock_read_unlock(&namespace_rwlock);
    645        
    646         /* Truncate the file if requested and if necessary. */
    647         if (oflag & O_TRUNC) {
    648                 fibril_rwlock_write_lock(&node->contents_rwlock);
    649                 if (node->size) {
    650                         rc = vfs_truncate_internal(node->fs_handle,
    651                             node->service_id, node->index, 0);
    652                         if (rc) {
    653                                 fibril_rwlock_write_unlock(&node->contents_rwlock);
    654                                 vfs_node_put(node);
    655                                 async_answer_0(rid, rc);
    656                                 return;
    657                         }
    658                         node->size = 0;
    659                 }
    660                 fibril_rwlock_write_unlock(&node->contents_rwlock);
    661         }
    662        
    663         /*
    664          * Get ourselves a file descriptor and the corresponding vfs_file_t
    665          * structure.
    666          */
    667         int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    668         if (fd < 0) {
    669                 vfs_node_put(node);
    670                 async_answer_0(rid, fd);
    671                 return;
    672         }
    673         vfs_file_t *file = vfs_file_get(fd);
    674         file->node = node;
    675         if (oflag & O_APPEND)
    676                 file->append = true;
    677        
    678         /*
    679          * The following increase in reference count is for the fact that the
    680          * file is being opened and that a file structure is pointing to it.
    681          * It is necessary so that the file will not disappear when
    682          * vfs_node_put() is called. The reference will be dropped by the
    683          * respective VFS_IN_CLOSE.
    684          */
    685         vfs_node_addref(node);
    686         vfs_node_put(node);
    687         vfs_file_put(file);
    688        
    689         /* Success! Return the new file descriptor to the client. */
    690         async_answer_1(rid, EOK, fd);
    691 }
    692 
    693620void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
    694621{
     
    13491276}
    13501277
     1278void vfs_wait_handle(ipc_callid_t rid, ipc_call_t *request)
     1279{
     1280        int fd = vfs_wait_handle_internal();
     1281        async_answer_1(rid, EOK, fd);
     1282}
     1283
    13511284/**
    13521285 * @}
Note: See TracChangeset for help on using the changeset viewer.