1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef POWERMAN_H
24 #define POWERMAN_H
25 
26 #include "backends/platform/psp/thread.h"
27 #include "common/singleton.h"
28 #include "common/list.h"
29 
30 #include "engines/engine.h"  // for PauseToken
31 
32 /*
33  *  Implement this class (interface) if you want to use PowerManager's suspend callback functionality
34  *
35  */
36 class Suspendable {
37 public:
~Suspendable()38 	virtual ~Suspendable() {}
39 	virtual int suspend() = 0;
40 	virtual int resume() = 0;
41 };
42 
43 /******************************************************************************************************
44 *
45 *  This class will call a Suspendable when the PSP goes to suspend/resumes. It also provides the ability to block
46 *  a thread when the PSP is going to suspend/suspending, and to wake it up when the PSP is resumed.
47 *	This ability is very useful for managing the PSPIoStream class, but may be found useful by other classes as well.
48 *
49 *******************************************************************************************************/
50 class PowerManager: public Common::Singleton<PowerManager> {
51 
52 public:
53 	int blockOnSuspend();								/* block if suspending */
54 	bool beginCriticalSection();	/* Use a critical section to block (if suspend was already pressed) */
55 	void endCriticalSection();							/* and to prevent the PSP from suspending in a particular section */
56 	bool registerForSuspend(Suspendable *item);			/* register to be called to suspend/resume */
57 	bool unregisterForSuspend(Suspendable *item);		/* remove from suspend/resume list */
58 	void suspend();									/* callback to have all items in list suspend */
59 	void resume();									/* callback to have all items in list resume */
60 	// Functions for pausing the engine
61 	void pollPauseEngine();							/* Poll whether the engine should be paused */
62 
63 	enum {
64 		Error = -1,
65 		NotBlocked = 0,
66 		Blocked = 1
67 	};
68 
69 	enum PauseState {
70 		UNPAUSED = 0,
71 		PAUSING,
72 		PAUSED
73 	};
74 
75 private:
76 	friend class Common::Singleton<PowerManager>;
77 	PowerManager();
78 	~PowerManager();
79 
80 	Common::List<Suspendable *> _suspendList;		// list to register in
81 
82 	volatile bool _pauseFlag;						// For pausing, which is before suspending
83 	volatile bool _pauseFlagOld;					// Save the last state of the flag while polling
84 	volatile PauseState _pauseClientState;			// Pause state of the target
85 	PauseToken _pauseToken;
86 
87 	volatile bool _suspendFlag;						// protected variable
88 	PspMutex _flagMutex;							// mutex to access access flag
89 	PspMutex _listMutex;							// mutex to access Suspendable list
90 	PspCondition _threadSleep;						// signal to synchronize accessing threads
91 	PspCondition _pmSleep;							// signal to wake up the PM from a critical section
92 	volatile int _criticalCounter;					// Counter of how many threads are in a critical section
93 	int _error;										// error code - PM can't talk to us. For debugging
94 	volatile int _PMStatus;							// What the PM is doing. for debugging
95 
96 	// States for PM to be in (used for debugging)
97 	enum PMState {
98 		kInitDone = 1,
99 		kDestroyPM = 2,
100 		kWaitForClientPause = 3,
101 		kWaitForClientToFinishPausing = 4,
102 		kGettingFlagMutexSuspend = 5,
103 		kGotFlagMutexSuspend = 6,
104 		kWaitCritSectionSuspend = 7,
105 		kDoneWaitingCritSectionSuspend = 8,
106 		kGettingListMutexSuspend = 9,
107 		kIteratingListSuspend = 10,
108 		kDoneIteratingListSuspend = 11,
109 		kDoneSuspend = 12,
110 		kDonePowerUnlock,
111 		kBeginResume,
112 		kCheckingPauseFlag,
113 		kGettingListMutexResume,
114 		kIteratingListResume,
115 		kDoneIteratingListResume,
116 		kGettingFlagMutexResume,
117 		kGotFlagMutexResume,
118 		kSignalSuspendedThreadsResume,
119 		kDoneSignallingSuspendedThreadsResume,
120 		kDoneResume
121 	};
122 
123 	volatile int _listCounter;						/* How many people are in the list - just for debugging */
124 
125 	void debugPM();									/* print info about the PM */
126 
127 public:
getPMStatus()128 	int getPMStatus() const { return _PMStatus; }
129 
130 };
131 
132 // For easy access
133 #define PowerMan	PowerManager::instance()
134 
135 #endif /* POWERMAN_H */
136