summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/x11/VBoxClient/thread.cpp
blob: 4655cb7b14df87360a6552ce8c8e5c95be16e64c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/** @file
 *
 * VirtualBox additions client application: thread class.
 */

/*
 * Copyright (C) 2006-2011 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#include <VBox/log.h>

#include "thread.h"

/** Stop the thread using its stop method and get the exit value. */
int VBoxGuestThread::stop(RTMSINTERVAL cMillies, int *prc)
{
    int rc = VINF_SUCCESS;

    LogRelFlowFunc(("\n"));
    if (NIL_RTTHREAD == mSelf)  /* Assertion */
    {
        LogRelThisFunc(("Attempted to stop thread %s which is not running!\n", mName));
        return VERR_INTERNAL_ERROR;
    }
    mExit = true;
    mFunction->stop();
    if (0 != (mFlags & RTTHREADFLAGS_WAITABLE))
    {
        rc = RTThreadWait(mSelf, cMillies, prc);
        if (RT_SUCCESS(rc))
        {
            mSelf = NIL_RTTHREAD;
        }
        else
        {
            LogRelThisFunc(("Failed to stop thread %s!\n", mName));
        }
    }
    LogRelFlowFunc(("returning %Rrc\n", rc));
    return rc;
}

/** Destroy the class, stopping the thread if necessary. */
VBoxGuestThread::~VBoxGuestThread(void)
{
    LogRelFlowFunc(("\n"));
    if (NIL_RTTHREAD != mSelf)
    {
        LogRelThisFunc(("Warning!  Stopping thread %s, as it is still running!\n", mName));
        stop(2000, 0);
    }
    LogRelFlowFunc(("returning\n"));
}

/** Start the thread. */
int VBoxGuestThread::start(void)
{
    int rc = VINF_SUCCESS;

    LogRelFlowFunc(("returning\n"));
    if (NIL_RTTHREAD != mSelf)  /* Assertion */
    {
        LogRelThisFunc(("Attempted to start thread %s twice!\n", mName));
        return VERR_INTERNAL_ERROR;
    }
    mExit = false;
    rc = RTThreadCreate(&mSelf, threadFunction, reinterpret_cast<void *>(this),
                          mStack, mType, mFlags, mName);
    LogRelFlowFunc(("returning %Rrc\n", rc));
    return rc;
}

/** Yield the CPU */
bool VBoxGuestThread::yield(void)
{
    return RTThreadYield();
}

/** The "real" thread function for the VBox runtime. */
int VBoxGuestThread::threadFunction(RTTHREAD self, void *pvUser)
{
    int rc = VINF_SUCCESS;

    LogRelFlowFunc(("\n"));
    PSELF pSelf = reinterpret_cast<PSELF>(pvUser);
    pSelf->mRunning = true;
    rc = pSelf->mFunction->threadFunction(pSelf);
    pSelf->mRunning = false;
    LogRelFlowFunc(("returning %Rrc\n", rc));
    return rc;
}