aboutsummaryrefslogtreecommitdiff
path: root/engines/tony/sched.h
blob: a9868edad0bfd756d507c0e64f2d3bea52cde689 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * Data structures used by the process scheduler
 */

#ifndef TONY_SCHED_H
#define TONY_SCHED_H

#include "common/list.h"
#include "tony/coroutine.h"

namespace Tony {

// the size of process specific info
#define	PARAM_SIZE	32

// the maximum number of processes
#define	NUM_PROCESS	100
#define MAX_PROCESSES 100

#define INFINITE 0xffffffff
#define INVALID_PID_VALUE 0

typedef void (*CORO_ADDR)(CoroContext &, const void *);

/** process structure */
struct PROCESS {
	PROCESS *pNext;		///< pointer to next process in active or free list
	PROCESS *pPrevious;	///< pointer to previous process in active or free list

	CoroContext state;		///< the state of the coroutine
	CORO_ADDR  coroAddr;	///< the entry point of the coroutine

	int sleepTime;		///< number of scheduler cycles to sleep
	uint32 pid;			///< process ID
	bool waiting;		///< process is currently in a waiting state
	char param[PARAM_SIZE];	///< process specific info
};
typedef PROCESS *PPROCESS;

struct INT_CONTEXT;

/** Event structure */
struct EVENT {
	uint32 pid;
	bool manualReset;
	bool signalled;
};

/**
 * Create and manage "processes" (really coroutines).
 */
class Scheduler {
public:
	/** Pointer to a function of the form "void function(PPROCESS)" */
	typedef void (*VFPTRPP)(PROCESS *);

private:

	/** list of all processes */
	PROCESS *processList;

	/** active process list - also saves scheduler state */
	PROCESS *active;

	/** pointer to free process list */
	PROCESS *pFreeProcesses;

	/** the currently active process */
	PROCESS *pCurrent;

	/** Auto-incrementing process Id */
	int pidCounter;

	/** Event list */
	Common::List<EVENT *> _events;

#ifdef DEBUG
	// diagnostic process counters
	int numProcs;
	int maxProcs;

	void CheckStack();
#endif

	/**
	 * Called from killProcess() to enable other resources
	 * a process may be allocated to be released.
	 */
	VFPTRPP pRCfunction;

	PROCESS *getProcess(uint32 pid);
	EVENT *getEvent(uint32 pid);
public:

	Scheduler();
	~Scheduler();

	void reset();

	#ifdef	DEBUG
	void printStats();
	#endif

	void schedule();
	void rescheduleAll();
	void reschedule(PPROCESS pReSchedProc = NULL);
	void giveWay(PPROCESS pReSchedProc = NULL);
	void waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired = NULL);
	void waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, 
			uint32 duration, bool *expired = NULL);
	void Scheduler::sleep(CORO_PARAM, uint32 duration);

	uint32 createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam);
	uint32 createProcess(CORO_ADDR coroAddr, const void *pParam) {
		return createProcess(coroAddr, &pParam, sizeof(void *));
	}
	void killProcess(PROCESS *pKillProc);

	PROCESS *getCurrentProcess();
	int getCurrentPID() const;
	int killMatchingProcess(uint32 pidKill, int pidMask = -1);

	void setResourceCallback(VFPTRPP pFunc);

	/* Event methods */
	uint32 createEvent(bool bManualReset, bool bInitialState);
	void closeEvent(uint32 pidEvent);
	void setEvent(uint32 pidEvent);
	void resetEvent(uint32 pidEvent);
	void pulseEvent(uint32 pidEvent);
};

extern Scheduler *g_scheduler;	// FIXME: Temporary global var, to be used until everything has been OOifyied

} // End of namespace Tony

#endif		// TONY_SCHED_H