Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/thread/src/mac/safe.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 6.1 KB
Line 
1// (C) Copyright Mac Murrett 2001.
2// Use, modification and distribution are subject to the
3// Boost Software License, Version 1.0. (See accompanying file
4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6// See http://www.boost.org for most recent version.
7
8#include <DriverServices.h>
9#include <Events.h>
10#include <Multiprocessing.h>
11#include <Threads.h>
12
13#include <boost/bind.hpp>
14#include <boost/function.hpp>
15
16#include <boost/thread/detail/force_cast.hpp>
17#include <limits>
18#include "execution_context.hpp"
19
20
21using boost::detail::thread::force_cast;
22
23
24namespace boost {
25
26namespace threads {
27
28namespace mac {
29
30namespace detail {
31
32
33static OSStatus safe_wait(function<OSStatus, Duration> &rFunction, Duration lDuration);
34
35
36// we call WNE to allow tasks that own the resource the blue is waiting on system
37//    task time, in case they are blocked on an ST remote call (or a memory allocation
38//    for that matter).
39static void idle()
40{
41    if(at_st())
42    {
43        EventRecord sEvent;
44        bool bEvent = WaitNextEvent(0U, &sEvent, 0UL, NULL);
45    }
46}
47
48
49OSStatus safe_wait_on_semaphore(MPSemaphoreID pSemaphoreID, Duration lDuration)
50{
51    function<OSStatus, Duration> oWaitOnSemaphore;
52    oWaitOnSemaphore = bind(MPWaitOnSemaphore, pSemaphoreID, _1);
53    return(safe_wait(oWaitOnSemaphore, lDuration));
54}
55
56
57OSStatus safe_enter_critical_region(MPCriticalRegionID pCriticalRegionID, Duration lDuration, MPCriticalRegionID pCriticalRegionCriticalRegionID/* = kInvalidID*/)
58{
59    if(pCriticalRegionCriticalRegionID != kInvalidID)
60    {
61        if(at_mp())
62        {
63        // enter the critical region's critical region
64            OSStatus lStatus = noErr;
65            AbsoluteTime sExpiration;
66            if(lDuration != kDurationImmediate && lDuration != kDurationForever)
67            {
68                sExpiration = AddDurationToAbsolute(lDuration, UpTime());
69            }
70            lStatus = MPEnterCriticalRegion(pCriticalRegionCriticalRegionID, lDuration);
71            assert(lStatus == noErr || lStatus == kMPTimeoutErr);
72            if(lStatus == noErr)
73            {
74            // calculate a new duration
75                if(lDuration != kDurationImmediate && lDuration != kDurationForever)
76                {
77                // check if we have any time left
78                    AbsoluteTime sUpTime(UpTime());
79                    if(force_cast<uint64_t>(sExpiration) > force_cast<uint64_t>(sUpTime))
80                    {
81                    // reset our duration to our remaining time
82                        lDuration = AbsoluteDeltaToDuration(sExpiration, sUpTime);
83                    }
84                    else
85                    {
86                    // no time left
87                        lDuration = kDurationImmediate;
88                    }
89                }
90            // if we entered the critical region, exit it again
91                lStatus = MPExitCriticalRegion(pCriticalRegionCriticalRegionID);
92                assert(lStatus == noErr);
93            }
94            else
95            {
96            // otherwise, give up
97                return(lStatus);
98            }
99        }
100        else
101        {
102        // if we're at system task time, try to enter the critical region's critical
103        //    region until we succeed.  MP tasks will block on this until we let it go.
104            OSStatus lStatus;
105            do
106            {
107                lStatus = MPEnterCriticalRegion(pCriticalRegionCriticalRegionID, kDurationImmediate);
108            } while(lStatus == kMPTimeoutErr);
109            assert(lStatus == noErr);
110        }
111    }
112
113// try to enter the critical region
114    function<OSStatus, Duration> oEnterCriticalRegion;
115    oEnterCriticalRegion = bind(MPEnterCriticalRegion, pCriticalRegionID, _1);
116    OSStatus lStatus = safe_wait(oEnterCriticalRegion, lDuration);
117
118// if we entered the critical region's critical region to get the critical region,
119//    exit the critical region's critical region.
120    if(pCriticalRegionCriticalRegionID != kInvalidID && at_mp() == false)
121    {
122        lStatus = MPExitCriticalRegion(pCriticalRegionCriticalRegionID);
123        assert(lStatus == noErr);
124    }
125    return(lStatus);
126}
127
128OSStatus safe_wait_on_queue(MPQueueID pQueueID, void **pParam1, void **pParam2, void **pParam3, Duration lDuration)
129{
130    function<OSStatus, Duration> oWaitOnQueue;
131    oWaitOnQueue = bind(MPWaitOnQueue, pQueueID, pParam1, pParam2, pParam3, _1);
132    return(safe_wait(oWaitOnQueue, lDuration));
133}
134
135OSStatus safe_delay_until(AbsoluteTime *pWakeUpTime)
136{
137    if(execution_context() == k_eExecutionContextMPTask)
138    {
139        return(MPDelayUntil(pWakeUpTime));
140    }
141    else
142    {
143        uint64_t ullWakeUpTime = force_cast<uint64_t>(*pWakeUpTime);
144
145        while(force_cast<uint64_t>(UpTime()) < ullWakeUpTime)
146        {
147            idle();
148        }
149
150        return(noErr);
151    }
152}
153
154
155OSStatus safe_wait(function<OSStatus, Duration> &rFunction, Duration lDuration)
156{
157    if(execution_context() == k_eExecutionContextMPTask)
158    {
159        return(rFunction(lDuration));
160    }
161    else
162    {
163        uint64_t ullExpiration = 0ULL;
164
165    // get the expiration time in UpTime units
166        if(lDuration == kDurationForever)
167        {
168            ullExpiration = (::std::numeric_limits<uint64_t>::max)();
169        }
170        else if(lDuration == kDurationImmediate)
171        {
172            ullExpiration = force_cast<uint64_t>(UpTime());
173        }
174        else
175        {
176            AbsoluteTime sExpiration = AddDurationToAbsolute(lDuration, UpTime());
177            ullExpiration = force_cast<uint64_t>(sExpiration);
178        }
179
180        OSStatus lStatus;
181        bool bExpired = false;
182
183        do
184        {
185            lStatus = rFunction(kDurationImmediate);
186// mm - "if" #if 0'd out to allow task time to threads blocked on I/O
187#if 0
188            if(lStatus == kMPTimeoutErr)
189#endif
190            {
191                idle();
192            }
193            if(lDuration != kDurationForever)
194            {
195                bExpired = (force_cast<uint64_t>(UpTime()) < ullExpiration);
196            }
197        } while(lStatus == kMPTimeoutErr && bExpired == false);
198
199        return(lStatus);
200    }
201}
202
203
204} // namespace detail
205
206} // namespace mac
207
208} // namespace threads
209
210} // namespace boost
Note: See TracBrowser for help on using the repository browser.