VirtualBox

Changeset 5817 in vbox for trunk/src/VBox/Additions/linux


Ignore:
Timestamp:
Nov 22, 2007 5:57:32 PM (17 years ago)
Author:
vboxsync
Message:

Additions (Linux): added support for waiting for host events from guest R3 and cleaned up the coding style in the kernel module slightly (to Linux kernel coding style)

Location:
trunk/src/VBox/Additions/linux/module
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/module/vboxmod.c

    r5606 r5817  
    3333MODULE_VERSION(VBOX_VERSION_STRING);
    3434#endif
     35
     36/*****************************************************************************
     37* Macros                                                                     *
     38*****************************************************************************/
     39
     40/* We need to define these ones here as they only exist in kernels 2.6 and up */
     41
     42#define __vbox_wait_event_interruptible_timeout(wq, condition, timeout, ret)   \
     43do {                                                                      \
     44        int __ret = 0;                                                    \
     45        if (!(condition)) {                                               \
     46          wait_queue_t __wait;                                            \
     47          unsigned long expire;                                           \
     48          init_waitqueue_entry(&__wait, current);                         \
     49                                                                          \
     50          expire = timeout + jiffies;                                     \
     51          add_wait_queue(&wq, &__wait);                                   \
     52          for (;;) {                                                      \
     53                  set_current_state(TASK_INTERRUPTIBLE);                  \
     54                  if (condition)                                          \
     55                          break;                                          \
     56                  if (jiffies > expire) {                                 \
     57                          ret = jiffies - expire;                         \
     58                          break;                                          \
     59                  }                                                       \
     60                  if (!signal_pending(current)) {                         \
     61                          schedule_timeout(timeout);                      \
     62                          continue;                                       \
     63                  }                                                       \
     64                  ret = -ERESTARTSYS;                                     \
     65                  break;                                                  \
     66          }                                                               \
     67          current->state = TASK_RUNNING;                                  \
     68          remove_wait_queue(&wq, &__wait);                                \
     69        }                                                                 \
     70} while (0)
     71
     72/*
     73   retval == 0; condition met; we're good.
     74   retval < 0; interrupted by signal.
     75   retval > 0; timed out.
     76*/
     77#define vbox_wait_event_interruptible_timeout(wq, condition, timeout)   \
     78({                                                                      \
     79        int __ret = 0;                                                  \
     80        if (!(condition))                                               \
     81                __vbox_wait_event_interruptible_timeout(wq, condition,  \
     82                                                timeout, __ret);        \
     83        __ret;                                                          \
     84})
     85
    3586
    3687/* This is called by our assert macros to find out whether we want
     
    100151                if (ASMAtomicCmpXchgU32(&hgcm_connections[i].client_id, client_id, 0)) {
    101152                        hgcm_connections[i].filp = filp;
     153#ifdef DEBUG
     154                        LogRelFunc(("Registered client ID %d, file pointer %p at position %d in the table.\n",
     155                                    client_id, filp, i));
     156#endif
    102157                        found = true;
    103158                }
     
    120175        for (i = 0; (i < MAX_HGCM_CONNECTIONS) && (false == found); ++i) {
    121176                if (hgcm_connections[i].client_id == client_id) {
     177#ifdef DEBUG
     178                        LogRelFunc(("Unregistered client ID %d, file pointer %p at position %d in the table.\n",
     179                                    client_id, hgcm_connections[i].filp, i));
     180#endif
     181                        hgcm_connections[i].filp = NULL;
    122182                        hgcm_connections[i].client_id = 0;
    123183                        found = true;
     
    144204        for (i = 0; i < MAX_HGCM_CONNECTIONS; ++i) {
    145205                if (hgcm_connections[i].filp == filp) {
     206                        VBoxGuestHGCMDisconnectInfo infoDisconnect;
     207#ifdef DEBUG
     208                        LogRelFunc(("Unregistered client ID %d, file pointer %p at position %d in the table.\n",
     209                                    hgcm_connections[i].client_id, filp, i));
     210#endif
     211                        infoDisconnect.u32ClientID = hgcm_connections[i].client_id;
     212                        vboxadd_cmc_call(vboxDev, IOCTL_VBOXGUEST_HGCM_DISCONNECT,
     213                                         &infoDisconnect);
     214                        hgcm_connections[i].filp = NULL;
    146215                        hgcm_connections[i].client_id = 0;
    147216                }
     
    171240}
    172241
    173 /**
    174  * Wait for event
    175  *
    176  */
    177 static void
    178 vboxadd_wait_for_event_helper (VBoxDevice *dev, long timeout,
    179                                uint32_t in_mask, uint32_t * out_mask)
    180 {
    181     BUG ();
    182 }
    183 
    184242static void
    185243vboxadd_wait_for_event (VBoxGuestWaitEventInfo * info)
    186244{
    187     long timeout;
    188 
    189     timeout = msecs_to_jiffies (info->u32TimeoutIn);
    190     vboxadd_wait_for_event_helper (vboxDev, timeout,
    191                                    info->u32EventMaskIn,
    192                                    &info->u32EventFlagsOut);
    193 }
    194 
     245    long timeleft;
     246    uint32_t cInterruptions = vboxDev->u32GuestInterruptions;
     247    uint32_t in_mask = info->u32EventMaskIn;
     248
     249    info->u32Result = VBOXGUEST_WAITEVENT_OK;
     250    timeleft = vbox_wait_event_interruptible_timeout
     251                            (vboxDev->eventq,
     252                                (vboxDev->u32Events & in_mask)
     253                             || (vboxDev->u32GuestInterruptions != cInterruptions),
     254                             msecs_to_jiffies (info->u32TimeoutIn));
     255    if (vboxDev->u32GuestInterruptions != cInterruptions) {
     256            info->u32Result = VBOXGUEST_WAITEVENT_INTERRUPTED;
     257    }
     258    if (timeleft < 0) {
     259            info->u32Result = VBOXGUEST_WAITEVENT_INTERRUPTED;
     260    }
     261    if (timeleft == 0) {
     262            info->u32Result = VBOXGUEST_WAITEVENT_TIMEOUT;
     263    }
     264    info->u32EventFlagsOut = vboxDev->u32Events & in_mask;
     265    vboxDev->u32Events &= ~in_mask;
     266}
     267
     268/**
     269 * IOCtl handler - wait for an event from the host.
     270 *
     271 * @returns Linux kernel return code
     272 * @param ptr User space pointer to a structure describing the event
     273 */
     274static int vboxadd_wait_event(void *ptr)
     275{
     276        int rc = 0;
     277        VBoxGuestWaitEventInfo info;
     278
     279        if (copy_from_user (&info, ptr, sizeof (info))) {
     280                LogRelFunc (("IOCTL_VBOXGUEST_WAITEVENT: can not get event info\n"));
     281                rc = -EFAULT;
     282        }
     283
     284        if (0 == rc) {
     285                vboxadd_wait_for_event (&info);
     286
     287                if (copy_to_user (ptr, &info, sizeof (info))) {
     288                        LogRelFunc (("IOCTL_VBOXGUEST_WAITEVENT: can not put out_mask\n"));
     289                        rc = -EFAULT;
     290                }
     291        }
     292        return 0;
     293}
    195294
    196295/**
     
    222321        } else {
    223322                /* Register that the connection is associated with this file pointer. */
     323                LogRelFunc(("Connected, client ID %u\n", info.u32ClientID));
    224324                rc = vboxadd_register_hgcm_connection(info.u32ClientID, filp);
    225325                if (0 != rc) {
     
    251351                         unsigned int cmd, unsigned long arg)
    252352{
    253     switch (cmd)
    254     {
     353        int rc = 0;
     354
     355        switch (cmd) {
    255356        case IOCTL_VBOXGUEST_WAITEVENT:
    256         {
    257             VBoxGuestWaitEventInfo info;
    258             char *ptr = (void *) arg;
    259 
    260             if (copy_from_user (&info, ptr, sizeof (info)))
    261             {
    262                 LogRelFunc (("IOCTL_VBOXGUEST_WAITEVENT: can not get event info\n"));
    263                 return -EFAULT;
    264             }
    265 
    266             vboxadd_wait_for_event (&info);
    267 
    268             ptr += offsetof (VBoxGuestWaitEventInfo, u32EventFlagsOut);
    269             if (put_user (info.u32EventFlagsOut, (uint32_t*)ptr))
    270             {
    271                 LogRelFunc (("IOCTL_VBOXGUEST_WAITEVENT: can not put out_mask\n"));
    272                 return -EFAULT;
    273             }
    274             return 0;
    275         }
    276 
    277         case IOCTL_VBOXGUEST_VMMREQUEST:
    278         {
     357                rc = vboxadd_wait_event((void *) arg);
     358                break;
     359
     360        case VBOXGUEST_IOCTL_WAITEVENT_INTERRUPT_ALL:
     361                ++vboxDev->u32GuestInterruptions;
     362                break;
     363
     364        case IOCTL_VBOXGUEST_VMMREQUEST: {
    279365            VMMDevRequestHeader reqHeader;
    280366            VMMDevRequestHeader *reqFull = NULL;
     
    283369            int rc;
    284370
    285             if (_IOC_SIZE(cmd) != sizeof(VMMDevRequestHeader))
    286             {
    287                 LogRelFunc(("IOCTL_VBOXGUEST_VMMREQUEST: invalid VMM request structure size: %d\n",
    288                          _IOC_SIZE(cmd)));
    289                 return -EINVAL;
    290             }
     371            AssertCompileSize(VMMDevRequestHeader, _IOC_SIZE(cmd));
    291372            if (copy_from_user(&reqHeader, (void*)arg, _IOC_SIZE(cmd)))
    292373            {
     
    361442
    362443        case IOCTL_VBOXGUEST_HGCM_CALL:
    363         {
    364444        /* This IOCTL allows the guest to make an HGCM call from user space.  The
    365445           OS-independant part of the Guest Additions already contain code for making an
     
    369449           passed to the call (which include pointers to other memory) inside the kernel's
    370450           address space. */
    371                 return vbox_ioctl_hgcm_call(arg, vboxDev);
    372         }
     451                rc = vbox_ioctl_hgcm_call(arg, vboxDev);
     452                break;
    373453
    374454        case IOCTL_VBOXGUEST_HGCM_CONNECT:
    375         {
    376                 return vboxadd_hgcm_connect(filp, arg);
    377         }
     455                rc = vboxadd_hgcm_connect(filp, arg);
     456                break;
    378457
    379458        default:
    380         {
    381             LogRelFunc(("unknown command: %x\n", cmd));
    382             return -EINVAL;
    383         }
    384     }
    385     return 0;
     459                LogRelFunc(("unknown command: %x\n", cmd));
     460                rc = -EINVAL;
     461                break;
     462        }
     463        return rc;
    386464}
    387465
  • trunk/src/VBox/Additions/linux/module/vboxmod.h

    r4071 r5817  
    5151    /** event synchronization */
    5252    wait_queue_head_t eventq;
     53    /** number of times the guest has interrupted the event loop -
     54        implemented as a counter to prevent one waiter swallowing the
     55        event. */
     56    uint32_t u32GuestInterruptions;
    5357};
    5458
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette