summaryrefslogtreecommitdiff
path: root/trunk/TAO/orbsvcs/orbsvcs/RTCosScheduling/RTCosScheduling_PCP_Manager.h
blob: ced96a1f72e0d9e4f03d7370f504e6a561e45f7e (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// -*- C++ -*-

//=============================================================================
/**
 *  @file   RTCosScheduling_PCP_Manager.h
 *
 *  $Id$
 *
 *  @author Matt Murphy <murphym@cs.uri.edu>
 *  @author based upon work by Greg Cooper
 *  @author University of Rhode Island
 */
//=============================================================================

#ifndef PCP_MANAGER_H
#define PCP_MANAGER_H
#include /**/ "ace/pre.h"

#include "ace/config-all.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/Shared_Memory_MM.h"
#include "ace/Map_T.h"
#include "ace/SString.h"
#include "tao/RTCORBA/RTCORBA.h"


#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4250)
#endif /* _MSC_VER */

#if defined (__BORLANDC__)
#pragma option push -w-rvl -w-rch -w-ccc -w-inl
#endif /* __BORLANDC__ */


TAO_BEGIN_VERSIONED_NAMESPACE_DECL

namespace TAO {


#if !defined (LOCK_ARRAY_SIZE)
  #define LOCK_ARRAY_SIZE 1024
#endif /* LOCK_ARRAY_SIZE */

#ifndef COS_SCHEDULING_CONTAINERS
#define COS_SCHEDULING_CONTAINERS
  /*
   * ResourceCeilingMap
   *
   * This typedef is used in the RTCORBA 1.0 Scheduling Service to
   * map names of resources on a server with priority ceilings.
   */
  typedef ACE_CString COS_SCHEDULING_RESOURCE_KEY;
  typedef int COS_SCHEDULING_RESOURCE_VALUE;

  typedef ACE_Map_Manager_Adapter<
    COS_SCHEDULING_RESOURCE_KEY,
    COS_SCHEDULING_RESOURCE_VALUE,
    ACE_Noop_Key_Generator<COS_SCHEDULING_RESOURCE_KEY> > CosSchedulingResourceMap;
#endif /* COS_SCHEDULING_CONTAINERS */


/**
* @class CosSchedulingLockList
*
* @brief    This program provides an abstract mechanism
* for the PCP_Manager class to store its lists of locks in
* shared memory.  It provides an efficient allocation and
* retrieval system and uses a pseudo-linked-list based on
* offsets (rather than absolute pointers) which allows it
* to work regardless of where it is mapped in a process's
* address space.  This means it can be used in a shared
* memory segment.
*
*/
struct CosSchedulingLockNode
{
  /// unique ID of the thread owning the lock
  int threadID_;

  /// the lock's priority ceiling
  int priority_ceiling_;

  /// the thread's original global priority
  int priority_;

  /// the thread's elevated priority
  int elevated_priority_;

  /// offset to the next lock in the list
  int next_offset_;

  /// Condition Variable to wait on Mutex
  ACE_SYNCH_CONDITION *condition_;

  /**
   * Translates the offset to the next lock
   * to a pointer and returns it
   */
  struct CosSchedulingLockNode *next();

  /**
   * Translates the pointer into an offset and
   * stores it in the structure
   */
  void next(const struct CosSchedulingLockNode *Next);

  /**
   * Copies the relevant fields while preserving those which should not be
   *modified
   */
  const CosSchedulingLockNode& operator=(const CosSchedulingLockNode& L);

};

class CosSchedulingLockList
{
  public:
  /**
   * Creates a CosSchedulingLockList structure using the storage in lock_array:
   * if Init is 1, the array is initialized to indicate that
   * none of the nodes are in use
   *
   * @param lock_array The shared memory space for the CosSchedulingLockList
   * @param size The size of the lock list
   * @param mutex the mutex that guards the CosSchedulingLockList
   */
  CosSchedulingLockList(CosSchedulingLockNode *lock_array,
                        const int size,
                        ACE_SYNCH_MUTEX *mutex);

  /**
   * Calls ACE_Thread::remove() on all conditions in the list;
   * should only be called when SchedInit terminates
   * (may not be necessary then)
   *
   * @param size the number of locks to destroy, starting at head
   */
  void destroy(const int size);

  /**
   * Adds L to the granted list, if space is available
   * (returns success); the list of granted locks is kept sorted
   * by priority-ceiling so that the highest ceiling can
   * be found quickly at the head
   *
   * @param L the CosSchedulingLockNode to add to the granted list.
   */
  int grant_lock(const CosSchedulingLockNode& L);

  /**
   * Adds L to the pending list, if space is available
   * (returns success); the list of pending locks is kept
   * sorted by priority so that the highest priority thread
   * awaiting a lock will be at the head; returns pointer to
   * condition variable upon success, NULL otherwise
   *
   * @param L The lock to add to the pending list.
   * @param mutex The mutex that guards the locks.
   */
  int defer_lock(const CosSchedulingLockNode& L,
    ACE_SYNCH_MUTEX &mutex);

  /**
   * Removes a node from the granted lock list whose threadID_
   * matches that of L, replacing L with the removed lock
   *
   * @param L released lock
   */
  int release_lock(CosSchedulingLockNode& L);

  /**
   * Removes the first node from the pending lock list,
   * replacing L with the removed lock
   *
   * @param L  Reference to the lock that is removed from pending
   */
  int remove_deferred_lock(CosSchedulingLockNode& L);

  /**
   * Returns a pointer to the node containing the highest ceiling (the
   * first node in the list of held locks)
   */
  CosSchedulingLockNode *highest_ceiling();


  /**
   * Returns a pointer to the node with the highest priority
   * (from the first node in the list of pending locks
   */
  CosSchedulingLockNode *highest_priority();

  private:

  /// A list of free locks
  CosSchedulingLockNode *free_;

  /// A list of Free locks
  CosSchedulingLockNode *granted_;

  /// A list of pending locks awaiting to be locked
  CosSchedulingLockNode *pending_;

};


/**
* @class PCP_Manager
*
* @brief PCP_Manager handles Priority Ceiling Control Protocol for the
* RTCORBA 1.0 ServerScheduler
* Each thread needs a PCP_Manager object: these are created by the
* PCP_Manager_Factory object, of which only one is needed per process
*
*/
class PCP_Manager
{
public:

  /**
   * Initializes a PCP_Manager object with the given lists, mutex,
   * condition variable, and priority mapper.
   *
   * @param locks A list of the locks to use in the PCP_Manager.
   * @param mutex The mutex to guard the locks.
   */
  PCP_Manager(CosSchedulingLockList *locks,
              ACE_SYNCH_MUTEX *mutex,
              const RTCORBA::Current_var current);

  /**
   * Acquires a lock on a shared resource using the
   * priority ceiling protocol
   *
   * @param PriorityCeiling The priority ceiling of the lock
   * @param priority The priority to lock at.
   */
  void lock(const int PriorityCeiling, const int Priority);

  /**
   * Releases a lock previously granted with lock()
   */
  void release_lock();

  /**
   * Returns the mThreadID data member
   */
  int threadID();

  private:
  int                   threadID_;  /// ID of thread owning this object
  CosSchedulingLockList *locks_;     /// combined list of locks
  ACE_SYNCH_MUTEX       *mutex_;     /// Mutex to guard lock list
  RTCORBA::Current_var  current_; /// reference to set local priority

};

/**
* @class PCP_Manager_Factory
*
* @brief Creates PCP_Managers.  Each process needs only one of
* these objects: it can create a PCP_Manager object for each
* thread as need arises.
*/
class PCP_Manager_Factory
{
public:

  /**
   * Initializes a PCP_Manager_Factory: each process should only
   * do this once.  It attaches a shared memory segment and retrieves
   * pointers to the granted and pending lock lists as well as
   * the mutex and condition variable.
   */
  PCP_Manager_Factory(const char *shared_file);

  ~PCP_Manager_Factory();

  /**
   * Creates a new PCP manager object using the lists and
   * synchronization objects found in shared memory.
   */
  PCP_Manager New_PCP_Manager(RTCORBA::Current_var current);

  private:
  CosSchedulingLockList *locks_;      /// lists of granted and pending locks
  ACE_SYNCH_MUTEX       mutex_;       /// The mutex for locking the lock list
  ACE_Shared_Memory_MM  mem_;         /// shared memory space
  char                  *shm_key_;    /// Key for shared memory
  CosSchedulingLockNode *lock_array_; /// The lock list

};

}

TAO_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
#include "orbsvcs/RTCosScheduling/RTCosScheduling_PCP_Manager.inl"
#endif /* __ACE_INLINE__ */


#if defined(_MSC_VER)
#pragma warning(pop)
#endif /* _MSC_VER */

#if defined (__BORLANDC__)
#pragma option pop
#endif /* __BORLANDC__ */

#include /**/ "ace/post.h"
#endif /* PCP_MANAGER_H */